Skip to content

Commit 3187958

Browse files
committed
[MECLIPSE-759] Add goal resolve-workspace-dependencies to resolve the M2_REPO classpath references of all projects contained in a workspace
git-svn-id: https://svn.apache.org/repos/asf/maven/plugins/trunk@1681500 13f79535-47bb-0310-9956-ffa450edef68
1 parent 927762b commit 3187958

4 files changed

Lines changed: 236 additions & 23 deletions

File tree

src/main/java/org/apache/maven/plugin/eclipse/EclipsePlugin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,8 @@ public class EclipsePlugin
451451
* If set to <code>true</code>, the standard execution environment matching the compiler settings is set as JRE. If
452452
* set to <code>false</code>, the JRE matching the configured compiler-plugin executable or JAVA_HOME is selected by
453453
* name, if it is configured in the workspace.
454+
*
455+
* @since 2.10
454456
*/
455457
@Parameter( property = "eclipse.preferStandardClasspathContainer", defaultValue = "false" )
456458
private boolean preferStandardClasspathContainer;
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
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+
}

src/main/java/org/apache/maven/plugin/eclipse/reader/ReadWorkspaceLocations.java

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.ArrayList;
2727
import java.util.HashMap;
2828
import java.util.Iterator;
29+
import java.util.List;
2930
import java.util.Map;
3031
import java.util.Properties;
3132
import java.util.Set;
@@ -542,38 +543,28 @@ else if ( !jreMap.containsKey( jrePath ) )
542543
}
543544

544545
/**
545-
* Scan the eclipse workspace and create a array with {@link IdeDependency} for all found artifacts.
546-
*
547-
* @param workspaceConfiguration the location of the eclipse workspace.
548-
* @param logger the logger to report errors and debug info.
546+
* @param workspaceDirectory the directory of the workspace
547+
* @param logger logger
548+
* @return the physical locations of all workspace projects
549549
*/
550-
private void readWorkspace( WorkspaceConfiguration workspaceConfiguration, Log logger )
550+
public List<File> readProjectLocations( File workspaceDirectory, Log logger )
551551
{
552-
ArrayList<IdeDependency> dependencies = new ArrayList<IdeDependency>();
553-
if ( workspaceConfiguration.getWorkspaceDirectory() != null )
554-
{
555-
File workspace =
556-
new File( workspaceConfiguration.getWorkspaceDirectory(),
557-
ReadWorkspaceLocations.METADATA_PLUGINS_ORG_ECLIPSE_CORE_RESOURCES_PROJECTS );
552+
List<File> projectLocations = new ArrayList<File>();
553+
File projectsDirectory =
554+
new File( workspaceDirectory, ReadWorkspaceLocations.METADATA_PLUGINS_ORG_ECLIPSE_CORE_RESOURCES_PROJECTS );
558555

559-
File[] directories = workspace.listFiles();
560-
for ( int index = 0; directories != null && index < directories.length; index++ )
556+
if ( projectsDirectory.exists() )
557+
{
558+
for ( File project : projectsDirectory.listFiles() )
561559
{
562-
File project = directories[index];
563560
if ( project.isDirectory() )
564561
{
565562
try
566563
{
567-
File projectLocation =
568-
getProjectLocation( workspaceConfiguration.getWorkspaceDirectory(), project );
564+
File projectLocation = getProjectLocation( workspaceDirectory, project );
569565
if ( projectLocation != null )
570566
{
571-
logger.debug( "read workpsace project " + projectLocation );
572-
IdeDependency ideDependency = readArtefact( projectLocation, logger );
573-
if ( ideDependency != null )
574-
{
575-
dependencies.add( ideDependency );
576-
}
567+
projectLocations.add( projectLocation );
577568
}
578569
}
579570
catch ( Exception e )
@@ -583,7 +574,40 @@ private void readWorkspace( WorkspaceConfiguration workspaceConfiguration, Log l
583574
}
584575
}
585576
}
586-
logger.debug( dependencies.size() + " from workspace " + workspaceConfiguration.getWorkspaceDirectory() );
577+
578+
return projectLocations;
579+
}
580+
581+
/**
582+
* Scan the eclipse workspace and create a array with {@link IdeDependency} for all found artifacts.
583+
*
584+
* @param workspaceConfiguration the location of the eclipse workspace.
585+
* @param logger the logger to report errors and debug info.
586+
*/
587+
private void readWorkspace( WorkspaceConfiguration workspaceConfiguration, Log logger )
588+
{
589+
List<IdeDependency> dependencies = new ArrayList<IdeDependency>();
590+
File workspaceDirectory = workspaceConfiguration.getWorkspaceDirectory();
591+
if ( workspaceDirectory != null )
592+
{
593+
for ( File projectLocation : readProjectLocations( workspaceDirectory, logger ) )
594+
{
595+
try
596+
{
597+
logger.debug( "read workpsace project " + projectLocation );
598+
IdeDependency ideDependency = readArtefact( projectLocation, logger );
599+
if ( ideDependency != null )
600+
{
601+
dependencies.add( ideDependency );
602+
}
603+
}
604+
catch ( Exception e )
605+
{
606+
logger.warn( "could not read workspace project from:" + projectLocation, e );
607+
}
608+
}
609+
}
610+
logger.debug( dependencies.size() + " from workspace " + workspaceDirectory );
587611
workspaceConfiguration.setWorkspaceArtefacts( dependencies.toArray( new IdeDependency[dependencies.size()] ) );
588612
}
589613
}

src/site/apt/index.apt.vm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ ${project.name}
5050
* {{{./eclipse-mojo.html}eclipse:eclipse}} generates the Eclipse configuration
5151
files.
5252

53+
* {{{./resolve-workspace-dependencies-mojo.html}eclipse:resolve-workspace-dependencies}} is used to download
54+
all missing M2_REPO classpath variable elements for all projects in a workspace. Used if the Eclipse project
55+
configuration files are committed to version control and other users need to resolve new artifacts after an
56+
update.
57+
5358
* {{{./clean-mojo.html}eclipse:clean}} is used to delete the files used by the
5459
Eclipse IDE.
5560

0 commit comments

Comments
 (0)