Adding the beginnings of a workspace to Maven, which is just a shared cache component for project, model, and POM file instances (for now). This allows fine-grained control over when such caches are cleared in environments where embedder instances may be reused multiple times, and will eventually enable new profile activators that require access to project information in the current build along with other advanced caching and cache-querying features.

git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@632482 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
John Dennis Casey 2008-02-29 22:58:00 +00:00
parent 4411b1c425
commit a5f49900f2
47 changed files with 1678 additions and 116 deletions

View File

@ -31,6 +31,11 @@ under the License.
<artifactId>maven-core</artifactId>
<name>Maven Core</name>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-workspace</artifactId>
<version>2.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-lifecycle</artifactId>

View File

@ -22,6 +22,7 @@
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 MavenExecutionRequest setProfileActivationContext( ProfileActivationConte
this.profileActivationContext = profileActivationContext;
return this;
}
public MavenWorkspaceMonitor getWorkspaceMonitor()
{
return workspaceMonitor;
}
public MavenExecutionRequest setWorkspaceMonitor( MavenWorkspaceMonitor workspaceMonitor )
{
this.workspaceMonitor = workspaceMonitor;
return this;
}
}

View File

@ -23,6 +23,7 @@
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();
}

View File

@ -305,7 +305,10 @@ private void executeTaskSegmentsForProject( TaskSegment segment,
}
}
dispatcher.dispatchEnd( MavenEvents.PHASE_EXECUTION, currentPhase );
if ( currentPhase != null )
{
dispatcher.dispatchEnd( MavenEvents.PHASE_EXECUTION, currentPhase );
}
}
finally
{

View File

@ -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 );
}
}
}

View File

@ -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();
}
}

View File

@ -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 );
}

View File

@ -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();
}

View File

@ -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();
}
}

View File

@ -102,6 +102,7 @@ public void tearDown()
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 void test_addExtension_usingModel_ShouldLoadExtensionComponent()
assertNotNull( result );
getContainer().setLookupRealm( oldRealm );
System.out.println( "\n\nEND\n\n\n\n\n\n\n" );
}
public void test_addExtension_usingModel_ShouldLoadCustomLifecycleMappingAndArtifactHandler()

View File

@ -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();
}
}
}

View File

@ -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 );
}
}
}

View File

@ -19,6 +19,8 @@
*/
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();
}

View File

@ -19,6 +19,8 @@
*/
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&lt;URL>. */
/** List&lt;URL&gt;. */
private List extensions = new ArrayList();
private MavenEmbedderLogger logger;
@ -64,6 +66,11 @@ public class DefaultConfiguration
private CoreErrorReporter errorReporter;
/** List&lt;EventMonitor&gt;. */
private List eventMonitors;
private MavenWorkspaceMonitor workspaceMonitor;
/** Creates a new instance of DefaultConfiguration */
public DefaultConfiguration()
{
@ -246,4 +253,38 @@ public Configuration setErrorReporter( CoreErrorReporter errorReporter )
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;
}
}

View File

@ -74,6 +74,7 @@
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 MavenExecutionRequest getDefaultRequest()
return request;
}
protected MavenWorkspaceStore getWorkspaceStore()
{
return workspaceStore;
}
// ----------------------------------------------------------------------
// Accessors
// ----------------------------------------------------------------------
@ -596,6 +605,8 @@ public List getSiteLifecyclePhases()
private MavenExecutionRequest request;
private EventDispatcher dispatcher;
private void start( Configuration configuration )
throws MavenEmbedderException
{
@ -690,6 +701,8 @@ private void start( Configuration configuration )
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 @@ private void start( Configuration configuration )
request = new DefaultMavenExecutionRequest();
populator.populateDefaults( request, configuration );
dispatcher = new DefaultEventDispatcher( request.getEventMonitors() );
}
catch ( ComponentLookupException e )
{

View File

@ -33,6 +33,9 @@
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.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 MavenExecutionRequest populateDefaults( MavenExecutionRequest request,
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 )
{

View File

@ -23,6 +23,9 @@ under the License.
<role>org.apache.maven.embedder.execution.MavenExecutionRequestPopulator</role>
<implementation>org.apache.maven.embedder.execution.DefaultMavenExecutionRequestPopulator</implementation>
<requirements>
<requirement>
<role>org.apache.maven.workspace.MavenWorkspaceStore</role>
</requirement>
<requirement>
<role>org.apache.maven.artifact.manager.WagonManager</role>
<role-hint>default</role-hint>

View File

@ -0,0 +1,15 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>testing</groupId>
<artifactId>read-with-deps</artifactId>
<version>1</version>
<dependencies>
<dependency>
<groupId>tests</groupId>
<artifactId>dep</artifactId>
<version>1</version>
<type>pom</type>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,6 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>testing</groupId>
<artifactId>dep</artifactId>
<version>1</version>
</project>

View File

@ -0,0 +1,6 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>testing</groupId>
<artifactId>simple-read-project</artifactId>
<version>1</version>
</project>

View File

@ -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();
}
}
}

View File

@ -32,6 +32,11 @@ under the License.
<description>This library is used to not only read Maven project object model files, but to assemble inheritence
and to retrieve remote models as required.</description>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-workspace</artifactId>
<version>2.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-profile</artifactId>

View File

@ -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
{

View File

@ -67,6 +67,7 @@
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 @@ private MavenProject assembleLineage( Model model,
if ( lastProject != null )
{
// TODO: Use cached parent project here, and stop looping, if possible...
lastProject.setParent( project );
project = lastProject.getParent();

View File

@ -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 @@ private List aggregateRepositoryLists( List remoteRepositories, List remoteArtif
}
}
// 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 );
}
}
}

View File

@ -35,6 +35,7 @@
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 ModelLineage buildModelLineage( File pom,
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

View File

@ -13,7 +13,7 @@ public class ModelAndFile
private final boolean validProfilesXmlLocation;
ModelAndFile( Model model,
public ModelAndFile( Model model,
File file,
boolean validProfilesXmlLocation )
{

View File

@ -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;
}
}

View File

@ -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 );
}

View File

@ -41,6 +41,9 @@ under the License.
<role-hint>default</role-hint>
<implementation>org.apache.maven.project.build.model.DefaultModelLineageBuilder</implementation>
<requirements>
<requirement>
<role>org.apache.maven.project.workspace.ProjectWorkspace</role>
</requirement>
<requirement>
<role>org.apache.maven.profiles.build.ProfileAdvisor</role>
<role-hint>default</role-hint>
@ -107,6 +110,9 @@ under the License.
<role-hint>default</role-hint>
<implementation>org.apache.maven.project.DefaultMavenProjectBuilder</implementation>
<requirements>
<requirement>
<role>org.apache.maven.project.workspace.ProjectWorkspace</role>
</requirement>
<requirement>
<role>org.apache.maven.artifact.metadata.ArtifactMetadataSource</role>
</requirement>
@ -310,6 +316,17 @@ under the License.
</requirement>
</requirements>
</component>
<component>
<role>org.apache.maven.project.workspace.ProjectWorkspace</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.project.workspace.DefaultProjectWorkspace</implementation>
<requirements>
<requirement>
<role>org.apache.maven.workspace.MavenWorkspaceStore</role>
</requirement>
</requirements>
</component>
</components>
</component-set>

View File

@ -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;
}
}

View File

@ -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 );
}
}

View File

@ -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 );
}
}

View File

@ -80,6 +80,9 @@ under the License.
<role-hint>test</role-hint>
<implementation>org.apache.maven.project.TestProjectBuilder</implementation>
<requirements>
<requirement>
<role>org.apache.maven.project.workspace.ProjectWorkspace</role>
</requirement>
<requirement>
<role>org.apache.maven.project.build.model.ModelLineageBuilder</role>
<role-hint>default</role-hint>

View File

@ -78,6 +78,9 @@ under the License.
<role-hint>test</role-hint>
<implementation>org.apache.maven.project.TestProjectBuilder</implementation>
<requirements>
<requirement>
<role>org.apache.maven.project.workspace.ProjectWorkspace</role>
</requirement>
<requirement>
<role>org.apache.maven.project.build.model.ModelLineageBuilder</role>
<role-hint>default</role-hint>

View File

@ -0,0 +1,8 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.maven.tests</groupId>
<artifactId>build-from-file</artifactId>
<version>1</version>
</project>

View File

@ -0,0 +1,8 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>tests</groupId>
<artifactId>project-caching</artifactId>
<version>1</version>
</project>

View File

@ -0,0 +1,11 @@
<metadata>
<groupId>tests</groupId>
<artifactId>project-caching</artifactId>
<versioning>
<release>1</release>
<latest>1</latest>
<versions>
<version>1</version>
</versions>
</versioning>
</metadata>

View File

@ -0,0 +1,7 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>tests</groupId>
<artifactId>build-model-lineage</artifactId>
<version>1</version>
</project>

View File

@ -0,0 +1,10 @@
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>tests</groupId>
<artifactId>childAndParent-parent</artifactId>
<version>1</version>
</parent>
<artifactId>childAndParent-child</artifactId>
</project>

View File

@ -0,0 +1,7 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>tests</groupId>
<artifactId>childAndParent-parent</artifactId>
<version>1</version>
</project>

View File

@ -0,0 +1,10 @@
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>tests</groupId>
<artifactId>resolve-parent-pom-parent</artifactId>
<version>1</version>
</parent>
<artifactId>resolve-parent-pom</artifactId>
</project>

17
maven-workspace/pom.xml Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?><project>
<parent>
<artifactId>maven</artifactId>
<groupId>org.apache.maven</groupId>
<version>2.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>maven-workspace</artifactId>
<name>maven-workspace</name>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -0,0 +1,9 @@
<component-set>
<components>
<component>
<role>org.apache.maven.workspace.MavenWorkspaceStore</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.workspace.DefaultMavenWorkspaceStore</implementation>
</component>
</components>
</component-set>

View File

@ -209,6 +209,7 @@ under the License.
<module>maven-project</module>
<module>maven-reporting-api</module>
<module>maven-embedder</module>
<module>maven-workspace</module>
</modules>
<properties>