diff options
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.java | 1150 |
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; + } + +} |