org.sourcepit.b2.p2.MavenDependenciesSiteGenerator.java Source code

Java tutorial

Introduction

Here is the source code for org.sourcepit.b2.p2.MavenDependenciesSiteGenerator.java

Source

/*
 * Copyright 2014 Bernd Vogt and others.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.sourcepit.b2.p2;

import static com.google.common.collect.Collections2.filter;
import static org.sourcepit.b2.internal.maven.util.MavenDepenenciesUtils.removeDependencies;
import static org.sourcepit.common.utils.lang.Exceptions.pipe;
import static org.sourcepit.osgifier.maven.p2.BundleSelectorUtils.selectBundles;

import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.apache.maven.model.Repository;
import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.project.MavenProject;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.sourcepit.b2.files.ModuleDirectory;
import org.sourcepit.b2.generator.GeneratorType;
import org.sourcepit.b2.generator.IB2GenerationParticipant;
import org.sourcepit.b2.internal.generator.AbstractPomGenerator;
import org.sourcepit.b2.internal.generator.ITemplates;
import org.sourcepit.b2.model.interpolation.internal.module.ResolutionContextResolver;
import org.sourcepit.b2.model.interpolation.layout.IInterpolationLayout;
import org.sourcepit.b2.model.interpolation.layout.LayoutManager;
import org.sourcepit.b2.model.interpolation.module.ModuleInterpolatorLifecycleParticipant;
import org.sourcepit.b2.model.module.AbstractFacet;
import org.sourcepit.b2.model.module.AbstractModule;
import org.sourcepit.b2.model.module.ModuleModelFactory;
import org.sourcepit.b2.model.module.PluginProject;
import org.sourcepit.b2.model.module.PluginsFacet;
import org.sourcepit.common.maven.model.ArtifactKey;
import org.sourcepit.common.maven.model.MavenArtifact;
import org.sourcepit.common.modeling.Annotatable;
import org.sourcepit.common.utils.lang.ThrowablePipe;
import org.sourcepit.common.utils.path.PathMatcher;
import org.sourcepit.common.utils.props.PropertiesSource;
import org.sourcepit.maven.dependency.model.DependencyModel;
import org.sourcepit.osgifier.core.model.context.BundleCandidate;
import org.sourcepit.osgifier.core.model.context.BundleReference;
import org.sourcepit.osgifier.core.model.context.OsgifierContext;
import org.sourcepit.osgifier.maven.p2.AbstractBundleTreeSelector;
import org.sourcepit.osgifier.maven.p2.BundleSelector;
import org.sourcepit.osgifier.maven.p2.P2UpdateSiteGenerator;

import com.google.common.base.Predicate;
import com.google.common.base.Strings;

@Named
public class MavenDependenciesSiteGenerator extends AbstractPomGenerator
        implements ModuleInterpolatorLifecycleParticipant, IB2GenerationParticipant {

    private Predicate<Dependency> JARS = new Predicate<Dependency>() {
        public boolean apply(Dependency dependency) {
            return "jar".equals(dependency.getType());
        }
    };

    @Inject
    private LegacySupport legacySupport;

    @Inject
    private P2UpdateSiteGenerator updateSiteGenerator;

    @Inject
    private LayoutManager layoutManager;

    public void preInterpolation(AbstractModule module, final PropertiesSource moduleProperties) {
        final MavenSession session = legacySupport.getSession();
        final MavenProject project = session.getCurrentProject();

        final List<Dependency> dependencies = new ArrayList<Dependency>(filter(project.getDependencies(), JARS));
        if (!dependencies.isEmpty()) {
            final IInterpolationLayout layout = layoutManager.getLayout(module.getLayoutId());
            final File siteDir = new File(layout.pathOfMetaDataFile(module, "maven-dependencies"));

            final String repositoryName = "maven-dependencies@" + project.getArtifactId();
            final List<ArtifactRepository> remoteRepositories = project.getRemoteArtifactRepositories();
            final ArtifactRepository localRepository = session.getLocalRepository();

            final Date startTime = session.getStartTime();

            final String pattern = moduleProperties.get("osgifier.updateSiteBundles");
            final PathMatcher bundleMatcher = pattern == null ? null : PathMatcher.parsePackagePatterns(pattern);

            BundleSelector bundleSelector = new AbstractBundleTreeSelector() {
                @Override
                public Collection<BundleCandidate> selectRootBundles(OsgifierContext bundleContext) {
                    final DependencyModel dependencyModel = bundleContext.getExtension(DependencyModel.class);

                    final Map<ArtifactKey, BundleCandidate> artifactKeyToBundle = new HashMap<ArtifactKey, BundleCandidate>();
                    for (BundleCandidate bundle : bundleContext.getBundles()) {
                        artifactKeyToBundle.put(getArtifactKey(bundle), bundle);
                    }

                    final List<BundleCandidate> rootBundles = new ArrayList<BundleCandidate>();
                    for (MavenArtifact artifact : dependencyModel.getRootArtifacts()) {
                        final BundleCandidate rootBundle = artifactKeyToBundle.get(artifact.getArtifactKey());
                        if (rootBundle != null && select(rootBundle)) {
                            rootBundles.add(rootBundle);
                        }
                    }
                    return rootBundles;
                }

                private ArtifactKey getArtifactKey(BundleCandidate bundle) {
                    return bundle.getExtension(MavenArtifact.class).getArtifactKey();
                }

                @Override
                public boolean select(Stack<BundleCandidate> path, BundleReference reference) {
                    return !reference.isOptional() && super.select(path, reference);
                }

                @Override
                protected boolean select(BundleCandidate bundle) {
                    return bundleMatcher == null || bundleMatcher.isMatch(bundle.getSymbolicName());
                }
            };

            final OsgifierContext bundleContext = updateSiteGenerator.generateUpdateSite(siteDir, dependencies,
                    true, remoteRepositories, localRepository, repositoryName, moduleProperties, startTime,
                    bundleSelector);

            try {
                module.setAnnotationData("b2.mavenDependencies", "repositoryURL",
                        siteDir.toURI().toURL().toExternalForm());
            } catch (MalformedURLException e) {
                throw pipe(e);
            }
            module.setAnnotationData("b2.mavenDependencies", "repositoryName", repositoryName);

            final Collection<BundleCandidate> selectedBundles = new LinkedHashSet<BundleCandidate>();
            selectBundles(selectedBundles, bundleContext, bundleSelector);
            interpolatePlugins(module, moduleProperties, selectedBundles);
        }
    }

    private static void interpolatePlugins(final AbstractModule module, PropertiesSource moduleProperties,
            Collection<BundleCandidate> selectedBundles) {
        ModuleModelFactory eFactory = ModuleModelFactory.eINSTANCE;

        PluginsFacet pluginsFacet = eFactory.createPluginsFacet();
        pluginsFacet.setName(getFacetName(moduleProperties));
        pluginsFacet.setDerived(true);

        PluginsFacet sourcesFacet = eFactory.createPluginsFacet();
        sourcesFacet.setName(getSourcesFacetName(moduleProperties));
        sourcesFacet.setDerived(true);

        if (pluginsFacet.getName().equals(sourcesFacet.getName())) {
            sourcesFacet = pluginsFacet;
        }

        for (BundleCandidate bundle : selectedBundles) {
            PluginProject pluginProject = eFactory.createPluginProject();
            pluginProject.setDerived(true);
            pluginProject.setId(bundle.getSymbolicName());
            pluginProject.setVersion(bundle.getVersion().toFullString());
            pluginProject.setBundleManifest(EcoreUtil.copy(bundle.getManifest()));

            if (pluginProject.getBundleManifest().getHeader("Eclipse-SourceBundle") == null) {
                pluginsFacet.getProjects().add(pluginProject);
            } else {
                sourcesFacet.getProjects().add(pluginProject);
            }
        }

        if (!pluginsFacet.getProjects().isEmpty()) {
            module.getFacets().add(pluginsFacet);
        }

        if (sourcesFacet != pluginsFacet && !sourcesFacet.getProjects().isEmpty()) {
            module.getFacets().add(sourcesFacet);
        }
    }

    private static String getSourcesFacetName(PropertiesSource moduleProperties) {
        final String sourcesClassifier = moduleProperties.get("b2.featuresSourceClassifier", "sources");
        final StringBuilder sb = new StringBuilder();
        sb.append(getFacetName(moduleProperties));
        if (!Strings.isNullOrEmpty(sourcesClassifier)) {
            sb.append('.');
            sb.append(sourcesClassifier);
        }
        return sb.toString();
    }

    private static String getFacetName(PropertiesSource moduleProperties) {
        return moduleProperties.get("b2.mavenDependenciesFacetName", "dependencies");
    }

    @Inject
    private ResolutionContextResolver contextResolver;

    public void postInterpolation(AbstractModule module, PropertiesSource moduleProperties, ThrowablePipe errors) {
        final String repositoryURL = module.getAnnotationData("b2.mavenDependencies", "repositoryURL");
        if (repositoryURL != null) {
            AbstractFacet facet = module.getFacetByName(getFacetName(moduleProperties));
            if (facet != null) {
                module.getFacets().remove(facet);
            }
            facet = module.getFacetByName(getSourcesFacetName(moduleProperties));
            if (facet != null) {
                module.getFacets().remove(facet);
            }
        }
    }

    @Override
    protected void generate(Annotatable inputElement, boolean skipFacets, PropertiesSource propertie,
            ITemplates templates, ModuleDirectory moduleDirectory) {
        if (inputElement instanceof AbstractModule) {
            final AbstractModule module = (AbstractModule) inputElement;

            final Set<AbstractModule> requiredModules = new LinkedHashSet<AbstractModule>();
            requiredModules.add(module);
            requiredModules.addAll(contextResolver.resolveResolutionContext(module, false).keySet());
            requiredModules.addAll(contextResolver.resolveResolutionContext(module, true).keySet());

            final Set<File> projectDirs = new HashSet<File>();
            for (MavenProject project : legacySupport.getSession().getProjects()) {
                projectDirs.add(project.getBasedir());
            }

            for (AbstractModule requiredModule : requiredModules) {
                if (projectDirs.contains(requiredModule.getDirectory())) // only if in reactor
                {
                    addMavenDependenciesRepository(module, requiredModule);
                }
            }
        }
    }

    private void addMavenDependenciesRepository(final AbstractModule module, AbstractModule requiredModule) {
        final String repositoryURL = requiredModule.getAnnotationData("b2.mavenDependencies", "repositoryURL");
        if (repositoryURL != null) {
            final File pomFile = resolvePomFile(module);

            final Model pom = readMavenModel(pomFile);

            removeDependencies(pom, JARS);

            final String repositoryName = requiredModule.getAnnotationData("b2.mavenDependencies",
                    "repositoryName");

            final Repository repository = new Repository();
            repository.setId(repositoryName);
            repository.setLayout("p2");
            repository.setUrl(repositoryURL);
            pom.addRepository(repository);

            writeMavenModel(pomFile, pom);
        }
    }

    @Override
    protected void addInputTypes(Collection<Class<? extends EObject>> inputTypes) {
        inputTypes.add(AbstractModule.class);
    }

    @Override
    public GeneratorType getGeneratorType() {
        return GeneratorType.MODULE_RESOURCE_FILTER;
    }
}