/******************************************************************************* * Copyright (c) 2014, 2015 IBH SYSTEMS GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBH SYSTEMS GmbH - initial API and implementation *******************************************************************************/ package org.eclipse.packagedrone.repo.generator.p2; import java.io.IOException; import java.io.OutputStream; import java.util.EnumSet; import java.util.Map; import java.util.Set; import java.util.function.Consumer; import org.eclipse.packagedrone.repo.MetaKey; import org.eclipse.packagedrone.repo.XmlHelper; import org.eclipse.packagedrone.repo.channel.ArtifactInformation; import org.eclipse.packagedrone.repo.event.AddedEvent; import org.eclipse.packagedrone.repo.event.RemovedEvent; import org.eclipse.packagedrone.repo.utils.osgi.feature.FeatureInformation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; public final class Helper { private final static Logger logger = LoggerFactory.getLogger ( Helper.class ); private Helper () { } public static boolean changeOf ( final Object event, final Type first, final Type... rest ) { return changeOf ( event, EnumSet.of ( first, rest ) ); } public static boolean changeOf ( final Object event, final Set<Type> types ) { logger.debug ( "Check if we need to generate: {}", event ); if ( event instanceof AddedEvent ) { final AddedEvent context = (AddedEvent)event; if ( isChange ( context.getMetaData (), types ) ) { return true; } } else if ( event instanceof RemovedEvent ) { final RemovedEvent context = (RemovedEvent)event; if ( isChange ( context.getMetaData (), types ) ) { return true; } } return false; } private static boolean isChange ( final Map<MetaKey, String> metaData, final Set<Type> types ) { for ( final Type type : types ) { switch ( type ) { case BUNDLE: if ( isBundle ( metaData ) ) { return true; } break; case FEATURE: if ( isFeature ( metaData ) ) { return true; } break; } } return false; } public static boolean shouldRegenerateCategory ( final Object event ) { logger.debug ( "Check if we need to generate: {}", event ); final boolean result = changeOf ( event, Type.FEATURE ); logger.debug ( "Result: {}", result ); return result; } public static boolean shouldRegenerateFeature ( final Object event ) { logger.debug ( "Check if we need to generate: {}", event ); final boolean result = changeOf ( event, Type.BUNDLE ); logger.debug ( "Result: {}", result ); return result; } public static boolean isFeature ( final Map<MetaKey, String> metaData ) { final String classifier = metaData.get ( new MetaKey ( "osgi", "classifier" ) ); logger.debug ( "Artifact OSGi classifier: {}", classifier ); return "eclipse.feature".equals ( classifier ); } public static boolean isBundle ( final Map<MetaKey, String> metaData ) { final String classifier = metaData.get ( new MetaKey ( "osgi", "classifier" ) ); logger.debug ( "Artifact OSGi classifier: {}", classifier ); return "bundle".equals ( classifier ); } public static void addFeatureRequirement ( final Set<String> context, final Element requires, final ArtifactInformation a ) { final String id = a.getMetaData ().get ( new MetaKey ( "osgi", "name" ) ); if ( id == null ) { return; } final String version = a.getMetaData ().get ( new MetaKey ( "osgi", "version" ) ); final String key = String.format ( "%s.feature.group-%s", id, version ); if ( !context.add ( key ) ) { return; } final Element p = XmlHelper.addElement ( requires, "required" ); final FeatureInformation fi = FeatureInformation.fromJson ( a.getMetaData ().get ( FeatureInformation.META_KEY ) ); if ( fi != null ) { final String filter = fi.getQualifiers ().toFilterString (); if ( filter != null ) { XmlHelper.addElement ( p, "filter" ).setTextContent ( filter ); } } p.setAttribute ( "namespace", "org.eclipse.equinox.p2.iu" ); p.setAttribute ( "name", id + ".feature.group" ); p.setAttribute ( "range", String.format ( "[%1$s,%1$s]", version ) ); } public static void addBundleRequirement ( final Set<String> context, final Element requires, final ArtifactInformation a ) { final String id = a.getMetaData ().get ( new MetaKey ( "osgi", "name" ) ); if ( id == null ) { return; } final String version = a.getMetaData ().get ( new MetaKey ( "osgi", "version" ) ); final String key = String.format ( "%s.feature.group-%s", id, version ); if ( !context.add ( key ) ) { return; } final Element p = requires.getOwnerDocument ().createElement ( "required" ); requires.appendChild ( p ); p.setAttribute ( "namespace", "org.eclipse.equinox.p2.iu" ); p.setAttribute ( "name", id ); p.setAttribute ( "range", String.format ( "[%1$s,%1$s]", version ) ); } public static void createFragmentFile ( final OutputStream out, final Consumer<Element> unitsConsumer ) throws IOException { final XmlHelper xml = new XmlHelper (); final Document doc = xml.create (); final Element units = doc.createElement ( "units" ); doc.appendChild ( units ); unitsConsumer.accept ( units ); XmlHelper.fixSize ( units ); try { xml.write ( doc, out ); } catch ( final IOException e ) { throw e; } catch ( final Exception e ) { throw new IOException ( e ); } } public static void addProperty ( final Element parent, final String key, final String value ) { if ( value == null ) { return; } final Element p = XmlHelper.addElement ( parent, "property" ); p.setAttribute ( "name", key ); p.setAttribute ( "value", value ); } public static void createCategoryUnit ( final Element units, final String id, final String label, final String description, final String version, final Consumer<Element> unitConsumer ) { final Element unit = XmlHelper.addElement ( units, "unit" ); unit.setAttribute ( "id", id ); unit.setAttribute ( "version", version ); final Element props = XmlHelper.addElement ( unit, "properties" ); addProperty ( props, "org.eclipse.equinox.p2.name", label ); addProperty ( props, "org.eclipse.equinox.p2.description", description ); addProperty ( props, "org.eclipse.equinox.p2.type.category", "true" ); XmlHelper.fixSize ( props ); { final Element provs = XmlHelper.addElement ( unit, "provides" ); final Element p = XmlHelper.addElement ( provs, "provided" ); p.setAttribute ( "namespace", "org.eclipse.equinox.p2.iu" ); p.setAttribute ( "name", id ); p.setAttribute ( "version", version ); XmlHelper.fixSize ( provs ); } unitConsumer.accept ( unit ); { final Element t = XmlHelper.addElement ( unit, "touchpoint" ); t.setAttribute ( "id", "null" ); t.setAttribute ( "version", "0.0.0" ); } } public static String makeDefaultVersion () { return String.format ( "0.0.0.0--%x", System.currentTimeMillis () ); } }