org.eclipse.tycho.extras.sourcefeature.SourceFeatureMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.tycho.extras.sourcefeature.SourceFeatureMojo.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Sonatype Inc. and others.
 * 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:
 *    Sonatype Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.tycho.extras.sourcefeature;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.maven.archiver.MavenArchiveConfiguration;
import org.apache.maven.archiver.MavenArchiver;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.codehaus.plexus.archiver.jar.JarArchiver;
import org.codehaus.plexus.archiver.util.DefaultFileSet;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.logging.Logger;
import org.eclipse.sisu.equinox.EquinoxServiceFactory;
import org.eclipse.tycho.ArtifactKey;
import org.eclipse.tycho.artifacts.TargetPlatform;
import org.eclipse.tycho.core.TychoProject;
import org.eclipse.tycho.core.osgitools.DebugUtils;
import org.eclipse.tycho.model.Feature;
import org.eclipse.tycho.model.FeatureRef;
import org.eclipse.tycho.model.PluginRef;
import org.eclipse.tycho.osgi.adapters.MavenLoggerAdapter;
import org.eclipse.tycho.p2.resolver.facade.P2ResolutionResult;
import org.eclipse.tycho.p2.resolver.facade.P2ResolutionResult.Entry;
import org.eclipse.tycho.p2.resolver.facade.P2Resolver;
import org.eclipse.tycho.p2.resolver.facade.P2ResolverFactory;

import de.pdark.decentxml.Document;
import de.pdark.decentxml.Element;
import de.pdark.decentxml.XMLDeclaration;

/**
 * @goal source-feature
 */
public class SourceFeatureMojo extends AbstractMojo {

    public static final String FEATURE_TEMPLATE_DIR = "sourceTemplateFeature";

    public static final String SOURCES_FEATURE_CLASSIFIER = "sources-feature";

    /**
     * @parameter default-value="${project}"
     */
    private MavenProject project;

    /**
     * Bundles and features that do not have corresponding sources.
     * 
     * @parameter
     */
    @SuppressWarnings("unused")
    private PlexusConfiguration excludes;

    /**
     * @parameter default-value="${session}"
     */
    private MavenSession session;

    private final Set<String> excludedPlugins = new HashSet<String>();

    private final Set<String> excludedFeatures = new HashSet<String>();

    /**
     * @parameter
     */
    private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();

    /**
     * @component role="org.codehaus.plexus.archiver.Archiver" roleHint="jar"
     */
    private JarArchiver jarArchiver;

    /**
     * @component
     */
    private MavenProjectHelper projectHelper;

    /**
     * @component role="org.eclipse.tycho.core.TychoProject"
     */
    private Map<String, TychoProject> projectTypes;

    /** @component */
    private EquinoxServiceFactory equinox;

    /** @component */
    private Logger logger;

    public void execute() throws MojoExecutionException, MojoFailureException {
        File template = new File(project.getBasedir(), FEATURE_TEMPLATE_DIR);

        if (!ArtifactKey.TYPE_ECLIPSE_FEATURE.equals(project.getPackaging()) || !template.isDirectory()) {
            return;
        }

        File outputJarFile = getOutputJarFile();

        TychoProject tychoProject = projectTypes.get(project.getPackaging());

        if (tychoProject == null) {
            throw new MojoExecutionException("Is not a supported tycho project " + project);
        }

        MavenArchiver archiver = new MavenArchiver();
        archiver.setArchiver(jarArchiver);
        archiver.setOutputFile(outputJarFile);

        try {
            File sourceFeatireDir = getSourcesFeatureDir(project);
            File featureXml = new File(sourceFeatireDir, Feature.FEATURE_XML);

            TargetPlatform targetPlatform = tychoProject.getTargetPlatform(project);

            final Feature sourceFeature = getSourceFeature(project, targetPlatform);

            Feature.write(sourceFeature, featureXml);

            DefaultFileSet mainFileSet = new DefaultFileSet();
            mainFileSet.setDirectory(template);

            archiver.getArchiver().addFileSet(mainFileSet);

            archiver.getArchiver().addFile(featureXml, Feature.FEATURE_XML);

            archiver.createArchive(project, archive);

            projectHelper.attachArtifact(project, outputJarFile, SOURCES_FEATURE_CLASSIFIER);
        } catch (MojoExecutionException e) {
            throw e;
        } catch (Exception e) {
            throw new MojoExecutionException("Could not package source feature jar", e);
        }
    }

    static File getSourcesFeatureDir(MavenProject project) {
        File dir = new File(project.getBuild().getDirectory(), SOURCES_FEATURE_CLASSIFIER);
        dir.mkdirs();
        new File(dir, "p2.inf").delete();
        return dir;
    }

    private Feature getSourceFeature(MavenProject project, TargetPlatform targetPlatform)
            throws IOException, MojoExecutionException {
        P2ResolverFactory factory = equinox.getService(P2ResolverFactory.class);
        P2Resolver p2 = factory
                .createResolver(new MavenLoggerAdapter(logger, DebugUtils.isDebugEnabled(session, project)));

        Feature feature = Feature.read(new File(project.getBuild().getDirectory(), "feature.xml"));

        Document document = new Document();
        document.setRootNode(new Element("feature"));
        document.setXmlDeclaration(new XMLDeclaration("1.0", "UTF-8"));
        Feature sourceFeature = new Feature(document);
        sourceFeature.setId(feature.getId() + ".source");
        sourceFeature.setVersion(feature.getVersion());

        // make sure versions of sources and binary features match
        FeatureRef binaryRef = new FeatureRef(new Element("includes"));
        binaryRef.setId(feature.getId());
        binaryRef.setVersion(feature.getVersion());
        sourceFeature.addFeatureRef(binaryRef);

        List<PluginRef> missingSourcePlugins = new ArrayList<PluginRef>();
        List<FeatureRef> missingSourceFeatures = new ArrayList<FeatureRef>();

        // include available source bundles
        for (PluginRef pluginRef : feature.getPlugins()) {

            if (excludedPlugins.contains(pluginRef.getId())) {
                continue;
            }

            // version is expected to be fully expanded at this point
            P2ResolutionResult result = p2.resolveInstallableUnit(targetPlatform, pluginRef.getId() + ".source",
                    pluginRef.getVersion());
            if (result.getArtifacts().size() == 1) {
                Entry sourceBundle = result.getArtifacts().iterator().next();

                PluginRef sourceRef = new PluginRef("plugin");
                sourceRef.setId(sourceBundle.getId());
                sourceRef.setVersion(sourceBundle.getVersion());
                sourceRef.setDownloadSide(0);
                sourceRef.setInstallSize(0);
                if (pluginRef.getOs() != null) {
                    sourceRef.setOs(pluginRef.getOs());
                }
                if (pluginRef.getWs() != null) {
                    sourceRef.setWs(pluginRef.getWs());
                }
                if (pluginRef.getArch() != null) {
                    sourceRef.setArch(pluginRef.getArch());
                }
                sourceRef.setUnpack(false);

                sourceFeature.addPlugin(sourceRef);
            } else {
                missingSourcePlugins.add(pluginRef);
            }
        }

        // include available source features
        for (FeatureRef featureRef : feature.getIncludedFeatures()) {

            if (excludedFeatures.contains(featureRef.getId())) {
                continue;
            }

            String sourceId = featureRef.getId() + ".source";

            P2ResolutionResult result = p2.resolveInstallableUnit(targetPlatform, sourceId + ".feature.group",
                    featureRef.getVersion());
            if (result.getArtifacts().size() == 1) {
                Entry entry = result.getArtifacts().iterator().next();

                FeatureRef sourceRef = new FeatureRef(new Element("includes"));
                sourceRef.setId(sourceId);
                sourceRef.setVersion(entry.getVersion());
                sourceFeature.addFeatureRef(sourceRef);
            } else {
                missingSourceFeatures.add(featureRef);
            }
        }

        if (!missingSourceFeatures.isEmpty() || !missingSourcePlugins.isEmpty()) {
            StringBuilder sb = new StringBuilder();

            sb.append("Could not generate source feature for project " + project.toString()).append("\n");

            if (!missingSourcePlugins.isEmpty()) {
                sb.append("    Missing sources for plugins " + missingSourcePlugins.toString()).append("\n");
            }

            if (!missingSourceFeatures.isEmpty()) {
                sb.append("    Missing sources for features " + missingSourceFeatures.toString()).append("\n");
            }

            throw new MojoExecutionException(sb.toString());
        }

        return sourceFeature;
    }

    protected File getOutputJarFile() {
        String filename = project.getArtifactId() + "-" + SOURCES_FEATURE_CLASSIFIER + ".jar";
        return new File(project.getBuild().getDirectory(), filename);
    }

    public void setExcludes(PlexusConfiguration excludes) {
        for (PlexusConfiguration plugin : excludes.getChildren("plugin")) {
            String id = getAttribute(plugin, "id");
            if (id != null) {
                excludedPlugins.add(id);
            }
        }
        for (PlexusConfiguration plugin : excludes.getChildren("feature")) {
            String id = getAttribute(plugin, "id");
            if (id != null) {
                excludedFeatures.add(id);
            }
        }
    }

    private String getAttribute(PlexusConfiguration dom, String attrName) {
        String attr = dom.getAttribute(attrName);
        if (attr == null) {
            return null;
        }
        attr = attr.trim();
        if (attr.length() == 0) {
            return null;
        }
        return attr;
    }
}