You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ah...@apache.org on 2015/04/01 02:24:02 UTC
[20/50] [abbrv] maven git commit: MNG-5775 Make the project graph
building code pluggable to allow for new/different implementations.
http://git-wip-us.apache.org/repos/asf/maven/blob/be3fb200/maven-core/src/test/java/org/apache/maven/graph/DefaultProjectDependencyGraphTest.java
----------------------------------------------------------------------
diff --git a/maven-core/src/test/java/org/apache/maven/graph/DefaultProjectDependencyGraphTest.java b/maven-core/src/test/java/org/apache/maven/graph/DefaultProjectDependencyGraphTest.java
new file mode 100644
index 0000000..e2caaeb
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/graph/DefaultProjectDependencyGraphTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.maven.graph;
+
+import junit.framework.TestCase;
+import org.apache.maven.execution.ProjectDependencyGraph;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.project.DuplicateProjectException;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.dag.CycleDetectedException;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class DefaultProjectDependencyGraphTest
+ extends TestCase
+{
+
+ private final MavenProject aProject = createA();
+
+ private final MavenProject depender1 = createProject( Arrays.asList( toDependency( aProject ) ), "depender1" );
+
+ private final MavenProject depender2 = createProject( Arrays.asList( toDependency( aProject ) ), "depender2" );
+
+ private final MavenProject depender3 = createProject( Arrays.asList( toDependency( aProject ) ), "depender3" );
+
+ private final MavenProject depender4 =
+ createProject( Arrays.asList( toDependency( aProject ), toDependency( depender3 ) ), "depender4" );
+
+ private final MavenProject transitiveOnly =
+ createProject( Arrays.asList( toDependency( depender3 ) ), "depender5" );
+
+ public void testGetSortedProjects()
+ throws DuplicateProjectException, CycleDetectedException
+ {
+ ProjectDependencyGraph graph = new DefaultProjectDependencyGraph( Arrays.asList( depender1, aProject ) );
+ final List<MavenProject> sortedProjects = graph.getSortedProjects();
+ assertEquals( aProject, sortedProjects.get( 0 ) );
+ assertEquals( depender1, sortedProjects.get( 1 ) );
+ }
+
+ public void testVerifyExpectedParentStructure()
+ throws CycleDetectedException, DuplicateProjectException
+ {
+ // This test verifies the baseline structure used in susequent tests. If this fails, the rest will fail.
+ ProjectDependencyGraph graph = threeProjectsDependingOnASingle();
+ final List<MavenProject> sortedProjects = graph.getSortedProjects();
+ assertEquals( aProject, sortedProjects.get( 0 ) );
+ assertEquals( depender1, sortedProjects.get( 1 ) );
+ assertEquals( depender2, sortedProjects.get( 2 ) );
+ assertEquals( depender3, sortedProjects.get( 3 ) );
+ }
+
+ public void testVerifyThatDownsteamProjectsComeInSortedOrder()
+ throws CycleDetectedException, DuplicateProjectException
+ {
+ final List<MavenProject> downstreamProjects =
+ threeProjectsDependingOnASingle().getDownstreamProjects( aProject, true );
+ assertEquals( depender1, downstreamProjects.get( 0 ) );
+ assertEquals( depender2, downstreamProjects.get( 1 ) );
+ assertEquals( depender3, downstreamProjects.get( 2 ) );
+ }
+
+ public void testTransitivesInOrder()
+ throws CycleDetectedException, DuplicateProjectException
+ {
+ final ProjectDependencyGraph graph =
+ new DefaultProjectDependencyGraph( Arrays.asList( depender1, depender4, depender2, depender3, aProject ) );
+
+ final List<MavenProject> downstreamProjects = graph.getDownstreamProjects( aProject, true );
+ assertEquals( depender1, downstreamProjects.get( 0 ) );
+ assertEquals( depender3, downstreamProjects.get( 1 ) );
+ assertEquals( depender4, downstreamProjects.get( 2 ) );
+ assertEquals( depender2, downstreamProjects.get( 3 ) );
+ }
+
+ public void testNonTransitivesInOrder()
+ throws CycleDetectedException, DuplicateProjectException
+ {
+ final ProjectDependencyGraph graph =
+ new DefaultProjectDependencyGraph( Arrays.asList( depender1, depender4, depender2, depender3, aProject ) );
+
+ final List<MavenProject> downstreamProjects = graph.getDownstreamProjects( aProject, false );
+ assertEquals( depender1, downstreamProjects.get( 0 ) );
+ assertEquals( depender3, downstreamProjects.get( 1 ) );
+ assertEquals( depender4, downstreamProjects.get( 2 ) );
+ assertEquals( depender2, downstreamProjects.get( 3 ) );
+ }
+
+ public void testWithTranistiveOnly()
+ throws CycleDetectedException, DuplicateProjectException
+ {
+ final ProjectDependencyGraph graph = new DefaultProjectDependencyGraph(
+ Arrays.asList( depender1, transitiveOnly, depender2, depender3, aProject ) );
+
+ final List<MavenProject> downstreamProjects = graph.getDownstreamProjects( aProject, true );
+ assertEquals( depender1, downstreamProjects.get( 0 ) );
+ assertEquals( depender3, downstreamProjects.get( 1 ) );
+ assertEquals( transitiveOnly, downstreamProjects.get( 2 ) );
+ assertEquals( depender2, downstreamProjects.get( 3 ) );
+ }
+
+ public void testWithMissingTranistiveOnly()
+ throws CycleDetectedException, DuplicateProjectException
+ {
+ final ProjectDependencyGraph graph = new DefaultProjectDependencyGraph(
+ Arrays.asList( depender1, transitiveOnly, depender2, depender3, aProject ) );
+
+ final List<MavenProject> downstreamProjects = graph.getDownstreamProjects( aProject, false );
+ assertEquals( depender1, downstreamProjects.get( 0 ) );
+ assertEquals( depender3, downstreamProjects.get( 1 ) );
+ assertEquals( depender2, downstreamProjects.get( 2 ) );
+ }
+
+ public void testGetUpstreamProjects()
+ throws CycleDetectedException, DuplicateProjectException
+ {
+ ProjectDependencyGraph graph = threeProjectsDependingOnASingle();
+ final List<MavenProject> downstreamProjects = graph.getUpstreamProjects( depender1, true );
+ assertEquals( aProject, downstreamProjects.get( 0 ) );
+ }
+
+ private ProjectDependencyGraph threeProjectsDependingOnASingle()
+ throws CycleDetectedException, DuplicateProjectException
+ {
+ return new DefaultProjectDependencyGraph( Arrays.asList( depender1, depender2, depender3, aProject ) );
+ }
+
+ private static MavenProject createA()
+ {
+ MavenProject result = new MavenProject();
+ result.setGroupId( "org.apache" );
+ result.setArtifactId( "A" );
+ result.setVersion( "1.2" );
+ return result;
+ }
+
+ static Dependency toDependency( MavenProject mavenProject )
+ {
+ final Dependency dependency = new Dependency();
+ dependency.setArtifactId( mavenProject.getArtifactId() );
+ dependency.setGroupId( mavenProject.getGroupId() );
+ dependency.setVersion( mavenProject.getVersion() );
+ return dependency;
+ }
+
+ private static MavenProject createProject( List<Dependency> dependencies, String artifactId )
+ {
+ MavenProject result = new MavenProject();
+ result.setGroupId( "org.apache" );
+ result.setArtifactId( artifactId );
+ result.setVersion( "1.2" );
+ result.setDependencies( dependencies );
+ return result;
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/maven/blob/be3fb200/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java
----------------------------------------------------------------------
diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java b/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java
index 04be08b..99b07e3 100644
--- a/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java
+++ b/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java
@@ -409,6 +409,11 @@ public class LifecycleExecutorTest
{
return Collections.emptyList();
}
+
+ public java.util.List<MavenProject> getAllSortedProjects()
+ {
+ return Collections.emptyList();
+ }
} );
final List<String> log = new ArrayList<String>();
http://git-wip-us.apache.org/repos/asf/maven/blob/be3fb200/maven-model-builder/pom.xml
----------------------------------------------------------------------
diff --git a/maven-model-builder/pom.xml b/maven-model-builder/pom.xml
index 738f64f..186e207 100644
--- a/maven-model-builder/pom.xml
+++ b/maven-model-builder/pom.xml
@@ -51,7 +51,10 @@
<groupId>org.apache.maven</groupId>
<artifactId>maven-builder-support</artifactId>
</dependency>
-
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
<dependency>
<groupId>org.eclipse.sisu</groupId>
<artifactId>org.eclipse.sisu.plexus</artifactId>
http://git-wip-us.apache.org/repos/asf/maven/blob/be3fb200/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
----------------------------------------------------------------------
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
index 80effb1..52b3c9c 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
@@ -19,6 +19,10 @@ package org.apache.maven.model.building;
* under the License.
*/
+
+import static org.apache.maven.model.building.Result.error;
+import static org.apache.maven.model.building.Result.newResult;
+
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -63,6 +67,7 @@ import org.apache.maven.model.profile.ProfileSelector;
import org.apache.maven.model.resolution.InvalidRepositoryException;
import org.apache.maven.model.resolution.ModelResolver;
import org.apache.maven.model.resolution.UnresolvableModelException;
+import org.apache.maven.model.resolution.WorkspaceModelResolver;
import org.apache.maven.model.superpom.SuperPomProvider;
import org.apache.maven.model.validation.ModelValidator;
import org.codehaus.plexus.component.annotations.Component;
@@ -241,8 +246,8 @@ public class DefaultModelBuilder
DefaultProfileActivationContext profileActivationContext = getProfileActivationContext( request );
problems.setSource( "(external profiles)" );
- List<Profile> activeExternalProfiles =
- profileSelector.getActiveProfiles( request.getProfiles(), profileActivationContext, problems );
+ List<Profile> activeExternalProfiles = profileSelector.getActiveProfiles( request.getProfiles(),
+ profileActivationContext, problems );
result.setActiveExternalProfiles( activeExternalProfiles );
@@ -258,7 +263,11 @@ public class DefaultModelBuilder
}
// read and validate raw model
- Model inputModel = readModel( request.getModelSource(), request.getPomFile(), request, problems );
+ Model inputModel = request.getRawModel();
+ if ( inputModel == null )
+ {
+ inputModel = readModel( request.getModelSource(), request.getPomFile(), request, problems );
+ }
problems.setRootModel( inputModel );
@@ -272,11 +281,12 @@ public class DefaultModelBuilder
{
lineage.add( currentData );
- Model tmpModel = currentData.getModel();
-
- Model rawModel = tmpModel.clone();
+ Model rawModel = currentData.getModel();
currentData.setRawModel( rawModel );
+ Model tmpModel = rawModel.clone();
+ currentData.setModel( tmpModel );
+
problems.setSource( tmpModel );
// model normalization
@@ -284,8 +294,8 @@ public class DefaultModelBuilder
profileActivationContext.setProjectProperties( tmpModel.getProperties() );
- List<Profile> activePomProfiles =
- profileSelector.getActiveProfiles( rawModel.getProfiles(), profileActivationContext, problems );
+ List<Profile> activePomProfiles = profileSelector.getActiveProfiles( rawModel.getProfiles(),
+ profileActivationContext, problems );
currentData.setActiveProfiles( activePomProfiles );
Map<String, Activation> interpolatedActivations = getProfileActivations( rawModel, false );
@@ -320,13 +330,13 @@ public class DefaultModelBuilder
}
else if ( currentData == resultData )
{ // First iteration - add initial parent id after version resolution.
- currentData.setGroupId( currentData.getRawModel().getGroupId() == null
- ? parentData.getGroupId()
- : currentData.getRawModel().getGroupId() );
+ currentData.setGroupId( currentData.getRawModel().getGroupId() == null ? parentData.getGroupId()
+ : currentData.getRawModel()
+ .getGroupId() );
- currentData.setVersion( currentData.getRawModel().getVersion() == null
- ? parentData.getVersion()
- : currentData.getRawModel().getVersion() );
+ currentData.setVersion( currentData.getRawModel().getVersion() == null ? parentData.getVersion()
+ : currentData.getRawModel()
+ .getVersion() );
currentData.setArtifactId( currentData.getRawModel().getArtifactId() );
parentIds.add( currentData.getId() );
@@ -345,9 +355,8 @@ public class DefaultModelBuilder
}
message += parentData.getId();
- problems.add(
- new ModelProblemCollectorRequest( ModelProblem.Severity.FATAL, ModelProblem.Version.BASE ).
- setMessage( message ) );
+ problems.add( new ModelProblemCollectorRequest( ModelProblem.Severity.FATAL, ModelProblem.Version.BASE )
+ .setMessage( message ) );
throw problems.newModelBuildingException();
}
@@ -376,7 +385,7 @@ public class DefaultModelBuilder
modelUrlNormalizer.normalize( resultModel, request );
// Now the fully interpolated model is available: reconfigure the resolver
- configureResolver( request.getModelResolver(), resultModel, problems , true );
+ configureResolver( request.getModelResolver(), resultModel, problems, true );
resultData.setGroupId( resultModel.getGroupId() );
resultData.setArtifactId( resultModel.getArtifactId() );
@@ -469,6 +478,23 @@ public class DefaultModelBuilder
return result;
}
+ @Override
+ public Result<? extends Model> buildRawModel( File pomFile, int validationLevel, boolean locationTracking )
+ {
+ final ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel( validationLevel )
+ .setLocationTracking( locationTracking );
+ final DefaultModelProblemCollector collector =
+ new DefaultModelProblemCollector( new DefaultModelBuildingResult() );
+ try
+ {
+ return newResult( readModel( null, pomFile, request, collector ), collector.getProblems() );
+ }
+ catch ( ModelBuildingException e )
+ {
+ return error( collector.getProblems() );
+ }
+ }
+
private Model readModel( ModelSource modelSource, File pomFile, ModelBuildingRequest request,
DefaultModelProblemCollector problems )
throws ModelBuildingException
@@ -524,14 +550,14 @@ public class DefaultModelBuilder
if ( pomFile != null )
{
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.V20 )
- .setMessage( "Malformed POM " + modelSource.getLocation() + ": " + e.getMessage() )
- .setException( e ) );
+ .setMessage( "Malformed POM " + modelSource.getLocation() + ": " + e.getMessage() )
+ .setException( e ) );
}
else
{
problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.V20 )
- .setMessage( "Malformed POM " + modelSource.getLocation() + ": " + e.getMessage() )
- .setException( e ) );
+ .setMessage( "Malformed POM " + modelSource.getLocation() + ": " + e.getMessage() )
+ .setException( e ) );
}
}
@@ -544,8 +570,8 @@ public class DefaultModelBuilder
catch ( ModelParseException e )
{
problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
- .setMessage( "Non-parseable POM " + modelSource.getLocation() + ": " + e.getMessage() )
- .setException( e ) );
+ .setMessage( "Non-parseable POM " + modelSource.getLocation() + ": " + e.getMessage() )
+ .setException( e ) );
throw problems.newModelBuildingException();
}
catch ( IOException e )
@@ -564,8 +590,7 @@ public class DefaultModelBuilder
}
}
problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
- .setMessage( "Non-readable POM " + modelSource.getLocation() + ": " + msg )
- .setException( e ) );
+ .setMessage( "Non-readable POM " + modelSource.getLocation() + ": " + msg ).setException( e ) );
throw problems.newModelBuildingException();
}
@@ -621,9 +646,8 @@ public class DefaultModelBuilder
catch ( InvalidRepositoryException e )
{
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
- .setMessage( "Invalid repository " + repository.getId() + ": " + e.getMessage() )
- .setLocation( repository.getLocation( "" ) )
- .setException( e ) );
+ .setMessage( "Invalid repository " + repository.getId() + ": " + e.getMessage() )
+ .setLocation( repository.getLocation( "" ) ).setException( e ) );
}
}
}
@@ -675,7 +699,8 @@ public class DefaultModelBuilder
if ( versions.get( key ) == null && managedVersions.get( key ) == null )
{
InputLocation location = plugins.get( key ).getLocation( "" );
- problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.V20 )
+ problems
+ .add( new ModelProblemCollectorRequest( Severity.WARNING, Version.V20 )
.setMessage( "'build.plugins.plugin.version' for " + key + " is missing." )
.setLocation( location ) );
}
@@ -800,9 +825,9 @@ public class DefaultModelBuilder
if ( !"pom".equals( parentModel.getPackaging() ) )
{
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
- .setMessage( "Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint( parentModel )
+ .setMessage( "Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint( parentModel )
+ ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"" )
- .setLocation( parentModel.getLocation( "packaging" ) ) );
+ .setLocation( parentModel.getLocation( "packaging" ) ) );
}
}
else
@@ -817,20 +842,52 @@ public class DefaultModelBuilder
DefaultModelProblemCollector problems )
throws ModelBuildingException
{
- ModelSource candidateSource = getParentPomFile( childModel, childSource );
-
- if ( candidateSource == null )
+ final Parent parent = childModel.getParent();
+ final ModelSource candidateSource;
+ final Model candidateModel;
+ final WorkspaceModelResolver resolver = request.getWorkspaceModelResolver();
+ if ( resolver == null )
{
- return null;
- }
+ candidateSource = getParentPomFile( childModel, childSource );
+
+ if ( candidateSource == null )
+ {
+ return null;
+ }
+
+ File pomFile = null;
+ if ( candidateSource instanceof FileModelSource )
+ {
+ pomFile = ( (FileModelSource) candidateSource ).getPomFile();
+ }
- File pomFile = null;
- if ( candidateSource instanceof FileModelSource )
+ candidateModel = readModel( candidateSource, pomFile, request, problems );
+ }
+ else
{
- pomFile = ( (FileModelSource) candidateSource ).getPomFile();
+ try
+ {
+ candidateModel =
+ resolver.resolveRawModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() );
+ }
+ catch ( UnresolvableModelException e )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE ) //
+ .setMessage( e.getMessage().toString() ).setLocation( parent.getLocation( "" ) ).setException( e ) );
+ throw problems.newModelBuildingException();
+ }
+ if ( candidateModel == null )
+ {
+ return null;
+ }
+ candidateSource = new FileModelSource( candidateModel.getPomFile() );
}
- Model candidateModel = readModel( candidateSource, pomFile, request, problems );
+ //
+ // TODO:jvz Why isn't all this checking the job of the duty of the workspace resolver, we know that we
+ // have a model that is suitable, yet more checks are done here and the one for the version is problematic
+ // before because with parents as ranges it will never work in this scenario.
+ //
String groupId = candidateModel.getGroupId();
if ( groupId == null && candidateModel.getParent() != null )
@@ -844,8 +901,6 @@ public class DefaultModelBuilder
version = candidateModel.getParent().getVersion();
}
- Parent parent = childModel.getParent();
-
if ( groupId == null || !groupId.equals( parent.getGroupId() ) || artifactId == null
|| !artifactId.equals( parent.getArtifactId() ) )
{
@@ -861,15 +916,19 @@ public class DefaultModelBuilder
problems.setSource( childModel );
problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.BASE )
- .setMessage( buffer.toString() )
- .setLocation( parent.getLocation( "" ) ) );
- return null;
- }
- if ( version == null || !version.equals( parent.getVersion() ) )
- {
+ .setMessage( buffer.toString() ).setLocation( parent.getLocation( "" ) ) );
return null;
}
+ //
+ // Here we just need to know that a version is fine to use but this validation we can do in our workspace
+ // resolver.
+ //
+
+ /*
+ * if ( version == null || !version.equals( parent.getVersion() ) ) { return null; }
+ */
+
ModelData parentData = new ModelData( candidateSource, candidateModel, groupId, artifactId, version );
return parentData;
@@ -944,9 +1003,7 @@ public class DefaultModelBuilder
}
problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
- .setMessage( buffer.toString() )
- .setLocation( parent.getLocation( "" ) )
- .setException( e ) );
+ .setMessage( buffer.toString() ).setLocation( parent.getLocation( "" ) ).setException( e ) );
throw problems.newModelBuildingException();
}
@@ -969,18 +1026,17 @@ public class DefaultModelBuilder
{
if ( childModel.getVersion() == null )
{
- problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 ).
- setMessage( "Version must be a constant" ).
- setLocation( childModel.getLocation( "" ) ) );
+ problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
+ .setMessage( "Version must be a constant" ).setLocation( childModel.getLocation( "" ) ) );
}
else
{
if ( childModel.getVersion().indexOf( "${" ) > -1 )
{
- problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 ).
- setMessage( "Version must be a constant" ).
- setLocation( childModel.getLocation( "version" ) ) );
+ problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
+ .setMessage( "Version must be a constant" )
+ .setLocation( childModel.getLocation( "version" ) ) );
}
}
@@ -1013,7 +1069,8 @@ public class DefaultModelBuilder
importIds.add( importing );
- ModelResolver modelResolver = request.getModelResolver();
+ final WorkspaceModelResolver workspaceResolver = request.getWorkspaceModelResolver();
+ final ModelResolver modelResolver = request.getModelResolver();
ModelBuildingRequest importRequest = null;
@@ -1037,25 +1094,25 @@ public class DefaultModelBuilder
if ( groupId == null || groupId.length() <= 0 )
{
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
- .setMessage( "'dependencyManagement.dependencies.dependency.groupId' for "
- + dependency.getManagementKey() + " is missing." )
- .setLocation( dependency.getLocation( "" ) ) );
+ .setMessage( "'dependencyManagement.dependencies.dependency.groupId' for "
+ + dependency.getManagementKey() + " is missing." )
+ .setLocation( dependency.getLocation( "" ) ) );
continue;
}
if ( artifactId == null || artifactId.length() <= 0 )
{
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
- .setMessage( "'dependencyManagement.dependencies.dependency.artifactId' for "
- + dependency.getManagementKey() + " is missing." )
- .setLocation( dependency.getLocation( "" ) ) );
+ .setMessage( "'dependencyManagement.dependencies.dependency.artifactId' for "
+ + dependency.getManagementKey() + " is missing." )
+ .setLocation( dependency.getLocation( "" ) ) );
continue;
}
if ( version == null || version.length() <= 0 )
{
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
- .setMessage( "'dependencyManagement.dependencies.dependency.version' for "
- + dependency.getManagementKey() + " is missing." )
- .setLocation( dependency.getLocation( "" ) ) );
+ .setMessage( "'dependencyManagement.dependencies.dependency.version' for "
+ + dependency.getManagementKey() + " is missing." )
+ .setLocation( dependency.getLocation( "" ) ) );
continue;
}
@@ -1074,67 +1131,85 @@ public class DefaultModelBuilder
continue;
}
- DependencyManagement importMngt =
- getCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT );
+ DependencyManagement importMngt = getCache( request.getModelCache(), groupId, artifactId, version,
+ ModelCacheTag.IMPORT );
if ( importMngt == null )
{
- if ( modelResolver == null )
+ if ( workspaceResolver == null && modelResolver == null )
{
throw new IllegalArgumentException( "no model resolver provided, cannot resolve import POM "
+ ModelProblemUtils.toId( groupId, artifactId, version ) + " for POM "
+ ModelProblemUtils.toSourceHint( model ) );
}
- ModelSource importSource;
- try
+ Model importModel = null;
+ if ( workspaceResolver != null )
{
- importSource = modelResolver.resolveModel( groupId, artifactId, version );
+ try
+ {
+ importModel = workspaceResolver.resolveEffectiveModel( groupId, artifactId, version );
+ }
+ catch ( UnresolvableModelException e )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
+ .setMessage( e.getMessage().toString() ).setException( e ) );
+ continue;
+ }
}
- catch ( UnresolvableModelException e )
+
+ // no workspace resolver or workspace resolver returned null (i.e. model not in workspace)
+ if ( importModel == null )
{
- StringBuilder buffer = new StringBuilder( 256 );
- buffer.append( "Non-resolvable import POM" );
- if ( !containsCoordinates( e.getMessage(), groupId, artifactId, version ) )
+ final ModelSource importSource;
+ try
{
- buffer.append( " " ).append( ModelProblemUtils.toId( groupId, artifactId, version ) );
+ importSource = modelResolver.resolveModel( groupId, artifactId, version );
}
- buffer.append( ": " ).append( e.getMessage() );
+ catch ( UnresolvableModelException e )
+ {
+ StringBuilder buffer = new StringBuilder( 256 );
+ buffer.append( "Non-resolvable import POM" );
+ if ( !containsCoordinates( e.getMessage(), groupId, artifactId, version ) )
+ {
+ buffer.append( " " ).append( ModelProblemUtils.toId( groupId, artifactId, version ) );
+ }
+ buffer.append( ": " ).append( e.getMessage() );
- problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
- .setMessage( buffer.toString() )
- .setLocation( dependency.getLocation( "" ) )
+ problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
+ .setMessage( buffer.toString() ).setLocation( dependency.getLocation( "" ) )
.setException( e ) );
- continue;
- }
+ continue;
+ }
- if ( importRequest == null )
- {
- importRequest = new DefaultModelBuildingRequest();
- importRequest.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
- importRequest.setModelCache( request.getModelCache() );
- importRequest.setSystemProperties( request.getSystemProperties() );
- importRequest.setUserProperties( request.getUserProperties() );
- importRequest.setLocationTracking( request.isLocationTracking() );
- }
+ if ( importRequest == null )
+ {
+ importRequest = new DefaultModelBuildingRequest();
+ importRequest.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
+ importRequest.setModelCache( request.getModelCache() );
+ importRequest.setSystemProperties( request.getSystemProperties() );
+ importRequest.setUserProperties( request.getUserProperties() );
+ importRequest.setLocationTracking( request.isLocationTracking() );
+ }
- importRequest.setModelSource( importSource );
- importRequest.setModelResolver( modelResolver.newCopy() );
+ importRequest.setModelSource( importSource );
+ importRequest.setModelResolver( modelResolver.newCopy() );
- ModelBuildingResult importResult;
- try
- {
- importResult = build( importRequest );
- }
- catch ( ModelBuildingException e )
- {
- problems.addAll( e.getProblems() );
- continue;
- }
+ final ModelBuildingResult importResult;
+ try
+ {
+ importResult = build( importRequest );
+ }
+ catch ( ModelBuildingException e )
+ {
+ problems.addAll( e.getProblems() );
+ continue;
+ }
- problems.addAll( importResult.getProblems() );
+ problems.addAll( importResult.getProblems() );
- Model importModel = importResult.getEffectiveModel();
+ importModel = importResult.getEffectiveModel();
+ }
importMngt = importModel.getDependencyManagement();
http://git-wip-us.apache.org/repos/asf/maven/blob/be3fb200/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java
----------------------------------------------------------------------
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java
index bd4211a..8b4a01b 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java
@@ -25,8 +25,10 @@ import java.util.Date;
import java.util.List;
import java.util.Properties;
+import org.apache.maven.model.Model;
import org.apache.maven.model.Profile;
import org.apache.maven.model.resolution.ModelResolver;
+import org.apache.maven.model.resolution.WorkspaceModelResolver;
/**
* Collects settings that control building of effective models.
@@ -37,6 +39,8 @@ public class DefaultModelBuildingRequest
implements ModelBuildingRequest
{
+ private Model rawModel;
+
private File pomFile;
private ModelSource modelSource;
@@ -67,6 +71,8 @@ public class DefaultModelBuildingRequest
private ModelCache modelCache;
+ private WorkspaceModelResolver workspaceResolver;
+
/**
* Creates an empty request.
*/
@@ -373,4 +379,30 @@ public class DefaultModelBuildingRequest
return this;
}
+ @Override
+ public Model getRawModel()
+ {
+ return rawModel;
+ }
+
+ @Override
+ public ModelBuildingRequest setRawModel( Model rawModel )
+ {
+ this.rawModel = rawModel;
+ return this;
+ }
+
+ @Override
+ public WorkspaceModelResolver getWorkspaceModelResolver()
+ {
+ return workspaceResolver;
+ }
+
+ @Override
+ public ModelBuildingRequest setWorkspaceModelResolver( WorkspaceModelResolver workspaceResolver )
+ {
+ this.workspaceResolver = workspaceResolver;
+ return this;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/maven/blob/be3fb200/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java
----------------------------------------------------------------------
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java
index 7074689..c5c2cbf 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java
@@ -24,8 +24,10 @@ import java.util.Date;
import java.util.List;
import java.util.Properties;
+import org.apache.maven.model.Model;
import org.apache.maven.model.Profile;
import org.apache.maven.model.resolution.ModelResolver;
+import org.apache.maven.model.resolution.WorkspaceModelResolver;
/**
* A model building request that delegates all methods invocations to another request, meant for easy transformations by
@@ -254,4 +256,30 @@ class FilterModelBuildingRequest
return this;
}
-}
+ @Override
+ public Model getRawModel()
+ {
+ return request.getRawModel();
+ }
+
+ @Override
+ public ModelBuildingRequest setRawModel( Model rawModel )
+ {
+ request.setRawModel( rawModel );
+ return this;
+ }
+
+ @Override
+ public WorkspaceModelResolver getWorkspaceModelResolver()
+ {
+ return request.getWorkspaceModelResolver();
+ }
+
+ @Override
+ public ModelBuildingRequest setWorkspaceModelResolver( WorkspaceModelResolver workspaceResolver )
+ {
+ request.setWorkspaceModelResolver( workspaceResolver );
+ return this;
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/maven/blob/be3fb200/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java
----------------------------------------------------------------------
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java
index c6c75f9..2a49a21 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java
@@ -19,6 +19,10 @@ package org.apache.maven.model.building;
* under the License.
*/
+import java.io.File;
+
+import org.apache.maven.model.Model;
+
/**
* Builds the effective model from a POM.
*
@@ -51,4 +55,13 @@ public interface ModelBuilder
ModelBuildingResult build( ModelBuildingRequest request, ModelBuildingResult result )
throws ModelBuildingException;
+ /**
+ * Performs only the part of {@link ModelBuilder#build(ModelBuildingRequest)} that loads the raw model
+ *
+ * @param request
+ * @return
+ * @throws ModelBuildingException
+ */
+ Result<? extends Model> buildRawModel( File pomFile, int validationLevel, boolean locationTracking );
+
}
http://git-wip-us.apache.org/repos/asf/maven/blob/be3fb200/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java
----------------------------------------------------------------------
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java
index 2a3a25a..c10274d 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java
@@ -24,8 +24,10 @@ import java.util.Date;
import java.util.List;
import java.util.Properties;
+import org.apache.maven.model.Model;
import org.apache.maven.model.Profile;
import org.apache.maven.model.resolution.ModelResolver;
+import org.apache.maven.model.resolution.WorkspaceModelResolver;
/**
* Collects settings that control the building of effective models.
@@ -63,6 +65,20 @@ public interface ModelBuildingRequest
int VALIDATION_LEVEL_STRICT = VALIDATION_LEVEL_MAVEN_3_0;
/**
+ * Gets the raw model to build. If not set, model source will be used to load raw model.
+ *
+ * @return The raw model to build or {@code null} if not set.
+ */
+ Model getRawModel();
+
+ /**
+ * Set raw model.
+ *
+ * @param model
+ */
+ ModelBuildingRequest setRawModel( Model rawModel );
+
+ /**
* Gets the source of the POM to process.
*
* @return The source of the POM or {@code null} if not set.
@@ -315,4 +331,8 @@ public interface ModelBuildingRequest
*/
ModelBuildingRequest setModelCache( ModelCache modelCache );
-}
+ WorkspaceModelResolver getWorkspaceModelResolver();
+
+ ModelBuildingRequest setWorkspaceModelResolver( WorkspaceModelResolver workspaceResolver );
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/maven/blob/be3fb200/maven-model-builder/src/main/java/org/apache/maven/model/building/Result.java
----------------------------------------------------------------------
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/Result.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/Result.java
new file mode 100644
index 0000000..a962897
--- /dev/null
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/Result.java
@@ -0,0 +1,255 @@
+package org.apache.maven.model.building;
+
+/*
+ * 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.
+ */
+
+import static com.google.common.base.Predicates.in;
+import static com.google.common.collect.Iterables.any;
+import static com.google.common.collect.Iterables.concat;
+import static com.google.common.collect.Iterables.transform;
+import static java.util.Collections.singleton;
+import static java.util.EnumSet.of;
+import static org.apache.maven.model.building.ModelProblem.Severity.ERROR;
+import static org.apache.maven.model.building.ModelProblem.Severity.FATAL;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.apache.maven.model.building.ModelProblem.Severity;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+
+/**
+ * There are various forms of results that are represented by this class:
+ * <ol>
+ * <li>success - in which case only the model field is set
+ * <li>success with warnings - model field + non-error model problems
+ * <li>error - no model, but diagnostics
+ * <li>error - (partial) model and diagnostics
+ * </ol>
+ * Could encode these variants as subclasses, but kept in one for now
+ *
+ * @author bbusjaeger
+ * @param <T>
+ */
+public class Result<T>
+{
+
+ /**
+ * Success without warnings
+ *
+ * @param model
+ * @return
+ */
+ public static <T> Result<T> success( T model )
+ {
+ return success( model, Collections.<ModelProblem>emptyList() );
+ }
+
+ /**
+ * Success with warnings
+ *
+ * @param model
+ * @param problems
+ * @return
+ */
+ public static <T> Result<T> success( T model, Iterable<? extends ModelProblem> problems )
+ {
+ assert !hasErrors( problems );
+ return new Result<T>( false, model, problems );
+ }
+
+ /**
+ * Success with warnings
+ *
+ * @param model
+ * @param results
+ * @return
+ */
+ public static <T> Result<T> success( T model, Result<?>... results )
+ {
+ return success( model, Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) );
+ }
+
+ /**
+ * Error with problems describing the cause
+ *
+ * @param problems
+ * @return
+ */
+ public static <T> Result<T> error( Iterable<? extends ModelProblem> problems )
+ {
+ return error( null, problems );
+ }
+
+ public static <T> Result<T> error( T model )
+ {
+ return error( model, Collections.<ModelProblem>emptyList() );
+ }
+
+ public static <T> Result<T> error( Result<?> result )
+ {
+ return error( result.getProblems() );
+ }
+
+ public static <T> Result<T> error( Result<?>... results )
+ {
+ return error( Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) );
+ }
+
+ /**
+ * Error with partial result and problems describing the cause
+ *
+ * @param model
+ * @param problems
+ * @return
+ */
+ public static <T> Result<T> error( T model, Iterable<? extends ModelProblem> problems )
+ {
+ return new Result<T>( true, model, problems );
+ }
+
+ /**
+ * New result - determine whether error or success by checking problems for errors
+ *
+ * @param model
+ * @param problems
+ * @return
+ */
+ public static <T> Result<T> newResult( T model, Iterable<? extends ModelProblem> problems )
+ {
+ return new Result<T>( hasErrors( problems ), model, problems );
+ }
+
+ /**
+ * New result consisting of given result and new problem. Convenience for newResult(result.get(),
+ * concat(result.getProblems(),problems)).
+ *
+ * @param result
+ * @param problem
+ * @return
+ */
+ public static <T> Result<T> addProblem( Result<T> result, ModelProblem problem )
+ {
+ return addProblems( result, singleton( problem ) );
+ }
+
+ /**
+ * New result that includes the given
+ *
+ * @param result
+ * @param problems
+ * @return
+ */
+ public static <T> Result<T> addProblems( Result<T> result, Iterable<? extends ModelProblem> problems )
+ {
+ return new Result<T>( result.hasErrors() || hasErrors( problems ), result.get(), concat( result.getProblems(),
+ problems ) );
+ }
+
+ public static <T> Result<T> addProblems( Result<T> result, Result<?>... results )
+ {
+ return addProblems( result, Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) );
+ }
+
+ /**
+ * Turns the given results into a single result by combining problems and models into single collection.
+ *
+ * @param results
+ * @return
+ */
+ public static <T> Result<Iterable<T>> newResultSet( Iterable<? extends Result<? extends T>> results )
+ {
+ final boolean hasErrors = any( transform( results, new Function<Result<?>, Boolean>()
+ {
+ @Override
+ public Boolean apply( Result<?> input )
+ {
+ return input.hasErrors();
+ }
+ } ), Predicates.equalTo( true ) );
+ final Iterable<T> models = transform( results, new Function<Result<? extends T>, T>()
+ {
+ @Override
+ public T apply( Result<? extends T> input )
+ {
+ return input.get();
+ }
+ } );
+ final Iterable<ModelProblem> problems = concat( transform( results, GET_PROBLEMS ) );
+ return new Result<Iterable<T>>( hasErrors, models, problems );
+ }
+
+ // helper to determine if problems contain error
+ private static boolean hasErrors( Iterable<? extends ModelProblem> problems )
+ {
+ return any( transform( problems, new Function<ModelProblem, Severity>()
+ {
+ @Override
+ public Severity apply( ModelProblem input )
+ {
+ return input.getSeverity();
+ }
+ } ), in( of( ERROR, FATAL ) ) );
+ }
+
+ /**
+ * Class definition
+ */
+
+ private final boolean errors;
+
+ private final T value;
+
+ private final Iterable<? extends ModelProblem> problems;
+
+ private Result( boolean errors, T model, Iterable<? extends ModelProblem> problems )
+ {
+ this.errors = errors;
+ this.value = model;
+ this.problems = problems;
+ }
+
+ public Iterable<? extends ModelProblem> getProblems()
+ {
+ return problems;
+ }
+
+ public T get()
+ {
+ return value;
+ }
+
+ public boolean hasErrors()
+ {
+ return errors;
+ }
+
+ private static final Function<Result<?>, Iterable<? extends ModelProblem>> GET_PROBLEMS =
+ new Function<Result<?>, Iterable<? extends ModelProblem>>()
+ {
+ @Override
+ public Iterable<? extends ModelProblem> apply( Result<?> input )
+ {
+ return input.getProblems();
+ }
+ };
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/maven/blob/be3fb200/maven-model-builder/src/main/java/org/apache/maven/model/resolution/UnresolvableModelException.java
----------------------------------------------------------------------
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/UnresolvableModelException.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/UnresolvableModelException.java
index 733a276..bdb623a 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/UnresolvableModelException.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/UnresolvableModelException.java
@@ -78,6 +78,22 @@ public class UnresolvableModelException
}
/**
+ * Creates a new exception with specified cause
+ *
+ * @param cause
+ * @param groupId
+ * @param artifactId
+ * @param version
+ */
+ public UnresolvableModelException( Throwable cause, String groupId, String artifactId, String version )
+ {
+ super( cause );
+ this.groupId = groupId;
+ this.artifactId = artifactId;
+ this.version = version;
+ }
+
+ /**
* Gets the group id of the unresolvable model.
*
* @return The group id of the unresolvable model, can be empty but never {@code null}.
http://git-wip-us.apache.org/repos/asf/maven/blob/be3fb200/maven-model-builder/src/main/java/org/apache/maven/model/resolution/WorkspaceModelResolver.java
----------------------------------------------------------------------
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/WorkspaceModelResolver.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/WorkspaceModelResolver.java
new file mode 100644
index 0000000..d12edea
--- /dev/null
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/WorkspaceModelResolver.java
@@ -0,0 +1,33 @@
+package org.apache.maven.model.resolution;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.model.Model;
+
+public interface WorkspaceModelResolver
+{
+
+ Model resolveRawModel( String groupId, String artifactId, String versionConstraint )
+ throws UnresolvableModelException;
+
+ Model resolveEffectiveModel( String groupId, String artifactId, String versionConstraint )
+ throws UnresolvableModelException;
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/maven/blob/be3fb200/maven-model/src/main/mdo/maven.mdo
----------------------------------------------------------------------
diff --git a/maven-model/src/main/mdo/maven.mdo b/maven-model/src/main/mdo/maven.mdo
index 43bdb7e..2821ea6 100644
--- a/maven-model/src/main/mdo/maven.mdo
+++ b/maven-model/src/main/mdo/maven.mdo
@@ -1466,12 +1466,18 @@
<version>4.0.0+</version>
<code>
<![CDATA[
+ private String managementKey;
+
/**
* @return the management key as <code>groupId:artifactId:type</code>
*/
public String getManagementKey()
{
- return groupId + ":" + artifactId + ":" + type + ( classifier != null ? ":" + classifier : "" );
+ if ( managementKey == null )
+ {
+ managementKey = groupId + ":" + artifactId + ":" + type + ( classifier != null ? ":" + classifier : "" );
+ }
+ return managementKey;
}
]]>
</code>