diff --git a/maven-core/pom.xml b/maven-core/pom.xml
index da100be1e1..70d5a0b1c6 100644
--- a/maven-core/pom.xml
+++ b/maven-core/pom.xml
@@ -31,6 +31,11 @@ under the License.
maven-core
Maven Core
+
+ org.apache.maven
+ maven-workspace
+ 2.1-SNAPSHOT
+
org.apache.maven
maven-lifecycle
diff --git a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java
index 93b2d62811..d87f4e07d1 100644
--- a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java
+++ b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java
@@ -22,6 +22,7 @@ package org.apache.maven.execution;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.errors.CoreErrorReporter;
import org.apache.maven.monitor.event.EventMonitor;
+import org.apache.maven.monitor.event.MavenWorkspaceMonitor;
import org.apache.maven.profiles.ProfileManager;
import org.apache.maven.profiles.activation.ProfileActivationContext;
import org.apache.maven.realm.MavenRealmManager;
@@ -97,6 +98,8 @@ public class DefaultMavenExecutionRequest
private List eventMonitors;
+ private MavenWorkspaceMonitor workspaceMonitor;
+
private List activeProfiles;
private List inactiveProfiles;
@@ -694,4 +697,15 @@ public class DefaultMavenExecutionRequest
this.profileActivationContext = profileActivationContext;
return this;
}
+
+ public MavenWorkspaceMonitor getWorkspaceMonitor()
+ {
+ return workspaceMonitor;
+ }
+
+ public MavenExecutionRequest setWorkspaceMonitor( MavenWorkspaceMonitor workspaceMonitor )
+ {
+ this.workspaceMonitor = workspaceMonitor;
+ return this;
+ }
}
diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java
index ae43d37ae6..9706eed8b6 100644
--- a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java
+++ b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java
@@ -23,6 +23,7 @@ import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import org.apache.maven.errors.CoreErrorReporter;
import org.apache.maven.monitor.event.EventMonitor;
+import org.apache.maven.monitor.event.MavenWorkspaceMonitor;
import org.apache.maven.profiles.ProfileManager;
import org.apache.maven.profiles.activation.ProfileActivationContext;
import org.apache.maven.realm.MavenRealmManager;
@@ -216,4 +217,7 @@ public interface MavenExecutionRequest
MavenExecutionRequest setErrorReporter( CoreErrorReporter reporter );
CoreErrorReporter getErrorReporter();
+
+ MavenExecutionRequest setWorkspaceMonitor( MavenWorkspaceMonitor workspaceMonitor );
+ MavenWorkspaceMonitor getWorkspaceMonitor();
}
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java b/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java
index 2810f60bd3..6e9ecbe21b 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java
@@ -305,7 +305,10 @@ public class DefaultLifecycleExecutor
}
}
- dispatcher.dispatchEnd( MavenEvents.PHASE_EXECUTION, currentPhase );
+ if ( currentPhase != null )
+ {
+ dispatcher.dispatchEnd( MavenEvents.PHASE_EXECUTION, currentPhase );
+ }
}
finally
{
diff --git a/maven-core/src/main/java/org/apache/maven/monitor/event/AbstractEmbedderLifecycleMonitor.java b/maven-core/src/main/java/org/apache/maven/monitor/event/AbstractEmbedderLifecycleMonitor.java
new file mode 100644
index 0000000000..93e9d990d5
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/monitor/event/AbstractEmbedderLifecycleMonitor.java
@@ -0,0 +1,62 @@
+package org.apache.maven.monitor.event;
+
+
+public abstract class AbstractEmbedderLifecycleMonitor
+ extends AbstractSelectiveEventMonitor implements MavenEmbedderLifecycleMonitor
+{
+
+ public static final String[] EMBEDDER_LIFECYCLE_EVENTS = {
+ MavenEvents.EMBEDDER_LIFECYCLE,
+ MavenEvents.EMBEDDER_METHOD
+ };
+
+ protected AbstractEmbedderLifecycleMonitor()
+ {
+ super( EMBEDDER_LIFECYCLE_EVENTS, EMBEDDER_LIFECYCLE_EVENTS, MavenEvents.NO_EVENTS );
+ }
+
+ public void embedderInitialized( long timestamp )
+ {
+ }
+
+ public void embedderStopped( long timestamp )
+ {
+ }
+
+ public void embedderMethodStarted( String method, long timestamp )
+ {
+ }
+
+ public void embedderMethodEnded( String method, long timestamp )
+ {
+ }
+
+ protected void doEndEvent( String eventName,
+ String target,
+ long timestamp )
+ {
+ if ( MavenEvents.EMBEDDER_LIFECYCLE.equals( eventName ) )
+ {
+ embedderStopped( timestamp );
+ }
+ else if ( MavenEvents.EMBEDDER_METHOD.equals( eventName ) )
+ {
+ embedderMethodEnded( target, timestamp );
+ }
+ }
+
+ protected void doStartEvent( String eventName,
+ String target,
+ long timestamp )
+ {
+ if ( MavenEvents.EMBEDDER_LIFECYCLE.equals( eventName ) )
+ {
+ embedderInitialized( timestamp );
+ }
+ else if ( MavenEvents.EMBEDDER_METHOD.equals( eventName ) )
+ {
+ embedderMethodStarted( target, timestamp );
+ }
+ }
+
+}
diff --git a/maven-core/src/main/java/org/apache/maven/monitor/event/AbstractWorkspaceMonitor.java b/maven-core/src/main/java/org/apache/maven/monitor/event/AbstractWorkspaceMonitor.java
new file mode 100644
index 0000000000..91c7538686
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/monitor/event/AbstractWorkspaceMonitor.java
@@ -0,0 +1,25 @@
+package org.apache.maven.monitor.event;
+
+import org.apache.maven.workspace.MavenWorkspaceStore;
+
+public abstract class AbstractWorkspaceMonitor
+ extends AbstractEmbedderLifecycleMonitor
+ implements MavenWorkspaceMonitor
+{
+
+ private MavenWorkspaceStore workspaceManager;
+
+ public void setWorkspaceStore( MavenWorkspaceStore workspaceManager )
+ {
+ this.workspaceManager = workspaceManager;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.maven.embedder.lifecycle.MavenWorkspaceMonitor#clearCache()
+ */
+ public void clearCache()
+ {
+ workspaceManager.clear();
+ }
+
+}
\ No newline at end of file
diff --git a/maven-core/src/main/java/org/apache/maven/monitor/event/MavenEmbedderLifecycleMonitor.java b/maven-core/src/main/java/org/apache/maven/monitor/event/MavenEmbedderLifecycleMonitor.java
new file mode 100644
index 0000000000..665630f0b7
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/monitor/event/MavenEmbedderLifecycleMonitor.java
@@ -0,0 +1,16 @@
+package org.apache.maven.monitor.event;
+
+public interface MavenEmbedderLifecycleMonitor
+{
+
+ public void embedderInitialized( long timestamp );
+
+ public void embedderStopped( long timestamp );
+
+ public void embedderMethodStarted( String method,
+ long timestamp );
+
+ public void embedderMethodEnded( String method,
+ long timestamp );
+
+}
\ No newline at end of file
diff --git a/maven-core/src/main/java/org/apache/maven/monitor/event/MavenWorkspaceMonitor.java b/maven-core/src/main/java/org/apache/maven/monitor/event/MavenWorkspaceMonitor.java
new file mode 100644
index 0000000000..c0cbc84ccd
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/monitor/event/MavenWorkspaceMonitor.java
@@ -0,0 +1,13 @@
+package org.apache.maven.monitor.event;
+
+import org.apache.maven.workspace.MavenWorkspaceStore;
+
+public interface MavenWorkspaceMonitor
+ extends EventMonitor
+{
+
+ void setWorkspaceStore( MavenWorkspaceStore workspaceStore );
+
+ void clearCache();
+
+}
diff --git a/maven-core/src/main/java/org/apache/maven/monitor/event/PerCallWorkspaceMonitor.java b/maven-core/src/main/java/org/apache/maven/monitor/event/PerCallWorkspaceMonitor.java
new file mode 100644
index 0000000000..e0aea4fd87
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/monitor/event/PerCallWorkspaceMonitor.java
@@ -0,0 +1,23 @@
+package org.apache.maven.monitor.event;
+
+
+
+public class PerCallWorkspaceMonitor
+ extends AbstractWorkspaceMonitor
+{
+
+ public void embedderMethodEnded( String method,
+ long timestamp )
+ {
+ clearCache();
+ }
+
+ // Be double-sure that the cache is cleared when the embedder stops.
+ public void embedderStopped( long timestamp )
+ {
+ clearCache();
+ }
+
+
+
+}
diff --git a/maven-core/src/test/java/org/apache/maven/extension/DefaultExtensionManagerTest.java b/maven-core/src/test/java/org/apache/maven/extension/DefaultExtensionManagerTest.java
index 7837afb0fd..e8f8451ade 100644
--- a/maven-core/src/test/java/org/apache/maven/extension/DefaultExtensionManagerTest.java
+++ b/maven-core/src/test/java/org/apache/maven/extension/DefaultExtensionManagerTest.java
@@ -102,6 +102,7 @@ public class DefaultExtensionManagerTest
public void test_addExtension_usingModel_ShouldLoadExtensionComponent()
throws Exception
{
+ System.out.println( "\n\n\n\n\n\n\nSTART\n\n" );
File remoteRepoDir = findRemoteRepositoryDirectory();
File localRepo = createTempDir();
@@ -147,6 +148,8 @@ public class DefaultExtensionManagerTest
assertNotNull( result );
getContainer().setLookupRealm( oldRealm );
+
+ System.out.println( "\n\nEND\n\n\n\n\n\n\n" );
}
public void test_addExtension_usingModel_ShouldLoadCustomLifecycleMappingAndArtifactHandler()
diff --git a/maven-embedder/src/main/aspect/org/apache/maven/embedder/cache/CacheCleanerAspect.aj b/maven-embedder/src/main/aspect/org/apache/maven/embedder/cache/CacheCleanerAspect.aj
index b86f81e487..516230f00b 100644
--- a/maven-embedder/src/main/aspect/org/apache/maven/embedder/cache/CacheCleanerAspect.aj
+++ b/maven-embedder/src/main/aspect/org/apache/maven/embedder/cache/CacheCleanerAspect.aj
@@ -1,39 +1,11 @@
package org.apache.maven.embedder.cache;
-import org.apache.maven.project.MavenProjectBuilder;
-import org.apache.maven.project.DefaultMavenProjectBuilder;
-import org.apache.maven.project.build.model.DefaultModelLineageBuilder;
-import org.apache.maven.project.build.model.ModelLineageBuilder;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.embedder.MavenEmbedder;
-import org.apache.maven.embedder.MavenEmbedderException;
-import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
public privileged aspect CacheCleanerAspect
{
- private ModelLineageBuilder MavenEmbedder.modelLineageBuilder;
-
- private pointcut embedderStarted( MavenEmbedder embedder ):
- execution( * MavenEmbedder.start( .. ) )
- && this( embedder );
-
- void around( MavenEmbedder embedder )
- throws MavenEmbedderException:
- embedderStarted( embedder )
- {
- proceed( embedder );
-
- try
- {
- embedder.modelLineageBuilder = (ModelLineageBuilder) embedder.container.lookup( ModelLineageBuilder.ROLE );
- }
- catch ( ComponentLookupException e )
- {
- throw new MavenEmbedderException( "Cannot lookup required component.", e );
- }
- }
-
private pointcut requestAsLastParam( MavenExecutionRequest request, MavenEmbedder embedder ):
execution( * MavenEmbedder.*( .., MavenExecutionRequest ) )
&& args( .., request )
@@ -56,20 +28,9 @@ public privileged aspect CacheCleanerAspect
private void cleanup( MavenExecutionRequest request, MavenEmbedder embedder )
{
+ // TODO: Add this to the eventing-control mechanism that the workspace uses now,
+ // once we can accommodate context in the event method calls.
request.clearAccumulatedBuildState();
-
- MavenProjectBuilder projectBuilder = embedder.mavenProjectBuilder;
- ModelLineageBuilder lineageBuilder = embedder.modelLineageBuilder;
-
- if ( projectBuilder instanceof DefaultMavenProjectBuilder )
- {
- ((DefaultMavenProjectBuilder) projectBuilder).clearProjectCache();
- }
-
- if ( lineageBuilder instanceof DefaultModelLineageBuilder )
- {
- ((DefaultModelLineageBuilder) lineageBuilder).clearModelAndFileCache();
- }
}
}
diff --git a/maven-embedder/src/main/aspect/org/apache/maven/embedder/event/EmbedderEventDispatcherAspect.aj b/maven-embedder/src/main/aspect/org/apache/maven/embedder/event/EmbedderEventDispatcherAspect.aj
new file mode 100644
index 0000000000..16fc9db852
--- /dev/null
+++ b/maven-embedder/src/main/aspect/org/apache/maven/embedder/event/EmbedderEventDispatcherAspect.aj
@@ -0,0 +1,61 @@
+package org.apache.maven.embedder.event;
+
+import org.apache.maven.monitor.event.MavenEvents;
+import org.apache.maven.embedder.MavenEmbedder;
+import org.apache.maven.execution.MavenExecutionRequest;
+
+public privileged aspect EmbedderEventDispatcherAspect
+{
+
+ after( MavenEmbedder embedder ): execution( * MavenEmbedder.start( .. ) ) && this( embedder )
+ {
+ if ( embedder.dispatcher != null )
+ {
+ embedder.dispatcher.dispatchStart( MavenEvents.EMBEDDER_LIFECYCLE, "" );
+ }
+ }
+
+ before( MavenEmbedder embedder ): execution( * MavenEmbedder.stop( .. ) ) && this( embedder )
+ {
+ if ( embedder.dispatcher != null )
+ {
+ embedder.dispatcher.dispatchEnd( MavenEvents.EMBEDDER_LIFECYCLE, "" );
+ }
+ }
+
+ private pointcut eventedMethods( MavenEmbedder embedder ):
+ (
+ execution( * MavenEmbedder.*( .., MavenExecutionRequest ) )
+ || execution( * MavenEmbedder.*( MavenExecutionRequest ) )
+ || execution( * MavenEmbedder.*( MavenExecutionRequest, .. ) )
+ || execution( * MavenEmbedder.resolve( .. ) )
+ || execution( * MavenEmbedder.readProject( .. ) )
+ || execution( * MavenEmbedder.verifyPlugin( .. ) )
+ )
+ && this( embedder );
+
+ before( MavenEmbedder embedder ):
+ eventedMethods( embedder )
+ && !cflowbelow( eventedMethods( MavenEmbedder ) )
+ {
+ if ( embedder.dispatcher != null )
+ {
+ String target = thisJoinPointStaticPart.getSignature().getName();
+
+ embedder.dispatcher.dispatchStart( MavenEvents.EMBEDDER_METHOD, target );
+ }
+ }
+
+ after( MavenEmbedder embedder ):
+ eventedMethods( embedder )
+ && !cflowbelow( eventedMethods( MavenEmbedder ) )
+ {
+ if ( embedder.dispatcher != null )
+ {
+ String target = thisJoinPointStaticPart.getSignature().getName();
+
+ embedder.dispatcher.dispatchEnd( MavenEvents.EMBEDDER_METHOD, target );
+ }
+ }
+
+}
diff --git a/maven-embedder/src/main/java/org/apache/maven/embedder/Configuration.java b/maven-embedder/src/main/java/org/apache/maven/embedder/Configuration.java
index 92dafa58ad..ae5d8e976e 100644
--- a/maven-embedder/src/main/java/org/apache/maven/embedder/Configuration.java
+++ b/maven-embedder/src/main/java/org/apache/maven/embedder/Configuration.java
@@ -19,6 +19,8 @@ package org.apache.maven.embedder;
*/
import org.apache.maven.errors.CoreErrorReporter;
+import org.apache.maven.monitor.event.EventMonitor;
+import org.apache.maven.monitor.event.MavenWorkspaceMonitor;
import org.apache.maven.realm.MavenRealmManager;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.classworlds.ClassWorld;
@@ -141,4 +143,17 @@ public interface Configuration
CoreErrorReporter getErrorReporter();
+ // ----------------------------------------------------------------------------
+ // Event Monitors
+ // ----------------------------------------------------------------------------
+
+ Configuration addEventMonitor( EventMonitor eventMonitor );
+
+ Configuration setEventMonitors( List eventMonitors );
+
+ List getEventMonitors();
+
+ Configuration setWorkspaceMonitor( MavenWorkspaceMonitor workspaceMonitor );
+
+ MavenWorkspaceMonitor getWorkspaceMonitor();
}
diff --git a/maven-embedder/src/main/java/org/apache/maven/embedder/DefaultConfiguration.java b/maven-embedder/src/main/java/org/apache/maven/embedder/DefaultConfiguration.java
index 6d5250ce9f..2ecc3156e3 100644
--- a/maven-embedder/src/main/java/org/apache/maven/embedder/DefaultConfiguration.java
+++ b/maven-embedder/src/main/java/org/apache/maven/embedder/DefaultConfiguration.java
@@ -19,6 +19,8 @@ package org.apache.maven.embedder;
*/
import org.apache.maven.errors.CoreErrorReporter;
+import org.apache.maven.monitor.event.EventMonitor;
+import org.apache.maven.monitor.event.MavenWorkspaceMonitor;
import org.apache.maven.realm.MavenRealmManager;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.classworlds.ClassWorld;
@@ -49,7 +51,7 @@ public class DefaultConfiguration
private Properties systemProperties;
- /** List<URL>. */
+ /** List<URL>. */
private List extensions = new ArrayList();
private MavenEmbedderLogger logger;
@@ -64,6 +66,11 @@ public class DefaultConfiguration
private CoreErrorReporter errorReporter;
+ /** List<EventMonitor>. */
+ private List eventMonitors;
+
+ private MavenWorkspaceMonitor workspaceMonitor;
+
/** Creates a new instance of DefaultConfiguration */
public DefaultConfiguration()
{
@@ -246,4 +253,38 @@ public class DefaultConfiguration
this.errorReporter = errorReporter;
return this;
}
+
+ public Configuration addEventMonitor( EventMonitor eventMonitor )
+ {
+ if ( eventMonitors == null )
+ {
+ eventMonitors = new ArrayList();
+ }
+
+ eventMonitors.add( eventMonitor );
+
+ return this;
+ }
+
+ public List getEventMonitors()
+ {
+ return eventMonitors;
+ }
+
+ public Configuration setEventMonitors( List eventMonitors )
+ {
+ this.eventMonitors = eventMonitors;
+ return this;
+ }
+
+ public MavenWorkspaceMonitor getWorkspaceMonitor()
+ {
+ return workspaceMonitor;
+ }
+
+ public Configuration setWorkspaceMonitor( MavenWorkspaceMonitor workspaceMonitor )
+ {
+ this.workspaceMonitor = workspaceMonitor;
+ return this;
+ }
}
diff --git a/maven-embedder/src/main/java/org/apache/maven/embedder/MavenEmbedder.java b/maven-embedder/src/main/java/org/apache/maven/embedder/MavenEmbedder.java
index 8ca2629d0d..61da51695f 100644
--- a/maven-embedder/src/main/java/org/apache/maven/embedder/MavenEmbedder.java
+++ b/maven-embedder/src/main/java/org/apache/maven/embedder/MavenEmbedder.java
@@ -74,6 +74,7 @@ import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer;
import org.apache.maven.settings.validation.DefaultSettingsValidator;
import org.apache.maven.settings.validation.SettingsValidationResult;
import org.apache.maven.settings.validation.SettingsValidator;
+import org.apache.maven.workspace.MavenWorkspaceStore;
import org.codehaus.plexus.ContainerConfiguration;
import org.codehaus.plexus.DefaultContainerConfiguration;
import org.codehaus.plexus.DefaultPlexusContainer;
@@ -164,6 +165,9 @@ public class MavenEmbedder
private BuildPlanner buildPlanner;
+ // TODO: Remove this once we have better control over cache-cleaning.
+ private MavenWorkspaceStore workspaceStore;
+
// ----------------------------------------------------------------------
// Configuration
// ----------------------------------------------------------------------
@@ -197,6 +201,11 @@ public class MavenEmbedder
return request;
}
+ protected MavenWorkspaceStore getWorkspaceStore()
+ {
+ return workspaceStore;
+ }
+
// ----------------------------------------------------------------------
// Accessors
// ----------------------------------------------------------------------
@@ -596,6 +605,8 @@ public class MavenEmbedder
private MavenExecutionRequest request;
+ private EventDispatcher dispatcher;
+
private void start( Configuration configuration )
throws MavenEmbedderException
{
@@ -690,6 +701,8 @@ public class MavenEmbedder
buildPlanner = (BuildPlanner) container.lookup( BuildPlanner.class );
+ workspaceStore = (MavenWorkspaceStore) container.lookup( MavenWorkspaceStore.class );
+
artifactHandlerManager = (ArtifactHandlerManager) container.lookup( ArtifactHandlerManager.ROLE );
// This is temporary as we can probably cache a single request and use it for default values and
@@ -697,6 +710,8 @@ public class MavenEmbedder
request = new DefaultMavenExecutionRequest();
populator.populateDefaults( request, configuration );
+
+ dispatcher = new DefaultEventDispatcher( request.getEventMonitors() );
}
catch ( ComponentLookupException e )
{
diff --git a/maven-embedder/src/main/java/org/apache/maven/embedder/execution/DefaultMavenExecutionRequestPopulator.java b/maven-embedder/src/main/java/org/apache/maven/embedder/execution/DefaultMavenExecutionRequestPopulator.java
index 80fc6a7321..6f98f842a5 100644
--- a/maven-embedder/src/main/java/org/apache/maven/embedder/execution/DefaultMavenExecutionRequestPopulator.java
+++ b/maven-embedder/src/main/java/org/apache/maven/embedder/execution/DefaultMavenExecutionRequestPopulator.java
@@ -33,6 +33,9 @@ import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.model.Profile;
import org.apache.maven.model.Repository;
import org.apache.maven.monitor.event.DefaultEventMonitor;
+import org.apache.maven.monitor.event.EventMonitor;
+import org.apache.maven.monitor.event.MavenWorkspaceMonitor;
+import org.apache.maven.monitor.event.PerCallWorkspaceMonitor;
import org.apache.maven.plugin.Mojo;
import org.apache.maven.profiles.DefaultProfileManager;
import org.apache.maven.profiles.ProfileManager;
@@ -47,6 +50,7 @@ import org.apache.maven.settings.Settings;
import org.apache.maven.settings.SettingsConfigurationException;
import org.apache.maven.settings.SettingsUtils;
import org.apache.maven.wagon.repository.RepositoryPermissions;
+import org.apache.maven.workspace.MavenWorkspaceStore;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
@@ -92,12 +96,18 @@ public class DefaultMavenExecutionRequestPopulator
private WagonManager wagonManager;
+ private MavenWorkspaceStore workspaceManager;
+
private MavenSettingsBuilder settingsBuilder;
public MavenExecutionRequest populateDefaults( MavenExecutionRequest request,
Configuration configuration )
throws MavenEmbedderException
{
+ eventMonitors( request, configuration );
+
+ workspaceMonitor( request, configuration );
+
reporter( request, configuration );
executionProperties( request, configuration );
@@ -128,6 +138,59 @@ public class DefaultMavenExecutionRequestPopulator
return request;
}
+ private void workspaceMonitor( MavenExecutionRequest request,
+ Configuration configuration )
+ {
+ MavenWorkspaceMonitor workspaceMonitor = request.getWorkspaceMonitor();
+
+ if ( workspaceMonitor == null )
+ {
+ workspaceMonitor = configuration.getWorkspaceMonitor();
+ }
+
+ List requestEventMonitors = request.getEventMonitors();
+ if ( ( requestEventMonitors != null ) && !requestEventMonitors.isEmpty() )
+ {
+ for ( Iterator it = requestEventMonitors.iterator(); it.hasNext(); )
+ {
+ Object monitor = it.next();
+ if ( monitor instanceof MavenWorkspaceMonitor )
+ {
+ if ( workspaceMonitor == null )
+ {
+ workspaceMonitor = (MavenWorkspaceMonitor) monitor;
+ }
+ it.remove();
+ break;
+ }
+ }
+ }
+
+ if ( workspaceMonitor == null )
+ {
+ workspaceMonitor = new PerCallWorkspaceMonitor();
+ }
+
+ workspaceMonitor.setWorkspaceStore( workspaceManager );
+
+ request.addEventMonitor( workspaceMonitor );
+ }
+
+ private void eventMonitors( MavenExecutionRequest request,
+ Configuration configuration )
+ {
+ List configEventMonitors = configuration.getEventMonitors();
+
+ if ( ( configEventMonitors != null ) && !configEventMonitors.isEmpty() )
+ {
+ for ( Iterator it = configEventMonitors.iterator(); it.hasNext(); )
+ {
+ EventMonitor monitor = (EventMonitor) it.next();
+ request.addEventMonitor( monitor );
+ }
+ }
+ }
+
private void reporter( MavenExecutionRequest request,
Configuration configuration )
{
diff --git a/maven-embedder/src/main/resources/META-INF/plexus/components.xml b/maven-embedder/src/main/resources/META-INF/plexus/components.xml
index bc361da78a..ad55db36ed 100644
--- a/maven-embedder/src/main/resources/META-INF/plexus/components.xml
+++ b/maven-embedder/src/main/resources/META-INF/plexus/components.xml
@@ -23,6 +23,9 @@ under the License.
org.apache.maven.embedder.execution.MavenExecutionRequestPopulator
org.apache.maven.embedder.execution.DefaultMavenExecutionRequestPopulator
+
+ org.apache.maven.workspace.MavenWorkspaceStore
+
org.apache.maven.artifact.manager.WagonManager
default
diff --git a/maven-embedder/src/test/eventing-projects/read-with-deps/pom.xml b/maven-embedder/src/test/eventing-projects/read-with-deps/pom.xml
new file mode 100644
index 0000000000..4bbef519be
--- /dev/null
+++ b/maven-embedder/src/test/eventing-projects/read-with-deps/pom.xml
@@ -0,0 +1,15 @@
+
+ 4.0.0
+ testing
+ read-with-deps
+ 1
+
+
+
+ tests
+ dep
+ 1
+ pom
+
+
+
\ No newline at end of file
diff --git a/maven-embedder/src/test/eventing-projects/read-with-deps/repo/tests/dep/1/dep-1.pom b/maven-embedder/src/test/eventing-projects/read-with-deps/repo/tests/dep/1/dep-1.pom
new file mode 100644
index 0000000000..175bf21087
--- /dev/null
+++ b/maven-embedder/src/test/eventing-projects/read-with-deps/repo/tests/dep/1/dep-1.pom
@@ -0,0 +1,6 @@
+
+ 4.0.0
+ testing
+ dep
+ 1
+
\ No newline at end of file
diff --git a/maven-embedder/src/test/eventing-projects/simple-read-project/pom.xml b/maven-embedder/src/test/eventing-projects/simple-read-project/pom.xml
new file mode 100644
index 0000000000..9a3f6be472
--- /dev/null
+++ b/maven-embedder/src/test/eventing-projects/simple-read-project/pom.xml
@@ -0,0 +1,6 @@
+
+ 4.0.0
+ testing
+ simple-read-project
+ 1
+
\ No newline at end of file
diff --git a/maven-embedder/src/test/java/org/apache/maven/embedder/MavenEmbedderEventingTest.java b/maven-embedder/src/test/java/org/apache/maven/embedder/MavenEmbedderEventingTest.java
new file mode 100644
index 0000000000..af01b46b0c
--- /dev/null
+++ b/maven-embedder/src/test/java/org/apache/maven/embedder/MavenEmbedderEventingTest.java
@@ -0,0 +1,261 @@
+package org.apache.maven.embedder;
+
+import org.apache.maven.execution.DefaultMavenExecutionRequest;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.extension.ExtensionScanningException;
+import org.apache.maven.monitor.event.AbstractWorkspaceMonitor;
+import org.apache.maven.project.ProjectBuildingException;
+import org.apache.maven.reactor.MavenExecutionException;
+import org.apache.maven.workspace.MavenWorkspaceStore;
+import org.codehaus.plexus.util.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+
+import junit.framework.TestCase;
+
+public class MavenEmbedderEventingTest
+ extends TestCase
+{
+
+ protected String basedir;
+
+ protected void setUp()
+ throws Exception
+ {
+ super.setUp();
+
+ basedir = System.getProperty( "basedir" );
+
+ if ( basedir == null )
+ {
+ basedir = new File( "." ).getCanonicalPath();
+ }
+ }
+
+ public void testEmbedderInitializeAndStopEventsFired()
+ throws MavenEmbedderException
+ {
+ TestWorkspaceMonitor testWSMonitor = new TestWorkspaceMonitor();
+
+ Configuration config = new DefaultConfiguration();
+ config.setWorkspaceMonitor( testWSMonitor );
+
+ assertEquals( 0, testWSMonitor.initializeCaught );
+ assertEquals( 0, testWSMonitor.setManagerCaught );
+
+ MavenEmbedder embedder = new MavenEmbedder( config );
+
+ assertEquals( 1, testWSMonitor.initializeCaught );
+ assertEquals( 1, testWSMonitor.setManagerCaught );
+
+ assertEquals( 0, testWSMonitor.stopCaught );
+ assertEquals( 0, testWSMonitor.clearCaught );
+
+ assertSame( embedder.getWorkspaceStore(), testWSMonitor.workspaceManager );
+
+ embedder.stop();
+
+ assertEquals( 1, testWSMonitor.stopCaught );
+ assertEquals( 1, testWSMonitor.clearCaught );
+
+ assertEquals( 0, testWSMonitor.startMethodCaught );
+ assertEquals( 0, testWSMonitor.endMethodCaught );
+ }
+
+ public void testStartAndEndMethodEventsFiredOnSimpleReadProject()
+ throws IOException, MavenEmbedderException, ProjectBuildingException,
+ ExtensionScanningException, MavenExecutionException
+ {
+ EmbedderAndMonitor em = newEmbedder();
+
+ assertEquals( 0, em.monitor.startMethodCaught );
+ assertEquals( 0, em.monitor.endMethodCaught );
+
+ File dir = getFile( "simple-read-project" );
+ File pomFile = new File( dir, "pom.xml" );
+
+ em.embedder.readProject( pomFile );
+
+ assertEquals( 1, em.monitor.startMethodCaught );
+ assertEquals( 1, em.monitor.endMethodCaught );
+ assertEquals( 1, em.monitor.clearCaught );
+
+ assertSame( em.embedder.getWorkspaceStore(), em.monitor.workspaceManager );
+
+ em.embedder.stop();
+ }
+
+ public void testStartAndEndMethodEventsFiredOnReadWithDeps()
+ throws IOException, MavenEmbedderException, ProjectBuildingException,
+ ExtensionScanningException, MavenExecutionException
+ {
+ File dir = getFile( "read-with-deps" );
+ File pomFile = new File( dir, "pom.xml" );
+ File localRepoDir = new File( dir, "repo" );
+
+ EmbedderAndMonitor em = newEmbedder( localRepoDir );
+
+ assertEquals( 0, em.monitor.startMethodCaught );
+ assertEquals( 0, em.monitor.endMethodCaught );
+
+ em.embedder.readProject( pomFile );
+
+ assertEquals( 1, em.monitor.startMethodCaught );
+ assertEquals( 1, em.monitor.endMethodCaught );
+ assertEquals( 1, em.monitor.clearCaught );
+
+ assertSame( em.embedder.getWorkspaceStore(), em.monitor.workspaceManager );
+
+ em.embedder.stop();
+ }
+
+ public void testStartAndEndMethodEventsFiredOnExecute()
+ throws IOException, MavenEmbedderException, ProjectBuildingException,
+ ExtensionScanningException, MavenExecutionException
+ {
+ EmbedderAndMonitor em = newEmbedder();
+
+ assertEquals( 0, em.monitor.startMethodCaught );
+ assertEquals( 0, em.monitor.endMethodCaught );
+
+ File dir = getFile( "simple-read-project" );
+
+ MavenExecutionRequest request = new DefaultMavenExecutionRequest();
+ request.setGoals( Collections.singletonList( "clean" ) );
+ request.setBaseDirectory( dir );
+
+ em.embedder.execute( request );
+
+ assertEquals( 1, em.monitor.startMethodCaught );
+ assertEquals( 1, em.monitor.endMethodCaught );
+ assertEquals( 1, em.monitor.clearCaught );
+
+ assertSame( em.embedder.getWorkspaceStore(), em.monitor.workspaceManager );
+
+ em.embedder.stop();
+ }
+
+ private EmbedderAndMonitor newEmbedder()
+ throws MavenEmbedderException
+ {
+ return newEmbedder( null );
+ }
+
+ private EmbedderAndMonitor newEmbedder( File localRepoDir )
+ throws MavenEmbedderException
+ {
+ TestWorkspaceMonitor testWSMonitor = new TestWorkspaceMonitor();
+
+ Configuration config = new DefaultConfiguration();
+ config.setWorkspaceMonitor( testWSMonitor );
+ config.setMavenEmbedderLogger( new MavenEmbedderConsoleLogger() );
+
+ if ( localRepoDir != null )
+ {
+ config.setLocalRepository( localRepoDir );
+ }
+
+ return new EmbedderAndMonitor( new MavenEmbedder( config ), testWSMonitor );
+ }
+
+ private static final class EmbedderAndMonitor
+ {
+ private MavenEmbedder embedder;
+
+ private TestWorkspaceMonitor monitor;
+
+ private EmbedderAndMonitor( MavenEmbedder embedder,
+ TestWorkspaceMonitor monitor )
+ {
+ this.embedder = embedder;
+ this.monitor = monitor;
+ }
+ }
+
+ private File getFile( String path )
+ throws IOException
+ {
+ File testDirectory = new File( basedir, "src/test/eventing-projects/" + path );
+
+ System.out.println( "Test source dir: " + testDirectory );
+
+ File targetDirectory = new File( basedir, "target/eventing-projects/" + path );
+
+ System.out.println( "Test temp dir: " + targetDirectory );
+
+ targetDirectory.getParentFile().mkdirs();
+
+ FileUtils.copyDirectoryStructure( testDirectory, targetDirectory );
+
+ return targetDirectory;
+ }
+
+ private static final class TestWorkspaceMonitor
+ extends AbstractWorkspaceMonitor
+ {
+
+ private int initializeCaught = 0;
+
+ private int startMethodCaught = 0;
+
+ private int endMethodCaught = 0;
+
+ private int stopCaught = 0;
+
+ private int setManagerCaught = 0;
+
+ private int clearCaught = 0;
+
+ private MavenWorkspaceStore workspaceManager;
+
+ private boolean clearOnEndMethod = true;
+
+ private boolean clearOnStop = true;
+
+ public void embedderInitialized( long timestamp )
+ {
+ initializeCaught++;
+ }
+
+ public void embedderMethodEnded( String method,
+ long timestamp )
+ {
+ endMethodCaught++;
+ if ( clearOnEndMethod )
+ {
+ clearCache();
+ }
+ }
+
+ public void embedderMethodStarted( String method,
+ long timestamp )
+ {
+ startMethodCaught++;
+ }
+
+ public void embedderStopped( long timestamp )
+ {
+ stopCaught++;
+ if ( clearOnStop )
+ {
+ clearCache();
+ }
+ }
+
+ public void setWorkspaceStore( MavenWorkspaceStore workspaceManager )
+ {
+ setManagerCaught++;
+ this.workspaceManager = workspaceManager;
+ super.setWorkspaceStore( workspaceManager );
+ }
+
+ public void clearCache()
+ {
+ clearCaught++;
+ super.clearCache();
+ }
+
+ }
+}
diff --git a/maven-project/pom.xml b/maven-project/pom.xml
index a214ac8d17..5fc4db1896 100644
--- a/maven-project/pom.xml
+++ b/maven-project/pom.xml
@@ -32,6 +32,11 @@ under the License.
This library is used to not only read Maven project object model files, but to assemble inheritence
and to retrieve remote models as required.
+
+ org.apache.maven
+ maven-workspace
+ 2.1-SNAPSHOT
+
org.apache.maven
maven-profile
diff --git a/maven-project/src/main/aspect/org/apache/maven/project/aspect/ProjectCacheAspect.aj b/maven-project/src/main/aspect/org/apache/maven/project/aspect/ProjectCacheAspect.aj
index 6ef265c8a1..c46c4b72b2 100644
--- a/maven-project/src/main/aspect/org/apache/maven/project/aspect/ProjectCacheAspect.aj
+++ b/maven-project/src/main/aspect/org/apache/maven/project/aspect/ProjectCacheAspect.aj
@@ -13,21 +13,10 @@ import org.apache.maven.project.build.model.ModelAndFile;
import org.codehaus.plexus.util.StringUtils;
import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
public privileged aspect ProjectCacheAspect
{
- private Map DefaultMavenProjectBuilder.projectCache = new HashMap();
-
- public void DefaultMavenProjectBuilder.clearProjectCache()
- {
- logger.debug( "Clearing project cache." );
- projectCache.clear();
- logger.debug( "After clearing, " + projectCache.size() + " items remain." );
- }
-
private pointcut mavenProjectBuilder( DefaultMavenProjectBuilder builder ):
execution( * DefaultMavenProjectBuilder+.*( .. ) )
&& this( builder );
@@ -63,19 +52,6 @@ public privileged aspect ProjectCacheAspect
// proceed( child, parent, builder );
// }
- private pointcut setMavenProjectFile( File pomFile, MavenProject project, DefaultMavenProjectBuilder builder ):
- execution( void MavenProject.setFile( File ) )
- && cflow( mavenProjectBuilder( builder ) )
- && args( pomFile )
- && target( project );
-
- after( File pomFile, MavenProject project, DefaultMavenProjectBuilder builder ):
- setMavenProjectFile( pomFile, project, builder )
- {
- builder.logger.debug( "Caching project: " + project.getId() + " by its file: " + pomFile );
- builder.projectCache.put( pomFile, project );
- }
-
private pointcut pbBuildFromRepository( Artifact artifact, DefaultMavenProjectBuilder builder ):
execution( MavenProject DefaultMavenProjectBuilder+.buildFromRepository( Artifact, .. ) )
&& args( artifact, .. )
@@ -89,15 +65,10 @@ public privileged aspect ProjectCacheAspect
MavenProject project = null;
boolean skipCache = false;
- if ( Artifact.LATEST_VERSION.equals( artifact.getVersion() ) || Artifact.RELEASE_VERSION.equals( artifact.getVersion() ) )
- {
- builder.logger.debug( "Skipping cache for meta-version: " + artifact.getVersion() );
- skipCache = true;
- }
- else
+ if ( !Artifact.LATEST_VERSION.equals( artifact.getVersion() ) && !Artifact.RELEASE_VERSION.equals( artifact.getVersion() ) )
{
builder.logger.debug( "Checking cache for project (in buildFromRepository): " + key );
- project = (MavenProject) builder.projectCache.get( key );
+ project = (MavenProject) builder.projectWorkspace.getProject( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion() );
}
if ( project == null )
@@ -108,8 +79,8 @@ public privileged aspect ProjectCacheAspect
if ( !skipCache )
{
builder.logger.debug( "Caching result for: " + key + " (also keyed by file: " + project.getFile() + ")" );
- builder.projectCache.put( key, project );
- builder.projectCache.put( project.getFile(), project );
+ builder.projectWorkspace.storeProjectByCoordinate( project );
+ builder.projectWorkspace.storeProjectByFile( project );
}
}
else
@@ -131,7 +102,7 @@ public privileged aspect ProjectCacheAspect
{
builder.logger.debug( "Checking cache-hit on project (in build*): " + pomFile );
- MavenProject project = (MavenProject) builder.projectCache.get( pomFile );
+ MavenProject project = (MavenProject) builder.projectWorkspace.getProject( pomFile );
if ( project == null )
{
@@ -141,8 +112,8 @@ public privileged aspect ProjectCacheAspect
String key = createCacheKey( project.getGroupId(), project.getArtifactId(), project.getVersion() );
builder.logger.debug( "Caching result for: " + key + " (also keyed by file: " + pomFile + ")" );
- builder.projectCache.put( key, project );
- builder.projectCache.put( pomFile, project );
+ builder.projectWorkspace.storeProjectByFile( project );
+ builder.projectWorkspace.storeProjectByCoordinate( project );
}
else
{
@@ -159,17 +130,6 @@ public privileged aspect ProjectCacheAspect
return groupId + ":" + artifactId + ":" + version;
}
- private Map DefaultModelLineageBuilder.modelAndFileCache = new HashMap();
-
- public void DefaultModelLineageBuilder.clearModelAndFileCache()
- {
- logger.debug( "Clearing model-and-file cache." );
-
- modelAndFileCache.clear();
-
- logger.debug( "After clearing, model-and-file cache has " + modelAndFileCache.size() + " entries." );
- }
-
private pointcut mlbResolveParentPom( ModelAndFile child, DefaultModelLineageBuilder builder ):
execution( private ModelAndFile DefaultModelLineageBuilder.resolveParentPom( ModelAndFile, .. ) )
&& args( child, .. )
@@ -192,7 +152,7 @@ public privileged aspect ProjectCacheAspect
String key = createCacheKey( parentRef.getGroupId(), parentRef.getArtifactId(), parentRef.getVersion() );
builder.logger.debug( "Checking cache for parent model-and-file instance: " + key );
- parent = (ModelAndFile) builder.modelAndFileCache.get( key );
+ parent = (ModelAndFile) builder.projectWorkspace.getModelAndFile( parentRef.getGroupId(), parentRef.getArtifactId(), parentRef.getVersion() );
if ( parent == null )
{
@@ -202,8 +162,7 @@ public privileged aspect ProjectCacheAspect
if ( parent != null )
{
builder.logger.debug( "Caching parent model-and-file under: " + key + " and file: " + parent.getFile() + " (child is: " + childModel.getId() + ")" );
- builder.modelAndFileCache.put( key, parent );
- builder.modelAndFileCache.put( parent.getFile(), parent );
+ builder.projectWorkspace.storeModelAndFile( parent );
}
}
else
@@ -215,11 +174,9 @@ public privileged aspect ProjectCacheAspect
return parent;
}
- private pointcut buildModelLineageExec(): execution( ModelLineage DefaultModelLineageBuilder.buildModelLineage( .. ) );
-
private pointcut mlbReadModelCacheHit( File pomFile, DefaultModelLineageBuilder builder ):
- execution( Model DefaultModelLineageBuilder.readModel( File ) )
- && cflowbelow( buildModelLineageExec() )
+ call( Model DefaultModelLineageBuilder.readModel( File ) )
+ && withincode( ModelLineage DefaultModelLineageBuilder.buildModelLineage( .. ) )
&& args( pomFile )
&& this( builder );
@@ -227,22 +184,21 @@ public privileged aspect ProjectCacheAspect
throws ProjectBuildingException:
mlbReadModelCacheHit( pomFile, builder )
{
- builder.logger.debug( "Checking cache for model-and-file instance for parent-pom in file: " + pomFile );
- ModelAndFile cached = (ModelAndFile) builder.modelAndFileCache.get( pomFile );
+ builder.logger.debug( "Checking cache for model-and-file instance for pom in file: " + pomFile );
+ ModelAndFile cached = (ModelAndFile) builder.projectWorkspace.getModelAndFile( pomFile );
if ( cached != null )
{
- builder.logger.debug( "Returning cached parent-pom instance." );
+ builder.logger.debug( "Returning cached pom instance." );
return cached.getModel();
}
- builder.logger.debug( "Allowing readModel(..) to proceed for parent-pom in file: " + pomFile );
+ builder.logger.debug( "Allowing readModel(..) to proceed for pom in file: " + pomFile );
return proceed( pomFile, builder );
}
private pointcut mlbCacheableModelAndFileConstruction( Model model, File pomFile, DefaultModelLineageBuilder builder ):
call( ModelAndFile.new( Model, File, .. ) )
- && cflow( buildModelLineageExec() )
- && !cflowbelow( buildModelLineageExec() )
+ && withincode( ModelLineage DefaultModelLineageBuilder.buildModelLineage( .. ) )
&& args( model, pomFile, .. )
&& this( builder );
@@ -250,16 +206,14 @@ public privileged aspect ProjectCacheAspect
mlbCacheableModelAndFileConstruction( model, pomFile, builder )
{
builder.logger.debug( "Checking cache for model-and-file instance for file: " + pomFile );
- ModelAndFile cached = (ModelAndFile) builder.modelAndFileCache.get( pomFile );
+ ModelAndFile cached = (ModelAndFile) builder.projectWorkspace.getModelAndFile( pomFile );
if ( cached == null )
{
builder.logger.debug( "Allowing construction to proceed for model-and-file with model: " + model.getId() + " and file: " + pomFile );
cached = proceed( model, pomFile, builder );
- String key = createCacheKey( model.getGroupId(), model.getArtifactId(), model.getVersion() );
-
- builder.modelAndFileCache.put( key, cached );
- builder.modelAndFileCache.put( pomFile, cached );
+ builder.logger.debug( "Storing: " + cached );
+ builder.projectWorkspace.storeModelAndFile( cached );
}
else
{
diff --git a/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java b/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java
index 640a5799b9..dcf42c83e1 100644
--- a/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java
+++ b/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java
@@ -67,6 +67,7 @@ import org.apache.maven.project.interpolation.ModelInterpolator;
import org.apache.maven.project.path.PathTranslator;
import org.apache.maven.project.validation.ModelValidationResult;
import org.apache.maven.project.validation.ModelValidator;
+import org.apache.maven.project.workspace.ProjectWorkspace;
import org.codehaus.plexus.logging.LogEnabled;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
@@ -162,6 +163,8 @@ public class DefaultMavenProjectBuilder
private MavenTools mavenTools;
+ private ProjectWorkspace projectWorkspace;
+
//DO NOT USE, it is here only for backward compatibility reasons. The existing
// maven-assembly-plugin (2.2-beta-1) is accessing it via reflection.
@@ -1047,6 +1050,7 @@ public class DefaultMavenProjectBuilder
if ( lastProject != null )
{
+ // TODO: Use cached parent project here, and stop looping, if possible...
lastProject.setParent( project );
project = lastProject.getParent();
diff --git a/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java b/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java
index 4148286eb5..7b82403a53 100644
--- a/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java
+++ b/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java
@@ -95,6 +95,11 @@ public class MavenMetadataSource
public ResolutionGroup retrieve( Artifact artifact, ArtifactRepository localRepository, List remoteRepositories )
throws ArtifactMetadataRetrievalException
{
+ if ( remoteRepositories == null )
+ {
+ remoteRepositories = Collections.EMPTY_LIST;
+ }
+
try
{
loadProjectBuilder();
@@ -326,14 +331,17 @@ public class MavenMetadataSource
}
}
- // this list should contain the super-POM repositories, so we don't have to explicitly add them back.
- for ( Iterator it = remoteArtifactRepositories.iterator(); it.hasNext(); )
+ if ( remoteArtifactRepositories != null )
{
- ArtifactRepository repository = (ArtifactRepository) it.next();
-
- if ( !repositories.contains( repository ) )
+ // this list should contain the super-POM repositories, so we don't have to explicitly add them back.
+ for ( Iterator it = remoteArtifactRepositories.iterator(); it.hasNext(); )
{
- repositories.add( repository );
+ ArtifactRepository repository = (ArtifactRepository) it.next();
+
+ if ( !repositories.contains( repository ) )
+ {
+ repositories.add( repository );
+ }
}
}
diff --git a/maven-project/src/main/java/org/apache/maven/project/build/model/DefaultModelLineageBuilder.java b/maven-project/src/main/java/org/apache/maven/project/build/model/DefaultModelLineageBuilder.java
index 26fdfe8b89..918556e824 100644
--- a/maven-project/src/main/java/org/apache/maven/project/build/model/DefaultModelLineageBuilder.java
+++ b/maven-project/src/main/java/org/apache/maven/project/build/model/DefaultModelLineageBuilder.java
@@ -35,6 +35,7 @@ import org.apache.maven.profiles.activation.DefaultProfileActivationContext;
import org.apache.maven.profiles.activation.ProfileActivationContext;
import org.apache.maven.profiles.build.ProfileAdvisor;
import org.apache.maven.project.ProjectBuildingException;
+import org.apache.maven.project.workspace.ProjectWorkspace;
import org.codehaus.plexus.logging.LogEnabled;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.console.ConsoleLogger;
@@ -68,6 +69,8 @@ public class DefaultModelLineageBuilder
private ProfileAdvisor profileAdvisor;
+ private ProjectWorkspace projectWorkspace;
+
private Logger logger;
public DefaultModelLineageBuilder()
@@ -97,7 +100,6 @@ public class DefaultModelLineageBuilder
List currentRemoteRepositories = remoteRepositories == null ? new ArrayList()
: new ArrayList( remoteRepositories );
- // TODO: Cache the result of this readModel(..) call.
ModelAndFile current = new ModelAndFile( readModel( pom ), pom, validProfilesXmlLocation );
do
diff --git a/maven-project/src/main/java/org/apache/maven/project/build/model/ModelAndFile.java b/maven-project/src/main/java/org/apache/maven/project/build/model/ModelAndFile.java
index a2b023942c..d09f50b8d5 100644
--- a/maven-project/src/main/java/org/apache/maven/project/build/model/ModelAndFile.java
+++ b/maven-project/src/main/java/org/apache/maven/project/build/model/ModelAndFile.java
@@ -13,7 +13,7 @@ public class ModelAndFile
private final boolean validProfilesXmlLocation;
- ModelAndFile( Model model,
+ public ModelAndFile( Model model,
File file,
boolean validProfilesXmlLocation )
{
diff --git a/maven-project/src/main/java/org/apache/maven/project/workspace/DefaultProjectWorkspace.java b/maven-project/src/main/java/org/apache/maven/project/workspace/DefaultProjectWorkspace.java
new file mode 100644
index 0000000000..dce392c995
--- /dev/null
+++ b/maven-project/src/main/java/org/apache/maven/project/workspace/DefaultProjectWorkspace.java
@@ -0,0 +1,148 @@
+package org.apache.maven.project.workspace;
+
+import org.apache.maven.model.Model;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.build.model.ModelAndFile;
+import org.apache.maven.workspace.MavenWorkspaceStore;
+import org.codehaus.plexus.logging.LogEnabled;
+import org.codehaus.plexus.logging.Logger;
+
+import java.io.File;
+import java.net.URI;
+import java.util.Map;
+
+public class DefaultProjectWorkspace
+ implements ProjectWorkspace, LogEnabled
+{
+
+ private MavenWorkspaceStore workspaceStore;
+// private Logger logger;
+
+ public DefaultProjectWorkspace()
+ {
+ }
+
+ protected DefaultProjectWorkspace( MavenWorkspaceStore workspaceStore )
+ {
+ this.workspaceStore = workspaceStore;
+ }
+
+ public ModelAndFile getModelAndFile( String groupId,
+ String artifactId,
+ String version )
+ {
+ Map cache = workspaceStore.getWorkspaceCache( ProjectWorkspace.MODEL_AND_FILE_BYGAV_KEY );
+
+ String key = createCacheKey( groupId, artifactId, version );
+
+// getLogger().debug( "Retrieving ModelAndFile instance for: " + key + " from workspace." );
+ return (ModelAndFile) cache.get( key );
+ }
+
+ public ModelAndFile getModelAndFile( File modelFile )
+ {
+ Map cache = workspaceStore.getWorkspaceCache( ProjectWorkspace.MODEL_AND_FILE_BYFILE_KEY );
+
+ Object pathKey = resolvePathKey( modelFile );
+
+// getLogger().debug( "Retrieving ModelAndFile instance for: " + pathKey + " from workspace." );
+ return (ModelAndFile) cache.get( pathKey );
+ }
+
+ private Object resolvePathKey( File file )
+ {
+ if ( file == null )
+ {
+ return null;
+ }
+
+ URI path = file.toURI().normalize();
+
+ return path;
+ }
+
+ public MavenProject getProject( File projectFile )
+ {
+ Map cache = workspaceStore.getWorkspaceCache( ProjectWorkspace.PROJECT_INSTANCE_BYFILE_KEY );
+
+ Object pathKey = resolvePathKey( projectFile );
+
+// getLogger().debug( "Retrieving MavenProject instance for: " + pathKey + " from workspace." );
+ return (MavenProject) cache.get( pathKey );
+ }
+
+ public MavenProject getProject( String groupId,
+ String artifactId,
+ String version )
+ {
+ Map cache = workspaceStore.getWorkspaceCache( ProjectWorkspace.PROJECT_INSTANCE_BYGAV_KEY );
+
+ String key = createCacheKey( groupId, artifactId, version );
+
+// getLogger().debug( "Retrieving MavenProject instance for: " + key + " from workspace." );
+ return (MavenProject) cache.get( key );
+ }
+
+ public void storeModelAndFile( ModelAndFile modelAndFile )
+ {
+ Map cache = workspaceStore.getWorkspaceCache( ProjectWorkspace.MODEL_AND_FILE_BYFILE_KEY );
+
+ Object pathKey = resolvePathKey( modelAndFile.getFile() );
+
+// getLogger().debug( "Storing ModelAndFile instance under: " + pathKey + " in workspace." );
+ cache.put( pathKey, modelAndFile );
+
+ cache = workspaceStore.getWorkspaceCache( ProjectWorkspace.MODEL_AND_FILE_BYGAV_KEY );
+
+ Model model = modelAndFile.getModel();
+ String key = createCacheKey( model.getGroupId(), model.getArtifactId(), model.getVersion() );
+
+// getLogger().debug( "Storing ModelAndFile instance under: " + key + " in workspace." );
+ cache.put( key, modelAndFile );
+ }
+
+ public void storeProjectByFile( MavenProject project )
+ {
+ if ( project.getFile() == null ){
+ return;
+ }
+
+ Map cache = workspaceStore.getWorkspaceCache( ProjectWorkspace.PROJECT_INSTANCE_BYFILE_KEY );
+
+ Object pathKey = resolvePathKey( project.getFile() );
+
+// getLogger().debug( "Storing MavenProject instance under: " + pathKey + " in workspace." );
+ cache.put( pathKey, project );
+ }
+
+ public void storeProjectByCoordinate( MavenProject project )
+ {
+ Map cache = workspaceStore.getWorkspaceCache( ProjectWorkspace.PROJECT_INSTANCE_BYGAV_KEY );
+
+ String key = createCacheKey( project.getGroupId(), project.getArtifactId(), project.getVersion() );
+
+// getLogger().debug( "Storing MavenProject instance under: " + key + " in workspace." );
+ cache.put( key, project );
+ }
+
+ private String createCacheKey( String groupId, String artifactId, String version )
+ {
+ return groupId + ":" + artifactId + ":" + version;
+ }
+
+// protected Logger getLogger()
+// {
+// if ( logger == null )
+// {
+// logger = new ConsoleLogger( Logger.LEVEL_INFO, "internal" );
+// }
+//
+// return logger;
+// }
+
+ public void enableLogging( Logger logger )
+ {
+// this.logger = logger;
+ }
+
+}
diff --git a/maven-project/src/main/java/org/apache/maven/project/workspace/ProjectWorkspace.java b/maven-project/src/main/java/org/apache/maven/project/workspace/ProjectWorkspace.java
new file mode 100644
index 0000000000..ddbc4fe1f0
--- /dev/null
+++ b/maven-project/src/main/java/org/apache/maven/project/workspace/ProjectWorkspace.java
@@ -0,0 +1,32 @@
+package org.apache.maven.project.workspace;
+
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.build.model.ModelAndFile;
+
+import java.io.File;
+
+public interface ProjectWorkspace
+{
+
+ String PROJECT_INSTANCE_BYFILE_KEY = "maven:project:project:file";
+
+ String MODEL_AND_FILE_BYFILE_KEY = "maven:project:modelAndFile:file";
+
+ String PROJECT_INSTANCE_BYGAV_KEY = "maven:project:project:GAV";
+
+ String MODEL_AND_FILE_BYGAV_KEY = "maven:project:modelAndFile:GAV";
+
+ MavenProject getProject( File projectFile );
+
+ MavenProject getProject( String groupId, String artifactId, String version );
+
+ void storeProjectByFile( MavenProject project );
+
+ void storeProjectByCoordinate( MavenProject project );
+
+ ModelAndFile getModelAndFile( String groupId, String artifactId, String version );
+
+ ModelAndFile getModelAndFile( File modelFile );
+
+ void storeModelAndFile( ModelAndFile modelAndFile );
+}
diff --git a/maven-project/src/main/resources/META-INF/plexus/components.xml b/maven-project/src/main/resources/META-INF/plexus/components.xml
index 51afcef40d..ab15e3d33f 100644
--- a/maven-project/src/main/resources/META-INF/plexus/components.xml
+++ b/maven-project/src/main/resources/META-INF/plexus/components.xml
@@ -41,6 +41,9 @@ under the License.
default
org.apache.maven.project.build.model.DefaultModelLineageBuilder
+
+ org.apache.maven.project.workspace.ProjectWorkspace
+
org.apache.maven.profiles.build.ProfileAdvisor
default
@@ -107,6 +110,9 @@ under the License.
default
org.apache.maven.project.DefaultMavenProjectBuilder
+
+ org.apache.maven.project.workspace.ProjectWorkspace
+
org.apache.maven.artifact.metadata.ArtifactMetadataSource
@@ -310,6 +316,17 @@ under the License.
+
+
+ org.apache.maven.project.workspace.ProjectWorkspace
+ default
+ org.apache.maven.project.workspace.DefaultProjectWorkspace
+
+
+ org.apache.maven.workspace.MavenWorkspaceStore
+
+
+
diff --git a/maven-project/src/test/java/org/apache/maven/project/workspace/DefaultProjectWorkspaceTest.java b/maven-project/src/test/java/org/apache/maven/project/workspace/DefaultProjectWorkspaceTest.java
new file mode 100644
index 0000000000..02e11b1623
--- /dev/null
+++ b/maven-project/src/test/java/org/apache/maven/project/workspace/DefaultProjectWorkspaceTest.java
@@ -0,0 +1,83 @@
+package org.apache.maven.project.workspace;
+
+import org.apache.maven.model.Model;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.build.model.ModelAndFile;
+import org.apache.maven.workspace.DefaultMavenWorkspaceStore;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+public class DefaultProjectWorkspaceTest
+ extends TestCase
+{
+
+ public void testStoreAndRetrieveModelAndFile()
+ {
+ ModelAndFile maf = newModelAndFile( "group", "artifact", "1" );
+
+ DefaultProjectWorkspace ws = new DefaultProjectWorkspace( new DefaultMavenWorkspaceStore() );
+ ws.storeModelAndFile( maf );
+
+ ModelAndFile r1 = ws.getModelAndFile( maf.getFile() );
+
+ assertSame( maf, r1 );
+
+ ModelAndFile r2 = ws.getModelAndFile( maf.getModel().getGroupId(), maf.getModel().getArtifactId(), maf.getModel().getVersion() );
+
+ assertSame( maf, r2 );
+ }
+
+ public void testStoreAndRetrieveProjectByFile_CoordinateRetrievalReturnsNull()
+ {
+ MavenProject project = newProject( "group", "artifact", "1" );
+
+ DefaultProjectWorkspace ws = new DefaultProjectWorkspace( new DefaultMavenWorkspaceStore() );
+ ws.storeProjectByFile( project );
+
+ assertSame( project, ws.getProject( project.getFile() ) );
+ assertNull( ws.getProject( project.getGroupId(), project.getArtifactId(), project.getVersion() ) );
+ }
+
+ public void testStoreAndRetrieveProjectByCoordinate_FileRetrievalReturnsNull()
+ {
+ MavenProject project = newProject( "group", "artifact", "1" );
+
+ DefaultProjectWorkspace ws = new DefaultProjectWorkspace( new DefaultMavenWorkspaceStore() );
+ ws.storeProjectByCoordinate( project );
+
+ assertNull( ws.getProject( project.getFile() ) );
+ assertSame( project, ws.getProject( project.getGroupId(), project.getArtifactId(), project.getVersion() ) );
+ }
+
+ private MavenProject newProject( String gid,
+ String aid,
+ String ver )
+ {
+ File f = new File( "test-project" );
+ Model model = new Model();
+ model.setGroupId( gid );
+ model.setArtifactId( aid );
+ model.setVersion( ver );
+
+ MavenProject project = new MavenProject( model );
+ project.setFile( f );
+ return project;
+ }
+
+ private ModelAndFile newModelAndFile( String gid,
+ String aid,
+ String ver )
+ {
+ File f = new File( "test-modelAndFile" );
+ Model model = new Model();
+ model.setGroupId( gid );
+ model.setArtifactId( aid );
+ model.setVersion( ver );
+
+ ModelAndFile maf = new ModelAndFile( model, f, false );
+ return maf;
+ }
+
+}
diff --git a/maven-project/src/test/java/org/apache/maven/project/workspace/ModelAndFileCachingTest.java b/maven-project/src/test/java/org/apache/maven/project/workspace/ModelAndFileCachingTest.java
new file mode 100644
index 0000000000..30ac5d41d8
--- /dev/null
+++ b/maven-project/src/test/java/org/apache/maven/project/workspace/ModelAndFileCachingTest.java
@@ -0,0 +1,234 @@
+package org.apache.maven.project.workspace;
+
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
+import org.apache.maven.model.Model;
+import org.apache.maven.profiles.DefaultProfileManager;
+import org.apache.maven.profiles.ProfileManager;
+import org.apache.maven.profiles.activation.DefaultProfileActivationContext;
+import org.apache.maven.project.ProjectBuildingException;
+import org.apache.maven.project.build.model.ModelAndFile;
+import org.apache.maven.project.build.model.ModelLineage;
+import org.apache.maven.project.build.model.ModelLineageBuilder;
+import org.apache.maven.workspace.MavenWorkspaceStore;
+import org.codehaus.plexus.PlexusTestCase;
+import org.codehaus.plexus.logging.Logger;
+import org.codehaus.plexus.util.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+public class ModelAndFileCachingTest
+ extends PlexusTestCase
+{
+ private static final String MY_PATH = ModelAndFileCachingTest.class.getName()
+ .replace( '.', '/' )
+ + ".class";
+
+ private ProjectWorkspace projectWorkspace;
+
+ private MavenWorkspaceStore workspaceStore;
+
+ private ModelLineageBuilder lineageBuilder;
+
+ private ArtifactRepositoryFactory repoFactory;
+
+ private ProfileManager profileManager;
+
+ private ArtifactRepository localRepo;
+
+ private ArtifactFactory artifactFactory;
+
+ private List dirsToDelete = new ArrayList();
+
+ public void setUp()
+ throws Exception
+ {
+ super.setUp();
+ getContainer().getLoggerManager().setThresholds( Logger.LEVEL_DEBUG );
+
+ projectWorkspace = (ProjectWorkspace) lookup( ProjectWorkspace.class );
+ workspaceStore = (MavenWorkspaceStore) lookup( MavenWorkspaceStore.class );
+ lineageBuilder = (ModelLineageBuilder) lookup( ModelLineageBuilder.class );
+ repoFactory = (ArtifactRepositoryFactory) lookup( ArtifactRepositoryFactory.class );
+ artifactFactory = (ArtifactFactory) lookup( ArtifactFactory.class );
+
+ File localRepoDir = File.createTempFile( "local-repo.", ".tmp" );
+ localRepoDir.delete();
+ localRepoDir.mkdirs();
+
+ dirsToDelete.add( localRepoDir );
+
+ localRepo = repoFactory.createLocalRepository( localRepoDir );
+ profileManager = new DefaultProfileManager(
+ getContainer(),
+ new DefaultProfileActivationContext(
+ System.getProperties(),
+ true ) );
+ }
+
+ public void tearDown()
+ throws Exception
+ {
+ workspaceStore.clear();
+
+ if ( !dirsToDelete.isEmpty() )
+ {
+ for ( Iterator it = dirsToDelete.iterator(); it.hasNext(); )
+ {
+ File dir = (File) it.next();
+ try
+ {
+ FileUtils.deleteDirectory( dir );
+ }
+ catch ( IOException e )
+ {
+ // ignore.
+ }
+ }
+ }
+
+ super.tearDown();
+ }
+
+ public void testResolveParentPom_PreferCachedInstance()
+ throws IOException, ProjectBuildingException
+ {
+ File childPomFile = getFile( "resolveParentPom/pom.xml" );
+
+ String gid = "tests";
+ String aid = "resolve-parent-pom-parent";
+ String ver = "1";
+
+ ModelAndFile maf = newModelAndFile( gid, aid, ver );
+ projectWorkspace.storeModelAndFile( maf );
+
+ ModelLineage lineage = lineageBuilder.buildModelLineage( childPomFile,
+ localRepo,
+ Collections.EMPTY_LIST,
+ profileManager,
+ false,
+ false );
+
+ assertSame( maf.getModel(), lineage.getDeepestAncestorModel() );
+ }
+
+ public void testResolveParentPom_StoreByFileAndGAVIfUncached()
+ throws IOException, ProjectBuildingException
+ {
+ File childPomFile = getFile( "resolveParentPom/childAndParent/child/pom.xml" );
+ File parentPomFile = new File( childPomFile.getParentFile().getParentFile(), "pom.xml" );
+
+ String gid = "tests";
+ String aid = "childAndParent-parent";
+ String ver = "1";
+
+ ModelLineage lineage = lineageBuilder.buildModelLineage( childPomFile,
+ localRepo,
+ Collections.EMPTY_LIST,
+ profileManager,
+ false,
+ false );
+
+ assertEquals( parentPomFile.getCanonicalPath(), lineage.getDeepestAncestorFile()
+ .getCanonicalPath() );
+
+ ModelAndFile maf1 = projectWorkspace.getModelAndFile( gid, aid, ver );
+ assertNotNull( maf1 );
+ assertSame( maf1.getModel(), lineage.getDeepestAncestorModel() );
+
+ ModelAndFile maf2 = projectWorkspace.getModelAndFile( parentPomFile );
+ assertNotNull( maf2 );
+ assertSame( maf2.getModel(), lineage.getDeepestAncestorModel() );
+ }
+
+ public void testReadModel_PreferModelInstanceCachedByFile()
+ throws IOException, ProjectBuildingException
+ {
+ File pomFile = new File( "test/pom.xml" );
+
+ String gid = "tests";
+ String aid = "read-model";
+ String ver = "1";
+
+ ModelAndFile maf = newModelAndFile( gid, aid, ver, pomFile );
+ projectWorkspace.storeModelAndFile( maf );
+
+ ModelLineage lineage = lineageBuilder.buildModelLineage( pomFile,
+ localRepo,
+ Collections.EMPTY_LIST,
+ profileManager,
+ false,
+ false );
+
+ assertSame( maf.getModel(), lineage.getOriginatingModel() );
+ }
+
+ public void testBuildModelLineage_StoreByFileAndGAVIfUncached()
+ throws IOException, ProjectBuildingException
+ {
+ File pomFile = getFile( "buildModelLineage/pom.xml" );
+
+ String gid = "tests";
+ String aid = "build-model-lineage";
+ String ver = "1";
+
+ ModelLineage lineage = lineageBuilder.buildModelLineage( pomFile,
+ localRepo,
+ Collections.EMPTY_LIST,
+ profileManager,
+ false,
+ false );
+
+ assertEquals( pomFile.getCanonicalPath(), lineage.getOriginatingPOMFile()
+ .getCanonicalPath() );
+
+ ModelAndFile maf1 = projectWorkspace.getModelAndFile( gid, aid, ver );
+ assertNotNull( maf1 );
+ assertSame( maf1.getModel(), lineage.getOriginatingModel() );
+
+ ModelAndFile maf2 = projectWorkspace.getModelAndFile( pomFile );
+ assertNotNull( maf2 );
+ assertSame( maf2.getModel(), lineage.getOriginatingModel() );
+ }
+
+ private ModelAndFile newModelAndFile( String gid,
+ String aid,
+ String ver )
+ throws IOException
+ {
+ return newModelAndFile( gid, aid, ver, File.createTempFile( "model-and-file.", ".tmp" ) );
+ }
+
+ private ModelAndFile newModelAndFile( String gid,
+ String aid,
+ String ver,
+ File file )
+ {
+ Model model = new Model();
+ model.setGroupId( gid );
+ model.setArtifactId( aid );
+ model.setVersion( ver );
+
+ ModelAndFile maf = new ModelAndFile( model, file, false );
+
+ return maf;
+ }
+
+ private File getFile( String path )
+ {
+ ClassLoader cloader = Thread.currentThread().getContextClassLoader();
+ URL myRes = cloader.getResource( MY_PATH );
+
+ File myFile = new File( myRes.getPath() );
+
+ return new File( myFile.getParentFile(), path );
+ }
+
+}
diff --git a/maven-project/src/test/java/org/apache/maven/project/workspace/ProjectCachingTest.java b/maven-project/src/test/java/org/apache/maven/project/workspace/ProjectCachingTest.java
new file mode 100644
index 0000000000..9280d5fced
--- /dev/null
+++ b/maven-project/src/test/java/org/apache/maven/project/workspace/ProjectCachingTest.java
@@ -0,0 +1,286 @@
+package org.apache.maven.project.workspace;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.InvalidRepositoryException;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
+import org.apache.maven.model.Model;
+import org.apache.maven.profiles.DefaultProfileManager;
+import org.apache.maven.profiles.ProfileManager;
+import org.apache.maven.profiles.activation.DefaultProfileActivationContext;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.MavenProjectBuilder;
+import org.apache.maven.project.ProjectBuildingException;
+import org.apache.maven.project.build.model.ModelLineageBuilder;
+import org.apache.maven.workspace.MavenWorkspaceStore;
+import org.codehaus.plexus.PlexusTestCase;
+import org.codehaus.plexus.logging.Logger;
+import org.codehaus.plexus.util.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+// TODO: Add conversion/tests for modelAndFileCache -> projectWorkspace stuff in simple cases.
+// TODO: Add tests for project parents from cache (using model-and-file stuff, maybe?)
+public class ProjectCachingTest
+ extends PlexusTestCase
+{
+
+ private static final String MY_PATH = ProjectCachingTest.class.getName().replace( '.', '/' )
+ + ".class";
+
+ private ProjectWorkspace projectWorkspace;
+
+ private MavenWorkspaceStore workspaceStore;
+
+ private MavenProjectBuilder projectBuilder;
+
+ private ModelLineageBuilder lineageBuilder;
+
+ private ArtifactRepositoryFactory repoFactory;
+
+ private ProfileManager profileManager;
+
+ private ArtifactRepository localRepo;
+
+ private ArtifactFactory artifactFactory;
+
+ private List dirsToDelete = new ArrayList();
+
+ public void setUp()
+ throws Exception
+ {
+ super.setUp();
+ getContainer().getLoggerManager().setThresholds( Logger.LEVEL_DEBUG );
+
+ projectWorkspace = (ProjectWorkspace) lookup( ProjectWorkspace.class );
+ workspaceStore = (MavenWorkspaceStore) lookup( MavenWorkspaceStore.class );
+ projectBuilder = (MavenProjectBuilder) lookup( MavenProjectBuilder.class );
+ lineageBuilder = (ModelLineageBuilder) lookup( ModelLineageBuilder.class );
+ repoFactory = (ArtifactRepositoryFactory) lookup( ArtifactRepositoryFactory.class );
+ artifactFactory = (ArtifactFactory) lookup( ArtifactFactory.class );
+
+ File localRepoDir = File.createTempFile( "local-repo.", ".tmp" );
+ localRepoDir.delete();
+ localRepoDir.mkdirs();
+
+ dirsToDelete.add( localRepoDir );
+
+ localRepo = repoFactory.createLocalRepository( localRepoDir );
+ profileManager = new DefaultProfileManager(
+ getContainer(),
+ new DefaultProfileActivationContext(
+ System.getProperties(),
+ true ) );
+ }
+
+ public void tearDown()
+ throws Exception
+ {
+ workspaceStore.clear();
+
+ if ( !dirsToDelete.isEmpty() )
+ {
+ for ( Iterator it = dirsToDelete.iterator(); it.hasNext(); )
+ {
+ File dir = (File) it.next();
+ try
+ {
+ FileUtils.deleteDirectory( dir );
+ }
+ catch ( IOException e )
+ {
+ // ignore.
+ }
+ }
+ }
+
+ super.tearDown();
+ }
+
+ public void testBuildFromRepository_PreferCachedProject()
+ throws ProjectBuildingException
+ {
+ String gid = "org.apache.maven.tests";
+ String aid = "buildFromRepo-checkCacheFirst";
+ String ver = "1";
+
+ MavenProject project = newProject( gid, aid, ver );
+ projectWorkspace.storeProjectByCoordinate( project );
+
+ Artifact artifact = artifactFactory.createProjectArtifact( gid, aid, ver );
+
+ MavenProject result = projectBuilder.buildFromRepository( artifact,
+ Collections.EMPTY_LIST,
+ localRepo );
+
+ assertSame( project, result );
+ }
+
+ public void testBuildFromRepository_StoreProjectByCoordOnlyIfUncached()
+ throws ProjectBuildingException, InvalidRepositoryException
+ {
+ File lrDir = getFile( "buildFromRepo" );
+ File pomFile = new File( lrDir, "tests/project-caching/1/project-caching-1.pom" );
+
+ String gid = "tests";
+ String aid = "project-caching";
+ String ver = "1";
+
+ Artifact artifact = artifactFactory.createProjectArtifact( gid, aid, ver );
+
+ ArtifactRepository localRepo = repoFactory.createLocalRepository( lrDir );
+
+ MavenProject project = projectBuilder.buildFromRepository( artifact,
+ Collections.EMPTY_LIST,
+ localRepo );
+
+ MavenProject r1 = projectWorkspace.getProject( pomFile );
+
+ MavenProject r2 = projectWorkspace.getProject( gid, aid, ver );
+
+ assertNull( r1 );
+
+ assertSame( project, r2 );
+ }
+
+ public void testBuildFromRepository_DontCheckCacheForRELEASEMetaVersion()
+ throws ProjectBuildingException, InvalidRepositoryException
+ {
+ File lrDir = getFile( "buildFromRepo" );
+ File pomFile = new File( lrDir, "tests/project-caching/1/project-caching-1.pom" );
+
+ String gid = "tests";
+ String aid = "project-caching";
+ String ver = "1";
+
+ MavenProject seed = newProject( gid, aid, ver );
+
+ Artifact artifact = artifactFactory.createProjectArtifact( gid,
+ aid,
+ Artifact.RELEASE_VERSION );
+
+ ArtifactRepository localRepo = repoFactory.createLocalRepository( lrDir );
+
+ MavenProject project = projectBuilder.buildFromRepository( artifact,
+ Collections.EMPTY_LIST,
+ localRepo );
+
+ assertNotSame( seed, project );
+
+ MavenProject r1 = projectWorkspace.getProject( pomFile );
+
+ MavenProject r2 = projectWorkspace.getProject( gid, aid, ver );
+
+ assertNull( r1 );
+
+ assertSame( project, r2 );
+ }
+
+ public void testBuildFromRepository_DontCheckCacheForLATESTMetaVersion()
+ throws ProjectBuildingException, InvalidRepositoryException
+ {
+ File lrDir = getFile( "buildFromRepo" );
+ File pomFile = new File( lrDir, "tests/project-caching/1/project-caching-1.pom" );
+
+ String gid = "tests";
+ String aid = "project-caching";
+ String ver = "1";
+
+ MavenProject seed = newProject( gid, aid, ver );
+ projectWorkspace.storeProjectByCoordinate( seed );
+
+ Artifact artifact = artifactFactory.createProjectArtifact( gid,
+ aid,
+ Artifact.RELEASE_VERSION );
+
+ ArtifactRepository localRepo = repoFactory.createLocalRepository( lrDir );
+
+ MavenProject project = projectBuilder.buildFromRepository( artifact,
+ Collections.EMPTY_LIST,
+ localRepo );
+
+ assertNotSame( seed, project );
+
+ MavenProject r1 = projectWorkspace.getProject( pomFile );
+
+ MavenProject r2 = projectWorkspace.getProject( gid, aid, ver );
+
+ assertNull( r1 );
+
+ assertSame( project, r2 );
+ }
+
+ public void testBuildFromFile_PreferProjectCachedByFile()
+ throws ProjectBuildingException, InvalidRepositoryException
+ {
+ File pomFile = getFile( "buildFromFile/pom.xml" );
+
+ String gid = "org.apache.maven.tests";
+ String aid = "build-from-file";
+ String ver = "1";
+
+ MavenProject seed = newProject( gid, aid, ver );
+ seed.setFile( pomFile );
+
+ projectWorkspace.storeProjectByFile( seed );
+
+ MavenProject project = projectBuilder.build( pomFile, localRepo, profileManager );
+
+ assertSame( seed, project );
+
+ assertNull( projectWorkspace.getProject( gid, aid, ver ) );
+ }
+
+ public void testBuildFromFile_StoreByCoordAndFileIfUncached()
+ throws ProjectBuildingException, InvalidRepositoryException
+ {
+ File pomFile = getFile( "buildFromFile/pom.xml" );
+
+ String gid = "org.apache.maven.tests";
+ String aid = "build-from-file";
+ String ver = "1";
+
+ assertNull( projectWorkspace.getProject( pomFile ) );
+ assertNull( projectWorkspace.getProject( gid, aid, ver ) );
+
+ MavenProject project = projectBuilder.build( pomFile, localRepo, profileManager );
+
+ MavenProject byFile = projectWorkspace.getProject( pomFile );
+ MavenProject byCoord = projectWorkspace.getProject( gid, aid, ver );
+
+ assertSame( project, byFile );
+ assertSame( project, byCoord );
+ }
+
+ private MavenProject newProject( String gid,
+ String aid,
+ String ver )
+ {
+ Model model = new Model();
+ model.setGroupId( gid );
+ model.setArtifactId( aid );
+ model.setVersion( ver );
+
+ MavenProject project = new MavenProject( model );
+
+ return project;
+ }
+
+ private File getFile( String path )
+ {
+ ClassLoader cloader = Thread.currentThread().getContextClassLoader();
+ URL myRes = cloader.getResource( MY_PATH );
+
+ File myFile = new File( myRes.getPath() );
+
+ return new File( myFile.getParentFile(), path );
+ }
+
+}
diff --git a/maven-project/src/test/resources/org/apache/maven/project/ProjectClasspathTest.xml b/maven-project/src/test/resources/org/apache/maven/project/ProjectClasspathTest.xml
index f02fb46fe9..e74455e1c7 100644
--- a/maven-project/src/test/resources/org/apache/maven/project/ProjectClasspathTest.xml
+++ b/maven-project/src/test/resources/org/apache/maven/project/ProjectClasspathTest.xml
@@ -80,6 +80,9 @@ under the License.
test
org.apache.maven.project.TestProjectBuilder
+
+ org.apache.maven.project.workspace.ProjectWorkspace
+
org.apache.maven.project.build.model.ModelLineageBuilder
default
diff --git a/maven-project/src/test/resources/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.xml b/maven-project/src/test/resources/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.xml
index 4d5474bee7..b76f324e0a 100644
--- a/maven-project/src/test/resources/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.xml
+++ b/maven-project/src/test/resources/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.xml
@@ -78,6 +78,9 @@ under the License.
test
org.apache.maven.project.TestProjectBuilder
+
+ org.apache.maven.project.workspace.ProjectWorkspace
+
org.apache.maven.project.build.model.ModelLineageBuilder
default
diff --git a/maven-project/src/test/resources/org/apache/maven/project/workspace/buildFromFile/pom.xml b/maven-project/src/test/resources/org/apache/maven/project/workspace/buildFromFile/pom.xml
new file mode 100644
index 0000000000..45dc77d2a9
--- /dev/null
+++ b/maven-project/src/test/resources/org/apache/maven/project/workspace/buildFromFile/pom.xml
@@ -0,0 +1,8 @@
+
+ 4.0.0
+
+ org.apache.maven.tests
+ build-from-file
+ 1
+
+
\ No newline at end of file
diff --git a/maven-project/src/test/resources/org/apache/maven/project/workspace/buildFromRepo/tests/project-caching/1/project-caching-1.pom b/maven-project/src/test/resources/org/apache/maven/project/workspace/buildFromRepo/tests/project-caching/1/project-caching-1.pom
new file mode 100644
index 0000000000..d42117656a
--- /dev/null
+++ b/maven-project/src/test/resources/org/apache/maven/project/workspace/buildFromRepo/tests/project-caching/1/project-caching-1.pom
@@ -0,0 +1,8 @@
+
+ 4.0.0
+
+ tests
+ project-caching
+ 1
+
+
\ No newline at end of file
diff --git a/maven-project/src/test/resources/org/apache/maven/project/workspace/buildFromRepo/tests/project-caching/maven-metadata-local.xml b/maven-project/src/test/resources/org/apache/maven/project/workspace/buildFromRepo/tests/project-caching/maven-metadata-local.xml
new file mode 100644
index 0000000000..a608b4f81d
--- /dev/null
+++ b/maven-project/src/test/resources/org/apache/maven/project/workspace/buildFromRepo/tests/project-caching/maven-metadata-local.xml
@@ -0,0 +1,11 @@
+
+ tests
+ project-caching
+
+ 1
+ 1
+
+ 1
+
+
+
\ No newline at end of file
diff --git a/maven-project/src/test/resources/org/apache/maven/project/workspace/buildModelLineage/pom.xml b/maven-project/src/test/resources/org/apache/maven/project/workspace/buildModelLineage/pom.xml
new file mode 100644
index 0000000000..5c62a787cc
--- /dev/null
+++ b/maven-project/src/test/resources/org/apache/maven/project/workspace/buildModelLineage/pom.xml
@@ -0,0 +1,7 @@
+
+ 4.0.0
+
+ tests
+ build-model-lineage
+ 1
+
\ No newline at end of file
diff --git a/maven-project/src/test/resources/org/apache/maven/project/workspace/resolveParentPom/childAndParent/child/pom.xml b/maven-project/src/test/resources/org/apache/maven/project/workspace/resolveParentPom/childAndParent/child/pom.xml
new file mode 100644
index 0000000000..5953c32e2f
--- /dev/null
+++ b/maven-project/src/test/resources/org/apache/maven/project/workspace/resolveParentPom/childAndParent/child/pom.xml
@@ -0,0 +1,10 @@
+
+ 4.0.0
+
+ tests
+ childAndParent-parent
+ 1
+
+
+ childAndParent-child
+
\ No newline at end of file
diff --git a/maven-project/src/test/resources/org/apache/maven/project/workspace/resolveParentPom/childAndParent/pom.xml b/maven-project/src/test/resources/org/apache/maven/project/workspace/resolveParentPom/childAndParent/pom.xml
new file mode 100644
index 0000000000..365ec18388
--- /dev/null
+++ b/maven-project/src/test/resources/org/apache/maven/project/workspace/resolveParentPom/childAndParent/pom.xml
@@ -0,0 +1,7 @@
+
+ 4.0.0
+
+ tests
+ childAndParent-parent
+ 1
+
\ No newline at end of file
diff --git a/maven-project/src/test/resources/org/apache/maven/project/workspace/resolveParentPom/pom.xml b/maven-project/src/test/resources/org/apache/maven/project/workspace/resolveParentPom/pom.xml
new file mode 100644
index 0000000000..e0eec3a2b0
--- /dev/null
+++ b/maven-project/src/test/resources/org/apache/maven/project/workspace/resolveParentPom/pom.xml
@@ -0,0 +1,10 @@
+
+ 4.0.0
+
+ tests
+ resolve-parent-pom-parent
+ 1
+
+
+ resolve-parent-pom
+
\ No newline at end of file
diff --git a/maven-workspace/pom.xml b/maven-workspace/pom.xml
new file mode 100644
index 0000000000..263a86787a
--- /dev/null
+++ b/maven-workspace/pom.xml
@@ -0,0 +1,17 @@
+
+
+ maven
+ org.apache.maven
+ 2.1-SNAPSHOT
+
+ 4.0.0
+ maven-workspace
+ maven-workspace
+
+
+
+ org.codehaus.plexus
+ plexus-container-default
+
+
+
\ No newline at end of file
diff --git a/maven-workspace/src/main/java/org/apache/maven/workspace/DefaultMavenWorkspaceStore.java b/maven-workspace/src/main/java/org/apache/maven/workspace/DefaultMavenWorkspaceStore.java
new file mode 100644
index 0000000000..7f48202db8
--- /dev/null
+++ b/maven-workspace/src/main/java/org/apache/maven/workspace/DefaultMavenWorkspaceStore.java
@@ -0,0 +1,66 @@
+package org.apache.maven.workspace;
+
+import org.codehaus.plexus.logging.LogEnabled;
+import org.codehaus.plexus.logging.Logger;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+public class DefaultMavenWorkspaceStore
+ implements MavenWorkspaceStore, LogEnabled
+{
+
+ private Map caches = new HashMap();
+// private Logger logger;
+
+ public void clear()
+ {
+ for ( Iterator it = caches.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+// String cacheType = (String) entry.getKey();
+ Map cache = (Map) entry.getValue();
+
+// getLogger().debug( "Clearing workspace cache for: " + cacheType + " (" + cache.size() + " entries)" );
+ cache.clear();
+ }
+ }
+
+ public Map getWorkspaceCache( String cacheType )
+ {
+ Map result = (Map) caches.get( cacheType );
+
+ if ( result == null )
+ {
+ result = new HashMap();
+ initWorkspaceCache( cacheType, result );
+ }
+
+// getLogger().debug( "Retrieving workspace cache for: " + cacheType + " (" + result.size() + " entries)" );
+ return result;
+ }
+
+ public void initWorkspaceCache( String cacheType,
+ Map cache )
+ {
+// getLogger().debug( "Initializing workspace cache for: " + cacheType + " (" + cache.size() + " entries)" );
+ caches.put( cacheType, cache );
+ }
+
+// protected Logger getLogger()
+// {
+// if ( logger == null )
+// {
+// logger = new ConsoleLogger ( Logger.LEVEL_INFO, "internal" );
+// }
+//
+// return logger;
+// }
+
+ public void enableLogging( Logger logger )
+ {
+// this.logger = logger;
+ }
+
+}
diff --git a/maven-workspace/src/main/java/org/apache/maven/workspace/MavenWorkspaceStore.java b/maven-workspace/src/main/java/org/apache/maven/workspace/MavenWorkspaceStore.java
new file mode 100644
index 0000000000..44dd37645f
--- /dev/null
+++ b/maven-workspace/src/main/java/org/apache/maven/workspace/MavenWorkspaceStore.java
@@ -0,0 +1,14 @@
+package org.apache.maven.workspace;
+
+import java.util.Map;
+
+public interface MavenWorkspaceStore
+{
+
+ Map getWorkspaceCache( String cacheType );
+
+ void initWorkspaceCache( String cacheType, Map cache );
+
+ void clear();
+
+}
diff --git a/maven-workspace/src/main/resources/META-INF/plexus/components.xml b/maven-workspace/src/main/resources/META-INF/plexus/components.xml
new file mode 100644
index 0000000000..a5c9b39208
--- /dev/null
+++ b/maven-workspace/src/main/resources/META-INF/plexus/components.xml
@@ -0,0 +1,9 @@
+
+
+
+ org.apache.maven.workspace.MavenWorkspaceStore
+ default
+ org.apache.maven.workspace.DefaultMavenWorkspaceStore
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 4034ff769e..8d69b86928 100644
--- a/pom.xml
+++ b/pom.xml
@@ -209,6 +209,7 @@ under the License.
maven-project
maven-reporting-api
maven-embedder
+ maven-workspace