summaryrefslogtreecommitdiffstats
path: root/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/AbstractIdeSupportMojo.java
diff options
context:
space:
mode:
Diffstat (limited to 'maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/AbstractIdeSupportMojo.java')
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/AbstractIdeSupportMojo.java1150
1 files changed, 1150 insertions, 0 deletions
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/AbstractIdeSupportMojo.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/AbstractIdeSupportMojo.java
new file mode 100644
index 0000000000..6fc8295a4e
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/AbstractIdeSupportMojo.java
@@ -0,0 +1,1150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.tuscany.maven.plugin.eclipse;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.jar.Manifest;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.resolver.ArtifactCollector;
+import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
+import org.apache.maven.artifact.resolver.ArtifactResolutionException;
+import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.artifact.resolver.DebugResolutionListener;
+import org.apache.maven.artifact.resolver.ResolutionNode;
+import org.apache.maven.artifact.resolver.WarningResolutionListener;
+import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
+import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.VersionRange;
+import org.apache.maven.execution.RuntimeInformation;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.DependencyManagement;
+import org.apache.maven.model.Exclusion;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.eclipse.Constants;
+import org.apache.maven.plugin.eclipse.Messages;
+import org.apache.maven.plugin.ide.IdeDependency;
+import org.apache.maven.plugin.ide.IdeUtils;
+import org.apache.maven.project.MavenProject;
+import org.apache.tuscany.maven.bundle.plugin.BundleUtil;
+import org.codehaus.plexus.logging.LogEnabled;
+import org.codehaus.plexus.logging.Logger;
+
+/**
+ * Abstract base plugin which takes care of the common stuff usually needed by maven IDE plugins. A plugin extending
+ * AbstractIdeSupportMojo should implement the <code>setup()</code> and <code>writeConfiguration()</code> methods, plus
+ * the getters needed to get the various configuration flags and required components. The lifecycle:
+ *
+ * <pre>
+ * *** calls setup() where you can configure your specific stuff and stop the mojo from execute if appropriate ***
+ * - manually resolve project dependencies, NOT failing if a dependency is missing
+ * - compute project references (reactor projects) if the getUseProjectReferences() flag is set
+ * - download sources/javadocs if the getDownloadSources() flag is set
+ * *** calls writeConfiguration(), passing the list of resolved referenced dependencies ***
+ * - report the list of missing sources or just tell how to turn this feature on if the flag was disabled
+ * </pre>
+ *
+ * @author Fabrizio Giustina
+ * @version $Id: AbstractIdeSupportMojo.java 727620 2008-12-18 02:35:18Z baerrach $
+ */
+public abstract class AbstractIdeSupportMojo
+ extends AbstractMojo
+ implements LogEnabled
+{
+ /**
+ * Is it an PDE project? If yes, the plugin adds the necessary natures and build commands to the .project file.
+ * Additionally it copies all libraries to a project local directory and references them instead of referencing the
+ * files in the local Maven repository. It also ensured that the "Bundle-Classpath" in META-INF/MANIFEST.MF is
+ * synchronized.
+ *
+ * @parameter expression="${eclipse.pde}" default-value="true"
+ */
+ protected boolean pde;
+
+ /**
+ * The project whose project files to create.
+ *
+ * @parameter expression="${project}"
+ * @required
+ * @readonly
+ */
+ protected MavenProject project;
+
+ /**
+ * The currently executed project (can be a reactor project).
+ *
+ * @parameter expression="${executedProject}"
+ * @readonly
+ */
+ protected MavenProject executedProject;
+
+ /**
+ * The project packaging.
+ *
+ * @parameter expression="${project.packaging}"
+ */
+ protected String packaging;
+
+ /**
+ * Artifact factory, needed to download source jars for inclusion in classpath.
+ *
+ * @component role="org.apache.maven.artifact.factory.ArtifactFactory"
+ * @required
+ * @readonly
+ */
+ protected ArtifactFactory artifactFactory;
+
+ /**
+ * Artifact resolver, needed to download source jars for inclusion in classpath.
+ *
+ * @component role="org.apache.maven.artifact.resolver.ArtifactResolver"
+ * @required
+ * @readonly
+ */
+ protected ArtifactResolver artifactResolver;
+
+ /**
+ * Artifact collector, needed to resolve dependencies.
+ *
+ * @component role="org.apache.maven.artifact.resolver.ArtifactCollector"
+ * @required
+ * @readonly
+ */
+ protected ArtifactCollector artifactCollector;
+
+ /**
+ * @component role="org.apache.maven.artifact.metadata.ArtifactMetadataSource" hint="maven"
+ */
+ protected ArtifactMetadataSource artifactMetadataSource;
+
+ /**
+ * The runtime information for Maven, used to retrieve Maven's version number.
+ *
+ * @component
+ */
+ private RuntimeInformation runtimeInformation;
+
+ /**
+ * Remote repositories which will be searched for source attachments.
+ *
+ * @parameter expression="${project.remoteArtifactRepositories}"
+ * @required
+ * @readonly
+ */
+ protected List remoteArtifactRepositories;
+
+ /**
+ * Local maven repository.
+ *
+ * @parameter expression="${localRepository}"
+ * @required
+ * @readonly
+ */
+ protected ArtifactRepository localRepository;
+
+ /**
+ * If the executed project is a reactor project, this will contains the full list of projects in the reactor.
+ *
+ * @parameter expression="${reactorProjects}"
+ * @required
+ * @readonly
+ */
+ protected List reactorProjects;
+
+ /**
+ * Skip the operation when true.
+ *
+ * @parameter expression="${eclipse.skip}" default-value="false"
+ */
+ private boolean skip;
+
+ /**
+ * Enables/disables the downloading of source attachments. Defaults to false. When this flag is <code>true</code>
+ * remote repositories are checked for sources: in order to avoid repeated check for unavailable source archives, a
+ * status cache is mantained. To reset this cache run <code>mvn eclipse:remove-cache</code>, or use the
+ * <code>forceRecheck</code> option.
+ *
+ * @parameter expression="${downloadSources}"
+ */
+ protected boolean downloadSources;
+
+ /**
+ * Enables/disables the downloading of javadoc attachments. Defaults to false. When this flag is <code>true</code>
+ * remote repositories are checked for javadocs: in order to avoid repeated check for unavailable javadoc archives,
+ * a status cache is mantained. To reset this cache run <code>mvn eclipse:remove-cache</code>, or use the
+ * <code>forceRecheck</code> option.
+ *
+ * @parameter expression="${downloadJavadocs}"
+ */
+ protected boolean downloadJavadocs;
+
+ /**
+ * Enables/disables the rechecking of the remote repository for downloading source/javadoc attachments. Defaults to
+ * false. When this flag is <code>true</code> and the source or javadoc attachment has a status cache to indicate
+ * that it is not available, then the remote repository will be rechecked for a source or javadoc attachment and the
+ * status cache updated to reflect the new state.
+ *
+ * @parameter expression="${forceRecheck}"
+ */
+ protected boolean forceRecheck;
+
+ /**
+ * Plexus logger needed for debugging manual artifact resolution.
+ */
+ protected Logger logger;
+
+ /**
+ * Getter for <code>artifactMetadataSource</code>.
+ *
+ * @return Returns the artifactMetadataSource.
+ */
+ public ArtifactMetadataSource getArtifactMetadataSource()
+ {
+ return artifactMetadataSource;
+ }
+
+ /**
+ * Setter for <code>artifactMetadataSource</code>.
+ *
+ * @param artifactMetadataSource The artifactMetadataSource to set.
+ */
+ public void setArtifactMetadataSource( ArtifactMetadataSource artifactMetadataSource )
+ {
+ this.artifactMetadataSource = artifactMetadataSource;
+ }
+
+ /**
+ * Getter for <code>project</code>.
+ *
+ * @return Returns the project.
+ */
+ public MavenProject getProject()
+ {
+ return project;
+ }
+
+ /**
+ * Setter for <code>project</code>.
+ *
+ * @param project The project to set.
+ */
+ public void setProject( MavenProject project )
+ {
+ this.project = project;
+ }
+
+ /**
+ * Getter for <code>reactorProjects</code>.
+ *
+ * @return Returns the reactorProjects.
+ */
+ public List getReactorProjects()
+ {
+ return reactorProjects;
+ }
+
+ /**
+ * Setter for <code>reactorProjects</code>.
+ *
+ * @param reactorProjects The reactorProjects to set.
+ */
+ public void setReactorProjects( List reactorProjects )
+ {
+ this.reactorProjects = reactorProjects;
+ }
+
+ /**
+ * Getter for <code>remoteArtifactRepositories</code>.
+ *
+ * @return Returns the remoteArtifactRepositories.
+ */
+ public List getRemoteArtifactRepositories()
+ {
+ return remoteArtifactRepositories;
+ }
+
+ /**
+ * Setter for <code>remoteArtifactRepositories</code>.
+ *
+ * @param remoteArtifactRepositories The remoteArtifactRepositories to set.
+ */
+ public void setRemoteArtifactRepositories( List remoteArtifactRepositories )
+ {
+ this.remoteArtifactRepositories = remoteArtifactRepositories;
+ }
+
+ /**
+ * Getter for <code>artifactFactory</code>.
+ *
+ * @return Returns the artifactFactory.
+ */
+ public ArtifactFactory getArtifactFactory()
+ {
+ return artifactFactory;
+ }
+
+ /**
+ * Setter for <code>artifactFactory</code>.
+ *
+ * @param artifactFactory The artifactFactory to set.
+ */
+ public void setArtifactFactory( ArtifactFactory artifactFactory )
+ {
+ this.artifactFactory = artifactFactory;
+ }
+
+ /**
+ * Getter for <code>artifactResolver</code>.
+ *
+ * @return Returns the artifactResolver.
+ */
+ public ArtifactResolver getArtifactResolver()
+ {
+ return artifactResolver;
+ }
+
+ /**
+ * Setter for <code>artifactResolver</code>.
+ *
+ * @param artifactResolver The artifactResolver to set.
+ */
+ public void setArtifactResolver( ArtifactResolver artifactResolver )
+ {
+ this.artifactResolver = artifactResolver;
+ }
+
+ /**
+ * Getter for <code>executedProject</code>.
+ *
+ * @return Returns the executedProject.
+ */
+ public MavenProject getExecutedProject()
+ {
+ return executedProject;
+ }
+
+ /**
+ * Setter for <code>executedProject</code>.
+ *
+ * @param executedProject The executedProject to set.
+ */
+ public void setExecutedProject( MavenProject executedProject )
+ {
+ this.executedProject = executedProject;
+ }
+
+ /**
+ * Getter for <code>localRepository</code>.
+ *
+ * @return Returns the localRepository.
+ */
+ public ArtifactRepository getLocalRepository()
+ {
+ return localRepository;
+ }
+
+ /**
+ * Setter for <code>localRepository</code>.
+ *
+ * @param localRepository The localRepository to set.
+ */
+ public void setLocalRepository( ArtifactRepository localRepository )
+ {
+ this.localRepository = localRepository;
+ }
+
+ /**
+ * Getter for <code>downloadJavadocs</code>.
+ *
+ * @return Returns the downloadJavadocs.
+ */
+ public boolean getDownloadJavadocs()
+ {
+ return downloadJavadocs;
+ }
+
+ /**
+ * Setter for <code>downloadJavadocs</code>.
+ *
+ * @param downloadJavadoc The downloadJavadocs to set.
+ */
+ public void setDownloadJavadocs( boolean downloadJavadoc )
+ {
+ downloadJavadocs = downloadJavadoc;
+ }
+
+ /**
+ * Getter for <code>downloadSources</code>.
+ *
+ * @return Returns the downloadSources.
+ */
+ public boolean getDownloadSources()
+ {
+ return downloadSources;
+ }
+
+ /**
+ * Setter for <code>downloadSources</code>.
+ *
+ * @param downloadSources The downloadSources to set.
+ */
+ public void setDownloadSources( boolean downloadSources )
+ {
+ this.downloadSources = downloadSources;
+ }
+
+ protected void setResolveDependencies( boolean resolveDependencies )
+ {
+ this.resolveDependencies = resolveDependencies;
+ }
+
+ protected boolean isResolveDependencies()
+ {
+ return resolveDependencies;
+ }
+
+ /**
+ * return <code>false</code> if projects available in a reactor build should be considered normal dependencies,
+ * <code>true</code> if referenced project will be linked and not need artifact resolution.
+ *
+ * @return <code>true</code> if referenced project will be linked and not need artifact resolution
+ */
+ protected abstract boolean getUseProjectReferences();
+
+ /**
+ * Hook for preparation steps before the actual plugin execution.
+ *
+ * @return <code>true</code> if execution should continue or <code>false</code> if not.
+ * @throws MojoExecutionException generic mojo exception
+ */
+ protected abstract boolean setup()
+ throws MojoExecutionException;
+
+ /**
+ * Main plugin method where dependencies should be processed in order to generate IDE configuration files.
+ *
+ * @param deps list of <code>IdeDependency</code> objects, with artifacts, sources and javadocs already resolved
+ * @throws MojoExecutionException generic mojo exception
+ */
+ protected abstract void writeConfiguration( IdeDependency[] deps )
+ throws MojoExecutionException;
+
+ /**
+ * Not a plugin parameter. Collect the list of dependencies with a missing source artifact for the final report.
+ */
+ private List missingSourceDependencies = new ArrayList();
+
+ /**
+ * Not a plugin parameter. Collect the list of dependencies with a missing javadoc artifact for the final report.
+ */
+ // TODO merge this with the missingSourceDependencies in a classifier based map?
+ private List missingJavadocDependencies = new ArrayList();
+
+ /**
+ * Cached array of resolved dependencies.
+ */
+ private IdeDependency[] ideDeps;
+
+ /**
+ * Flag for mojo implementations to control whether normal maven dependencies should be resolved. Default value is
+ * true.
+ */
+ private boolean resolveDependencies = true;
+
+ /**
+ * @see org.codehaus.plexus.logging.LogEnabled#enableLogging(org.codehaus.plexus.logging.Logger)
+ */
+ public void enableLogging( Logger logger )
+ {
+ this.logger = logger;
+ }
+
+ /**
+ * @see org.apache.maven.plugin.Mojo#execute()
+ */
+ public final void execute()
+ throws MojoExecutionException, MojoFailureException
+ {
+ if ( skip )
+ {
+ return;
+ }
+
+ boolean processProject = setup();
+ if ( !processProject )
+ {
+ return;
+ }
+
+ // resolve artifacts
+ IdeDependency[] deps = doDependencyResolution();
+
+ resolveSourceAndJavadocArtifacts( deps );
+
+ writeConfiguration( deps );
+
+ reportMissingArtifacts();
+
+ }
+
+ /**
+ * Resolve project dependencies. Manual resolution is needed in order to avoid resolution of multiproject artifacts
+ * (if projects will be linked each other an installed jar is not needed) and to avoid a failure when a jar is
+ * missing.
+ *
+ * @throws MojoExecutionException if dependencies can't be resolved
+ * @return resolved IDE dependencies, with attached jars for non-reactor dependencies
+ */
+ protected IdeDependency[] doDependencyResolution()
+ throws MojoExecutionException
+ {
+ if ( ideDeps == null )
+ {
+ if ( resolveDependencies )
+ {
+ MavenProject project = getProject();
+ Set<String> imported = Collections.emptySet();
+ try {
+ imported = BundleUtil.getImportedPackages(project.getBasedir());
+ } catch (IOException e1) {
+ throw new MojoExecutionException(e1.getMessage(), e1);
+ }
+ ArtifactRepository localRepo = getLocalRepository();
+
+ List deps = getProject().getDependencies();
+
+ // Collect the list of resolved IdeDependencies.
+ List dependencies = new ArrayList();
+
+ if ( deps != null )
+ {
+ Map managedVersions =
+ createManagedVersionMap( getArtifactFactory(), project.getId(),
+ project.getDependencyManagement() );
+
+ ArtifactResolutionResult artifactResolutionResult = null;
+
+ try
+ {
+
+ List listeners = new ArrayList();
+
+ if ( logger.isDebugEnabled() )
+ {
+ listeners.add( new DebugResolutionListener( logger ) );
+ }
+
+ listeners.add( new WarningResolutionListener( logger ) );
+
+ artifactResolutionResult =
+ artifactCollector.collect( getProjectArtifacts(), project.getArtifact(), managedVersions,
+ localRepo, project.getRemoteArtifactRepositories(),
+ getArtifactMetadataSource(), null, listeners );
+ }
+ catch ( ArtifactResolutionException e )
+ {
+ getLog().debug( e.getMessage(), e );
+ getLog().error(
+ Messages.getString( "AbstractIdeSupportMojo.artifactresolution", new Object[] { //$NON-NLS-1$
+ e.getGroupId(), e.getArtifactId(), e.getVersion(),
+ e.getMessage() } ) );
+
+ // if we are here artifactResolutionResult is null, create a project without dependencies but
+ // don't fail
+ // (this could be a reactor projects, we don't want to fail everything)
+ // Causes MECLIPSE-185. Not sure if it should be handled this way??
+ return new IdeDependency[0];
+ }
+
+ // keep track of added reactor projects in order to avoid duplicates
+ Set emittedReactorProjectId = new HashSet();
+
+ for ( Iterator i = artifactResolutionResult.getArtifactResolutionNodes().iterator(); i.hasNext(); )
+ {
+
+ ResolutionNode node = (ResolutionNode) i.next();
+ int dependencyDepth = node.getDepth();
+ Artifact art = node.getArtifact();
+ // don't resolve jars for reactor projects
+ if ( hasToResolveJar( art ) )
+ {
+ try
+ {
+ artifactResolver.resolve( art, node.getRemoteRepositories(), localRepository );
+ }
+ catch ( ArtifactNotFoundException e )
+ {
+ getLog().debug( e.getMessage(), e );
+ getLog().warn(
+ Messages.getString( "AbstractIdeSupportMojo.artifactdownload", new Object[] { //$NON-NLS-1$
+ e.getGroupId(), e.getArtifactId(), e.getVersion(),
+ e.getMessage() } ) );
+ }
+ catch ( ArtifactResolutionException e )
+ {
+ getLog().debug( e.getMessage(), e );
+ getLog().warn(
+ Messages.getString( "AbstractIdeSupportMojo.artifactresolution", new Object[] { //$NON-NLS-1$
+ e.getGroupId(), e.getArtifactId(), e.getVersion(),
+ e.getMessage() } ) );
+ }
+ }
+
+ boolean includeArtifact = true;
+ if ( getExcludes() != null )
+ {
+ String artifactFullId = art.getGroupId() + ":" + art.getArtifactId();
+ if ( getExcludes().contains( artifactFullId ) )
+ {
+ getLog().info( "excluded: " + artifactFullId );
+ includeArtifact = false;
+ }
+ }
+
+ if ( includeArtifact
+ && ( !( getUseProjectReferences() && isAvailableAsAReactorProject( art ) ) || emittedReactorProjectId.add( art.getGroupId()
+ + '-' + art.getArtifactId() ) ) )
+ {
+
+ // the following doesn't work: art.getArtifactHandler().getPackaging() always returns "jar"
+ // also
+ // if the packaging specified in pom.xml is different.
+
+ // osgi-bundle packaging is provided by the felix osgi plugin
+ // eclipse-plugin packaging is provided by this eclipse plugin
+ // String packaging = art.getArtifactHandler().getPackaging();
+ // boolean isOsgiBundle = "osgi-bundle".equals( packaging ) || "eclipse-plugin".equals(
+ // packaging );
+
+ // we need to check the manifest, if "Bundle-SymbolicName" is there the artifact can be
+ // considered
+ // an osgi bundle
+ if ("pom".equals(art.getType())) {
+ continue;
+ }
+ File artifactFile = art.getFile();
+ MavenProject reactorProject = getReactorProject(art);
+ if (reactorProject != null) {
+ artifactFile = reactorProject.getBasedir();
+ }
+ boolean isOsgiBundle = false;
+ String osgiSymbolicName = null;
+ try {
+ osgiSymbolicName = BundleUtil.getBundleSymbolicName(artifactFile);
+ } catch (IOException e) {
+ getLog().error("Unable to read jar manifest from " + artifactFile, e);
+ }
+ isOsgiBundle = osgiSymbolicName != null;
+
+ IdeDependency dep =
+ new IdeDependency( art.getGroupId(), art.getArtifactId(), art.getVersion(),
+ art.getClassifier(), useProjectReference( art ),
+ Artifact.SCOPE_TEST.equals( art.getScope() ),
+ Artifact.SCOPE_SYSTEM.equals( art.getScope() ),
+ Artifact.SCOPE_PROVIDED.equals( art.getScope() ),
+ art.getArtifactHandler().isAddedToClasspath(), art.getFile(),
+ art.getType(), isOsgiBundle, osgiSymbolicName, dependencyDepth,
+ getProjectNameForArifact( art ) );
+ // no duplicate entries allowed. System paths can cause this problem.
+ if ( !dependencies.contains( dep ) )
+ {
+ // [rfeng] Do not add compile/provided dependencies
+ if (!(pde && (Artifact.SCOPE_COMPILE.equals(art.getScope()) || Artifact.SCOPE_PROVIDED
+ .equals(art.getScope())))) {
+ dependencies.add( dep );
+ } else {
+ // Check this compile dependency is an OSGi package supplier
+ if (!imported.isEmpty()) {
+ Set<String> exported = Collections.emptySet();
+ try {
+ exported = BundleUtil.getExportedPackages(artifactFile);
+ } catch (IOException e) {
+ getLog().error("Unable to read jar manifest from " + art.getFile(), e);
+ }
+ boolean matched = false;
+ for (String p : imported) {
+ if (exported.contains(p)) {
+ matched = true;
+ break;
+ }
+ }
+ if (!matched) {
+ dependencies.add(dep);
+ } else {
+ getLog()
+ .debug("Compile dependency is skipped as it is added through OSGi dependency: " + art);
+ }
+ } else {
+ dependencies.add(dep);
+ }
+ }
+ }
+ }
+
+ }
+
+ // @todo a final report with the list of
+ // missingArtifacts?
+
+ }
+
+ ideDeps = (IdeDependency[]) dependencies.toArray( new IdeDependency[dependencies.size()] );
+ }
+ else
+ {
+ ideDeps = new IdeDependency[0];
+ }
+ }
+
+ return ideDeps;
+ }
+
+ /**
+ * Find the name of the project as used in eclipse.
+ *
+ * @param artifact The artifact to find the eclipse name for.
+ * @return The name os the eclipse project.
+ */
+ abstract public String getProjectNameForArifact( Artifact artifact );
+
+ /**
+ * Returns the list of project artifacts. Also artifacts generated from referenced projects will be added, but with
+ * the <code>resolved</code> property set to true.
+ *
+ * @return list of projects artifacts
+ * @throws MojoExecutionException if unable to parse dependency versions
+ */
+ private Set getProjectArtifacts()
+ throws MojoExecutionException
+ {
+ // keep it sorted, this should avoid random classpath order in tests
+ Set artifacts = new TreeSet();
+
+ for ( Iterator dependencies = getProject().getDependencies().iterator(); dependencies.hasNext(); )
+ {
+ Dependency dependency = (Dependency) dependencies.next();
+
+ String groupId = dependency.getGroupId();
+ String artifactId = dependency.getArtifactId();
+ VersionRange versionRange;
+ try
+ {
+ versionRange = VersionRange.createFromVersionSpec( dependency.getVersion() );
+ }
+ catch ( InvalidVersionSpecificationException e )
+ {
+ throw new MojoExecutionException(
+ Messages.getString(
+ "AbstractIdeSupportMojo.unabletoparseversion", new Object[] { //$NON-NLS-1$
+ dependency.getArtifactId(),
+ dependency.getVersion(),
+ dependency.getManagementKey(), e.getMessage() } ),
+ e );
+ }
+
+ String type = dependency.getType();
+ if ( type == null )
+ {
+ type = Constants.PROJECT_PACKAGING_JAR;
+ }
+ String classifier = dependency.getClassifier();
+ boolean optional = dependency.isOptional();
+ String scope = dependency.getScope();
+ if ( scope == null )
+ {
+ scope = Artifact.SCOPE_COMPILE;
+ }
+
+ Artifact art =
+ getArtifactFactory().createDependencyArtifact( groupId, artifactId, versionRange, type, classifier,
+ scope, optional );
+
+ if ( scope.equalsIgnoreCase( Artifact.SCOPE_SYSTEM ) )
+ {
+ art.setFile( new File( dependency.getSystemPath() ) );
+ }
+
+ List exclusions = new ArrayList();
+ for ( Iterator j = dependency.getExclusions().iterator(); j.hasNext(); )
+ {
+ Exclusion e = (Exclusion) j.next();
+ exclusions.add( e.getGroupId() + ":" + e.getArtifactId() ); //$NON-NLS-1$
+ }
+
+ ArtifactFilter newFilter = new ExcludesArtifactFilter( exclusions );
+
+ art.setDependencyFilter( newFilter );
+
+ artifacts.add( art );
+ }
+
+ return artifacts;
+ }
+
+ /**
+ * Utility method that locates a project producing the given artifact.
+ *
+ * @param artifact the artifact a project should produce.
+ * @return <code>true</code> if the artifact is produced by a reactor projectart.
+ */
+ protected boolean isAvailableAsAReactorProject( Artifact artifact )
+ {
+ return getReactorProject( artifact ) != null;
+ }
+
+ /**
+ * Checks the list of reactor projects to see if the artifact is included.
+ *
+ * @param artifact the artifact to check if it is in the reactor
+ * @return the reactor project or null if it is not in the reactor
+ */
+ protected MavenProject getReactorProject( Artifact artifact ) {
+ if ( reactorProjects != null )
+ {
+ for ( Iterator iter = reactorProjects.iterator(); iter.hasNext(); )
+ {
+ MavenProject reactorProject = (MavenProject) iter.next();
+
+ if ( reactorProject.getGroupId().equals( artifact.getGroupId() )
+ && reactorProject.getArtifactId().equals( artifact.getArtifactId() ) )
+ {
+ if ( reactorProject.getVersion().equals( artifact.getVersion() ) )
+ {
+ return reactorProject;
+ }
+ else
+ {
+ getLog().info(
+ "Artifact "
+ + artifact.getId()
+ + " already available as a reactor project, but with different version. Expected: "
+ + artifact.getVersion() + ", found: " + reactorProject.getVersion() );
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return an array with all dependencies avalaible in the workspace, to be implemented by the subclasses.
+ */
+ protected IdeDependency[] getWorkspaceArtefacts()
+ {
+ return new IdeDependency[0];
+ }
+
+ private Map createManagedVersionMap( ArtifactFactory artifactFactory, String projectId,
+ DependencyManagement dependencyManagement )
+ throws MojoExecutionException
+ {
+ Map map;
+ if ( dependencyManagement != null && dependencyManagement.getDependencies() != null )
+ {
+ map = new HashMap();
+ for ( Iterator i = dependencyManagement.getDependencies().iterator(); i.hasNext(); )
+ {
+ Dependency d = (Dependency) i.next();
+
+ try
+ {
+ VersionRange versionRange = VersionRange.createFromVersionSpec( d.getVersion() );
+ Artifact artifact =
+ artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), versionRange,
+ d.getType(), d.getClassifier(), d.getScope(),
+ d.isOptional() );
+ map.put( d.getManagementKey(), artifact );
+ }
+ catch ( InvalidVersionSpecificationException e )
+ {
+ throw new MojoExecutionException( Messages.getString( "AbstractIdeSupportMojo.unabletoparseversion", new Object[] { //$NON-NLS-1$
+ projectId, d.getVersion(),
+ d.getManagementKey(), e.getMessage() } ),
+ e );
+ }
+ }
+ }
+ else
+ {
+ map = Collections.EMPTY_MAP;
+ }
+ return map;
+ }
+
+ /**
+ * Resolve source artifacts and download them if <code>downloadSources</code> is <code>true</code>. Source and
+ * javadocs artifacts will be attached to the <code>IdeDependency</code> Resolve source and javadoc artifacts. The
+ * resolved artifacts will be downloaded based on the <code>downloadSources</code> and <code>downloadJavadocs</code>
+ * attributes. Source and
+ *
+ * @param deps resolved dependencies
+ */
+ private void resolveSourceAndJavadocArtifacts( IdeDependency[] deps )
+ {
+ final List missingSources =
+ resolveDependenciesWithClassifier( deps, "sources", getDownloadSources() );
+ missingSourceDependencies.addAll( missingSources );
+
+ final List missingJavadocs =
+ resolveDependenciesWithClassifier( deps, "javadoc", getDownloadJavadocs() );
+ missingJavadocDependencies.addAll( missingJavadocs );
+ }
+
+ /**
+ * Resolve the required artifacts for each of the dependency. <code>sources</code> or <code>javadoc</code> artifacts
+ * (depending on the <code>classifier</code>) are attached to the dependency.
+ *
+ * @param deps resolved dependencies
+ * @param inClassifier the classifier we are looking for (either <code>sources</code> or <code>javadoc</code>)
+ * @param includeRemoteRepositories flag whether we should search remote repositories for the artifacts or not
+ * @return the list of dependencies for which the required artifact was not found
+ */
+ private List resolveDependenciesWithClassifier( IdeDependency[] deps, String inClassifier,
+ boolean includeRemoteRepositories )
+ {
+ List missingClassifierDependencies = new ArrayList();
+
+ // if downloadSources is off, just check
+ // local repository for reporting missing source jars
+ List remoteRepos = includeRemoteRepositories ? getRemoteArtifactRepositories() : Collections.EMPTY_LIST;
+
+ for ( int j = 0; j < deps.length; j++ )
+ {
+ IdeDependency dependency = deps[j];
+
+ if ( dependency.isReferencedProject() || dependency.isSystemScoped() )
+ {
+ // artifact not needed
+ continue;
+ }
+
+ if ( getLog().isDebugEnabled() )
+ {
+ getLog().debug(
+ "Searching for sources for " + dependency.getId() + ":" + dependency.getClassifier()
+ + " at " + dependency.getId() + ":" + inClassifier );
+ }
+
+ Artifact baseArtifact =
+ artifactFactory.createArtifactWithClassifier( dependency.getGroupId(), dependency.getArtifactId(),
+ dependency.getVersion(), dependency.getType(),
+ dependency.getClassifier() );
+ baseArtifact =
+ IdeUtils.resolveArtifact( artifactResolver, baseArtifact, remoteRepos, localRepository, getLog() );
+ if (!baseArtifact.isResolved()) {
+ // base artifact does not exist - no point checking for javadoc/sources
+ continue;
+ }
+
+ Artifact artifact =
+ IdeUtils.createArtifactWithClassifier( dependency.getGroupId(), dependency.getArtifactId(),
+ dependency.getVersion(), dependency.getClassifier(),
+ inClassifier, artifactFactory );
+ File notAvailableMarkerFile = IdeUtils.getNotAvailableMarkerFile( localRepository, artifact );
+
+ if (forceRecheck && notAvailableMarkerFile.exists()) {
+ if (!notAvailableMarkerFile.delete()) {
+ getLog().warn( Messages.getString( "AbstractIdeSupportMojo.unabletodeletenotavailablemarkerfile", notAvailableMarkerFile ) );
+ }
+ }
+
+ if ( !notAvailableMarkerFile.exists() )
+ {
+ artifact =
+ IdeUtils.resolveArtifact( artifactResolver, artifact, remoteRepos, localRepository, getLog() );
+ if ( artifact.isResolved() )
+ {
+ if ( "sources".equals( inClassifier ) )
+ {
+ dependency.setSourceAttachment( artifact.getFile() );
+ }
+ else if ( "javadoc".equals( inClassifier ) )
+ {
+ dependency.setJavadocAttachment( artifact.getFile() );
+ }
+ }
+ else
+ {
+ if ( includeRemoteRepositories )
+ {
+ try
+ {
+ notAvailableMarkerFile.createNewFile();
+ getLog().debug( Messages.getString( "AbstractIdeSupportMojo.creatednotavailablemarkerfile", notAvailableMarkerFile ) );
+ }
+ catch ( IOException e )
+ {
+ getLog().warn( Messages.getString( "AbstractIdeSupportMojo.failedtocreatenotavailablemarkerfile",
+ notAvailableMarkerFile ) );
+ }
+ }
+ // add the dependencies to the list
+ // of those lacking the required
+ // artifact
+ missingClassifierDependencies.add( dependency );
+ }
+ }
+ }
+
+ // return the list of dependencies missing the
+ // required artifact
+ return missingClassifierDependencies;
+
+ }
+
+ /**
+ * Output a message with the list of missing dependencies and info on how turn download on if it was disabled.
+ */
+ private void reportMissingArtifacts()
+ {
+ StringBuffer msg = new StringBuffer();
+
+ if ( !missingSourceDependencies.isEmpty() )
+ {
+ if ( getDownloadSources() )
+ {
+ msg.append( Messages.getString( "AbstractIdeSupportMojo.sourcesnotavailable" ) ); //$NON-NLS-1$
+ }
+ else
+ {
+ msg.append( Messages.getString( "AbstractIdeSupportMojo.sourcesnotdownloaded" ) ); //$NON-NLS-1$
+ }
+
+ for ( Iterator it = missingSourceDependencies.iterator(); it.hasNext(); )
+ {
+ IdeDependency art = (IdeDependency) it.next();
+ msg.append( Messages.getString( "AbstractIdeSupportMojo.sourcesmissingitem", art.getId() ) ); //$NON-NLS-1$
+ }
+ msg.append( "\n" ); //$NON-NLS-1$
+ }
+
+ if ( !missingJavadocDependencies.isEmpty() )
+ {
+ if ( getDownloadJavadocs() )
+ {
+ msg.append( Messages.getString( "AbstractIdeSupportMojo.javadocnotavailable" ) ); //$NON-NLS-1$
+ }
+ else
+ {
+ msg.append( Messages.getString( "AbstractIdeSupportMojo.javadocnotdownloaded" ) ); //$NON-NLS-1$
+ }
+
+ for ( Iterator it = missingJavadocDependencies.iterator(); it.hasNext(); )
+ {
+ IdeDependency art = (IdeDependency) it.next();
+ msg.append( Messages.getString( "AbstractIdeSupportMojo.javadocmissingitem", art.getId() ) ); //$NON-NLS-1$
+ }
+ msg.append( "\n" ); //$NON-NLS-1$
+ }
+ getLog().info( msg );
+ }
+
+ /**
+ * @return List of dependencies to exclude from eclipse classpath.
+ * @since 2.5
+ */
+ public abstract List getExcludes();
+
+ /**
+ * Checks if jar has to be resolved for the given artifact
+ *
+ * @param art the artifact to check
+ * @return true if resolution should happen
+ */
+ protected boolean hasToResolveJar( Artifact art )
+ {
+ return !( getUseProjectReferences() && isAvailableAsAReactorProject( art ) );
+ }
+
+ /**
+ * Checks if a projects reference has to be used for the given artifact
+ *
+ * @param art the artifact to check
+ * @return true if a project reference has to be used.
+ */
+ protected boolean useProjectReference( Artifact art )
+ {
+ return getUseProjectReferences() && isAvailableAsAReactorProject( art );
+ }
+
+ /**
+ * Checks whether the currently running Maven satisfies the specified version (range).
+ *
+ * @param version The version range to test for, must not be <code>null</code>.
+ * @return <code>true</code> if the current Maven version matches the specified version range, <code>false</code>
+ * otherwise.
+ */
+ protected boolean isMavenVersion( String version )
+ {
+ try
+ {
+ VersionRange versionRange = VersionRange.createFromVersionSpec( version );
+ ArtifactVersion mavenVersion = runtimeInformation.getApplicationVersion();
+ return versionRange.containsVersion( mavenVersion );
+ }
+ catch ( InvalidVersionSpecificationException e )
+ {
+ throw new IllegalArgumentException( e.getMessage() );
+ }
+ }
+
+ // [rfeng]
+ protected boolean isOSGiBundle() {
+ File base = project.getBasedir();
+ File mf = new File(base, "META-INF/MANIFEST.MF");
+ if (mf.isFile()) {
+ Manifest manifest = null;
+ try {
+ InputStream is = new FileInputStream(mf);
+ manifest = new Manifest(is);
+ is.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ if (manifest != null) {
+ String bundleName = manifest.getMainAttributes().getValue("Bundle-SymbolicName");
+ if (bundleName != null) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}