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