View Javadoc
1   package org.apache.maven.plugin.eclipse;
2   
3   import java.io.File;
4   import java.io.FileReader;
5   import java.util.ArrayList;
6   import java.util.List;
7   
8   import org.apache.maven.artifact.Artifact;
9   import org.apache.maven.artifact.factory.ArtifactFactory;
10  import org.apache.maven.artifact.repository.ArtifactRepository;
11  import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
12  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
13  import org.apache.maven.artifact.resolver.ArtifactResolver;
14  import org.apache.maven.plugin.AbstractMojo;
15  import org.apache.maven.plugin.MojoExecutionException;
16  import org.apache.maven.plugin.MojoFailureException;
17  import org.apache.maven.plugin.eclipse.reader.ReadWorkspaceLocations;
18  import org.apache.maven.plugins.annotations.Component;
19  import org.apache.maven.plugins.annotations.Mojo;
20  import org.apache.maven.plugins.annotations.Parameter;
21  import org.codehaus.plexus.util.StringUtils;
22  import org.codehaus.plexus.util.xml.Xpp3Dom;
23  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
24  
25  /**
26   * For all projects currently part of the workspace, all references to the <code>M2_REPO</code> classpath variable are
27   * resolved.
28   * <p>
29   * Note: not the projects of the <em>reactor</em> are inspected for unresolved artifacts, but the projects that are part
30   * of the <em>workspace</em>.
31   * 
32   * @since 2.10
33   * @author agudian
34   */
35  @Mojo( name = "resolve-workspace-dependencies", aggregator = true, requiresProject = false )
36  public class WorkspaceDependencyResolveMojo
37      extends AbstractMojo
38  {
39      /**
40       * The eclipse workspace directory.
41       * <p>
42       * If omitted, the parent directories of the working directory are checked. The first directory to contain a
43       * <code>.metadata</code> subdirectory is chosen.
44       */
45      @Parameter( property = "eclipse.workspace" )
46      private File workspace;
47  
48      @Component( role = ArtifactFactory.class )
49      private ArtifactFactory artifactFactory;
50  
51      @Component( role = ArtifactResolver.class )
52      private ArtifactResolver artifactResolver;
53  
54      @Parameter( property = "project.remoteArtifactRepositories", required = true, readonly = true )
55      private List<ArtifactRepository> remoteArtifactRepositories;
56  
57      @Parameter( property = "localRepository", required = true, readonly = true )
58      private ArtifactRepository localRepository;
59  
60      private List<File> findProjectLocations( File workspaceLocation )
61      {
62          return new ReadWorkspaceLocations().readProjectLocations( workspaceLocation, getLog() );
63      }
64  
65      private void validateWorkspaceLocation()
66          throws MojoExecutionException
67      {
68          if ( workspace != null && !isWorkspaceDirectory( workspace ) )
69          {
70              throw new MojoExecutionException( "Not a workspace directory: there is no subdirectory .metadata at "
71                  + workspace );
72          }
73  
74          if ( workspace == null )
75          {
76              File currentWorkingDirectory = new File( "." ).getAbsoluteFile();
77              while ( currentWorkingDirectory != null )
78              {
79                  if ( isWorkspaceDirectory( currentWorkingDirectory ) )
80                  {
81                      getLog().debug( "Detected workspace at " + currentWorkingDirectory );
82                      workspace = currentWorkingDirectory;
83                      return;
84                  }
85                  currentWorkingDirectory = currentWorkingDirectory.getParentFile();
86              }
87          }
88  
89          throw new MojoExecutionException( "No workspace location configured "
90              + "and none can be detected in the parent directories." );
91      }
92  
93      private boolean isWorkspaceDirectory( File currentWorkingDirectory )
94      {
95          return new File( currentWorkingDirectory, ".metadata" ).isDirectory();
96      }
97  
98      public void execute()
99          throws MojoExecutionException, MojoFailureException
100     {
101         validateWorkspaceLocation();
102 
103         for ( File location : findProjectLocations( workspace ) )
104         {
105             File classpathFile = new File( location, ".classpath" );
106             if ( classpathFile.exists() )
107             {
108                 getLog().info( "Resolving M2_REPO dependencies in " + classpathFile );
109                 try
110                 {
111                     Xpp3Dom classpath = Xpp3DomBuilder.build( new FileReader( classpathFile ) );
112 
113                     for ( Xpp3Dom entry : classpath.getChildren() )
114                     {
115                         if ( "var".equals( entry.getAttribute( "kind" ) ) )
116                         {
117                             resolveIfNecessary( entry.getAttribute( "path" ) );
118                             resolveIfNecessary( entry.getAttribute( "sourcepath" ) );
119                         }
120                     }
121 
122                 }
123                 catch ( Exception e )
124                 {
125                     getLog().error( "Error parsing " + classpathFile, e );
126                 }
127 
128             }
129         }
130     }
131 
132     private void resolveIfNecessary( String path )
133         throws ArtifactResolutionException
134     {
135         if ( null != path && path.startsWith( "M2_REPO" ) )
136         {
137             try
138             {
139                 Artifact artifact = createArtifactFromPath( path );
140                 if ( artifact != null )
141                 {
142                     artifactResolver.resolve( artifact, remoteArtifactRepositories, localRepository );
143                 }
144             }
145             catch ( ArtifactNotFoundException e )
146             {
147                 getLog().info( e );
148             }
149         }
150     }
151 
152     private Artifact createArtifactFromPath( String path )
153     {
154         String[] elements = path.split( "/" );
155         if ( elements.length < 4 )
156         {
157             getLog().error( "Unexpected repository path structure: " + path );
158             return null;
159         }
160 
161         List<String> groupParts = new ArrayList<String>();
162         for ( int i = 1; i < elements.length - 3; i++ )
163         {
164             groupParts.add( elements[i] );
165         }
166         String group = StringUtils.join( groupParts.iterator(), "." );
167         String artifactId = elements[elements.length - 3];
168         String version = elements[elements.length - 2];
169 
170         String classifier = null;
171         String fileName = elements[elements.length - 1];
172         String type = fileName.substring( fileName.lastIndexOf( '.' ) + 1 );
173         String possibleClassifier =
174             fileName.substring( artifactId.length() + version.length() + 1, fileName.length() - type.length() - 1 );
175         if ( possibleClassifier.length() > 1 )
176         {
177             classifier = possibleClassifier.substring( 1 );
178         }
179 
180         return artifactFactory.createArtifactWithClassifier( group, artifactId, version, type, classifier );
181     }
182 }