You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by be...@apache.org on 2009/09/28 15:56:26 UTC
svn commit: r819540 - in /maven/maven-3/trunk: ./
maven-core/src/main/java/org/apache/maven/classrealm/
maven-core/src/main/java/org/apache/maven/plugin/
maven-core/src/main/java/org/apache/maven/plugin/internal/
maven-core/src/main/java/org/apache/mav...
Author: bentmann
Date: Mon Sep 28 13:56:25 2009
New Revision: 819540
URL: http://svn.apache.org/viewvc?rev=819540&view=rev
Log:
[MNG-4381] Allow extension plugins to contribute non-core components to be reused by other plugins
Added:
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/DefaultExtensionRealmCache.java (with props)
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/ExtensionRealmCache.java (with props)
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectRealmCache.java (with props)
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptor.java (with props)
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java (with props)
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ProjectRealmCache.java (with props)
maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/ExtensionDescriptorBuilderTest.java (with props)
Modified:
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/MavenProject.java
maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingHelper.java
maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/EmptyProjectBuildingHelper.java
maven/maven-3/trunk/pom.xml
Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java?rev=819540&r1=819539&r2=819540&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java Mon Sep 28 13:56:25 2009
@@ -44,6 +44,14 @@
ClassRealm createProjectRealm( Model model );
/**
+ * Creates a new class realm for the specified build extension.
+ *
+ * @param plugin The extension plugin for which to create a realm, must not be {@code null}.
+ * @return The new extension realm, never {@code null}.
+ */
+ ClassRealm createExtensionRealm( Plugin extension );
+
+ /**
* Creates a new class realm for the specified plugin.
*
* @param plugin The plugin for which to create a realm, must not be {@code null}.
Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java?rev=819540&r1=819539&r2=819540&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java Mon Sep 28 13:56:25 2009
@@ -197,6 +197,16 @@
return "project>" + model.getGroupId() + ":" + model.getArtifactId() + ":" + model.getVersion();
}
+ public ClassRealm createExtensionRealm( Plugin plugin )
+ {
+ if ( plugin == null )
+ {
+ throw new IllegalArgumentException( "extension plugin missing" );
+ }
+
+ return createRealm( getKey( plugin, true ), null, null );
+ }
+
public ClassRealm createPluginRealm( Plugin plugin, ClassLoader parent, List<String> imports )
{
if ( plugin == null )
@@ -204,13 +214,14 @@
throw new IllegalArgumentException( "plugin missing" );
}
- return createRealm( getKey( plugin ), parent, imports );
+ return createRealm( getKey( plugin, false ), parent, imports );
}
- private String getKey( Plugin plugin )
+ private String getKey( Plugin plugin, boolean extension )
{
String version = ArtifactUtils.toSnapshotVersion( plugin.getVersion() );
- return "plugin>" + plugin.getGroupId() + ":" + plugin.getArtifactId() + ":" + version;
+ return ( extension ? "extension>" : "plugin>" ) + plugin.getGroupId() + ":" + plugin.getArtifactId() + ":"
+ + version;
}
private List<ClassRealmManagerDelegate> getDelegates()
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/DefaultExtensionRealmCache.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/DefaultExtensionRealmCache.java?rev=819540&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/DefaultExtensionRealmCache.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/DefaultExtensionRealmCache.java Mon Sep 28 13:56:25 2009
@@ -0,0 +1,231 @@
+package org.apache.maven.plugin;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.repository.RepositoryRequest;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Exclusion;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.project.ExtensionDescriptor;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.classworlds.realm.ClassRealm;
+import org.codehaus.plexus.component.annotations.Component;
+
+/**
+ * Default extension realm cache implementation. Assumes cached data does not change.
+ */
+@Component( role = ExtensionRealmCache.class )
+public class DefaultExtensionRealmCache
+ implements ExtensionRealmCache
+{
+
+ private static class CacheKey
+ {
+
+ private final Plugin extension;
+
+ private final List<ArtifactRepository> repositories = new ArrayList<ArtifactRepository>();
+
+ private final int hashCode;
+
+ public CacheKey( Plugin extension, RepositoryRequest repositoryRequest )
+ {
+ this.extension = extension.clone();
+ this.repositories.add( repositoryRequest.getLocalRepository() );
+ this.repositories.addAll( repositoryRequest.getRemoteRepositories() );
+
+ int hash = 17;
+ hash = hash * 31 + extensionHashCode( extension );
+ hash = hash * 31 + repositories.hashCode();
+ this.hashCode = hash;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if ( o == this )
+ {
+ return true;
+ }
+
+ if ( !( o instanceof CacheKey ) )
+ {
+ return false;
+ }
+
+ CacheKey other = (CacheKey) o;
+
+ return extensionEquals( extension, other.extension ) && eq( repositories, other.repositories );
+ }
+
+ }
+
+ private final Map<CacheKey, CacheRecord> cache = new HashMap<CacheKey, CacheRecord>();
+
+ public CacheRecord get( Plugin extension, RepositoryRequest repositoryRequest )
+ {
+ return cache.get( new CacheKey( extension, repositoryRequest ) );
+ }
+
+ public void put( Plugin extension, RepositoryRequest repositoryRequest, ClassRealm extensionRealm,
+ List<Artifact> extensionArtifacts, ExtensionDescriptor extensionDescriptor )
+ {
+ if ( extensionRealm == null || extensionArtifacts == null )
+ {
+ throw new NullPointerException();
+ }
+
+ CacheKey key = new CacheKey( extension, repositoryRequest );
+
+ if ( cache.containsKey( key ) )
+ {
+ throw new IllegalStateException( "Duplicate extension realm for extension " + extension.getId() );
+ }
+
+ CacheRecord record = new CacheRecord( extensionRealm, extensionArtifacts, extensionDescriptor );
+ cache.put( key, record );
+ }
+
+ public void flush()
+ {
+ cache.clear();
+ }
+
+ protected static int extensionHashCode( Plugin extension )
+ {
+ int hash = 17;
+
+ hash = hash * 31 + extension.getGroupId().hashCode();
+ hash = hash * 31 + extension.getArtifactId().hashCode();
+ hash = hash * 31 + extension.getVersion().hashCode();
+
+ for ( Dependency dependency : extension.getDependencies() )
+ {
+ hash = hash * 31 + dependency.getGroupId().hashCode();
+ hash = hash * 31 + dependency.getArtifactId().hashCode();
+ hash = hash * 31 + dependency.getVersion().hashCode();
+ hash = hash * 31 + dependency.getType().hashCode();
+ hash = hash * 31 + ( dependency.getClassifier() != null ? dependency.getClassifier().hashCode() : 0 );
+ hash = hash * 31 + ( dependency.getScope() != null ? dependency.getScope().hashCode() : 0 );
+
+ for ( Exclusion exclusion : dependency.getExclusions() )
+ {
+ hash = hash * 31 + exclusion.getGroupId().hashCode();
+ hash = hash * 31 + exclusion.getArtifactId().hashCode();
+ }
+ }
+
+ return hash;
+ }
+
+ private static boolean extensionEquals( Plugin a, Plugin b )
+ {
+ return eq( a.getGroupId(), b.getGroupId() ) //
+ && eq( a.getArtifactId(), b.getArtifactId() ) //
+ && eq( a.getVersion(), b.getVersion() ) //
+ && a.isExtensions() == b.isExtensions() //
+ && dependenciesEquals( a.getDependencies(), b.getDependencies() );
+ }
+
+ private static boolean dependenciesEquals( List<Dependency> a, List<Dependency> b )
+ {
+ if ( a.size() != b.size() )
+ {
+ return false;
+ }
+
+ Iterator<Dependency> aI = a.iterator();
+ Iterator<Dependency> bI = b.iterator();
+
+ while ( aI.hasNext() )
+ {
+ Dependency aD = aI.next();
+ Dependency bD = bI.next();
+
+ boolean r = eq( aD.getGroupId(), bD.getGroupId() ) //
+ && eq( aD.getArtifactId(), bD.getArtifactId() ) //
+ && eq( aD.getVersion(), bD.getVersion() ) //
+ && eq( aD.getType(), bD.getType() ) //
+ && eq( aD.getClassifier(), bD.getClassifier() ) //
+ && eq( aD.getScope(), bD.getScope() );
+
+ r &= exclusionsEquals( aD.getExclusions(), bD.getExclusions() );
+
+ if ( !r )
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static boolean exclusionsEquals( List<Exclusion> a, List<Exclusion> b )
+ {
+ if ( a.size() != b.size() )
+ {
+ return false;
+ }
+
+ Iterator<Exclusion> aI = a.iterator();
+ Iterator<Exclusion> bI = b.iterator();
+
+ while ( aI.hasNext() )
+ {
+ Exclusion aD = aI.next();
+ Exclusion bD = bI.next();
+
+ boolean r = eq( aD.getGroupId(), bD.getGroupId() ) //
+ && eq( aD.getArtifactId(), bD.getArtifactId() );
+
+ if ( !r )
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static <T> boolean eq( T s1, T s2 )
+ {
+ return s1 != null ? s1.equals( s2 ) : s2 == null;
+ }
+
+ public void register( MavenProject project, ClassRealm extensionRealm )
+ {
+ // default cache does not track extension usage
+ }
+
+}
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/DefaultExtensionRealmCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/DefaultExtensionRealmCache.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/ExtensionRealmCache.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/ExtensionRealmCache.java?rev=819540&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/ExtensionRealmCache.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/ExtensionRealmCache.java Mon Sep 28 13:56:25 2009
@@ -0,0 +1,77 @@
+package org.apache.maven.plugin;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.List;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.RepositoryRequest;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.project.ExtensionDescriptor;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.classworlds.realm.ClassRealm;
+
+/**
+ * Caches extension class realms. <strong>Warning:</strong> This is an internal utility interface that is only public
+ * for technical reasons, it is not part of the public API. In particular, this interface can be changed or deleted
+ * without prior notice.
+ *
+ * @author Igor Fedorenko
+ * @author Benjamin Bentmann
+ */
+public interface ExtensionRealmCache
+{
+
+ public static class CacheRecord
+ {
+
+ public final ClassRealm realm;
+
+ public final List<Artifact> artifacts;
+
+ public final ExtensionDescriptor desciptor;
+
+ public CacheRecord( ClassRealm realm, List<Artifact> artifacts, ExtensionDescriptor descriptor )
+ {
+ this.realm = realm;
+ this.artifacts = artifacts;
+ this.desciptor = descriptor;
+ }
+
+ }
+
+ CacheRecord get( Plugin extension, RepositoryRequest repositoryRequest );
+
+ void put( Plugin extension, RepositoryRequest repositoryRequest, ClassRealm extensionRealm,
+ List<Artifact> extensionArtifacts, ExtensionDescriptor extensionDescriptor );
+
+ void flush();
+
+ /**
+ * Registers the specified extension realm for usage with the given project. Integrators can use the information
+ * collected from this method in combination with a custom cache implementation to dispose unused extension realms
+ * from the cache.
+ *
+ * @param project The project that employs the extension realm, must not be {@code null}.
+ * @param extensionRealm The extension realm being used for the project, must not be {@code null}.
+ */
+ void register( MavenProject project, ClassRealm extensionRealm );
+
+}
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/ExtensionRealmCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/ExtensionRealmCache.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java?rev=819540&r1=819539&r2=819540&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java Mon Sep 28 13:56:25 2009
@@ -27,6 +27,7 @@
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -42,6 +43,7 @@
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.ResolutionErrorHandler;
+import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.classrealm.ClassRealmManager;
@@ -339,13 +341,16 @@
throw new IllegalArgumentException( "incomplete plugin descriptor, plugin artifact missing" );
}
+ MavenProject project = session.getCurrentProject();
+
RepositoryRequest request = new DefaultRepositoryRequest();
request.setLocalRepository( session.getLocalRepository() );
- request.setRemoteRepositories( session.getCurrentProject().getPluginArtifactRepositories() );
+ request.setRemoteRepositories( project.getPluginArtifactRepositories() );
request.setCache( session.getRepositoryCache() );
request.setOffline( session.isOffline() );
- List<Artifact> pluginArtifacts = resolvePluginArtifacts( plugin, pluginArtifact, request );
+ List<Artifact> pluginArtifacts =
+ resolvePluginArtifacts( plugin, pluginArtifact, request, project.getExtensionArtifactFilter() );
ClassRealm pluginRealm = classRealmManager.createPluginRealm( plugin, parent, imports );
@@ -417,7 +422,8 @@
*/
// FIXME: only exposed to allow workaround for MNG-4194
protected List<Artifact> resolvePluginArtifacts( Plugin plugin, Artifact pluginArtifact,
- RepositoryRequest repositoryRequest )
+ RepositoryRequest repositoryRequest,
+ ArtifactFilter extensionArtifactFilter )
throws PluginResolutionException
{
Set<Artifact> overrideArtifacts = new LinkedHashSet<Artifact>();
@@ -430,6 +436,11 @@
ArtifactFilter resolutionFilter = artifactFilterManager.getCoreArtifactFilter();
+ if ( extensionArtifactFilter != null )
+ {
+ resolutionFilter = new AndArtifactFilter( Arrays.asList( resolutionFilter, extensionArtifactFilter ) );
+ }
+
ArtifactResolutionRequest request = new ArtifactResolutionRequest( repositoryRequest );
request.setArtifact( pluginArtifact );
request.setArtifactDependencies( overrideArtifacts );
Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java?rev=819540&r1=819539&r2=819540&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java Mon Sep 28 13:56:25 2009
@@ -25,6 +25,7 @@
import org.apache.maven.artifact.repository.DefaultRepositoryRequest;
import org.apache.maven.artifact.repository.RepositoryRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
+import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.model.Model;
import org.apache.maven.model.building.AbstractModelBuildingListener;
import org.apache.maven.model.building.ModelBuildingEvent;
@@ -46,6 +47,8 @@
private ClassRealm projectRealm;
+ private ArtifactFilter extensionArtifactFilter;
+
private List<ArtifactRepository> remoteRepositories;
private List<ArtifactRepository> pluginRepositories;
@@ -79,6 +82,16 @@
}
/**
+ * Gets the artifact filter to exclude extension artifacts from plugin realms.
+ *
+ * @return The extension artifact filter or {@code null} if none.
+ */
+ public ArtifactFilter getExtentionArtifactFilter()
+ {
+ return extensionArtifactFilter;
+ }
+
+ /**
* Gets the effective remote artifact repositories for the project. The repository list is created from the
* repositories given by {@link ProjectBuildingRequest#getRemoteRepositories()} and the repositories given in the
* POM, i.e. {@link Model#getRepositories()}. The POM repositories themselves also contain any repositories
@@ -113,17 +126,6 @@
try
{
- remoteRepositories =
- projectBuildingHelper.createArtifactRepositories( model.getRepositories(), remoteRepositories,
- projectBuildingRequest );
- }
- catch ( Exception e )
- {
- event.getProblems().addError( "Invalid artifact repository: " + e.getMessage(), e );
- }
-
- try
- {
pluginRepositories =
projectBuildingHelper.createArtifactRepositories( model.getPluginRepositories(), pluginRepositories,
projectBuildingRequest );
@@ -143,7 +145,11 @@
repositoryRequest.setRemoteRepositories( pluginRepositories );
repositoryRequest.setOffline( projectBuildingRequest.isOffline() );
- projectRealm = projectBuildingHelper.createProjectRealm( model, repositoryRequest );
+ ProjectRealmCache.CacheRecord record =
+ projectBuildingHelper.createProjectRealm( model, repositoryRequest );
+
+ projectRealm = record.realm;
+ extensionArtifactFilter = record.extensionArtifactFilter;
}
catch ( ArtifactResolutionException e )
{
@@ -164,6 +170,18 @@
Thread.currentThread().setContextClassLoader( projectRealm );
}
}
+
+ // build the regular repos after extensions are loaded to allow for custom layouts
+ try
+ {
+ remoteRepositories =
+ projectBuildingHelper.createArtifactRepositories( model.getRepositories(), remoteRepositories,
+ projectBuildingRequest );
+ }
+ catch ( Exception e )
+ {
+ event.getProblems().addError( "Invalid artifact repository: " + e.getMessage(), e );
+ }
}
}
Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java?rev=819540&r1=819539&r2=819540&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java Mon Sep 28 13:56:25 2009
@@ -486,6 +486,7 @@
project.setPluginArtifactRepositories( listener.getPluginRepositories() );
project.setClassRealm( listener.getProjectRealm() );
+ project.setExtensionArtifactFilter( listener.getExtentionArtifactFilter() );
Build build = project.getBuild();
project.addScriptSourceRoot( build.getScriptSourceDirectory() );
Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java?rev=819540&r1=819539&r2=819540&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java Mon Sep 28 13:56:25 2009
@@ -19,10 +19,14 @@
* under the License.
*/
+import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.apache.maven.ArtifactFilterManager;
@@ -35,6 +39,8 @@
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.ResolutionErrorHandler;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
+import org.apache.maven.artifact.resolver.filter.ExclusionSetFilter;
+import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.classrealm.ClassRealmManager;
import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
@@ -42,6 +48,7 @@
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.Repository;
+import org.apache.maven.plugin.ExtensionRealmCache;
import org.apache.maven.plugin.version.DefaultPluginVersionRequest;
import org.apache.maven.plugin.version.PluginVersionRequest;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
@@ -75,6 +82,12 @@
private ClassRealmManager classRealmManager;
@Requirement
+ private ExtensionRealmCache extensionRealmCache;
+
+ @Requirement
+ private ProjectRealmCache projectRealmCache;
+
+ @Requirement
private RepositorySystem repositorySystem;
@Requirement
@@ -86,6 +99,8 @@
@Requirement
private PluginVersionResolver pluginVersionResolver;
+ private ExtensionDescriptorBuilder extensionDescriptorBuilder = new ExtensionDescriptorBuilder();
+
public List<ArtifactRepository> createArtifactRepositories( List<Repository> pomRepositories,
List<ArtifactRepository> externalRepositories,
ProjectBuildingRequest request )
@@ -114,51 +129,48 @@
return artifactRepositories;
}
- public ClassRealm createProjectRealm( Model model, RepositoryRequest repositoryRequest )
+ public synchronized ProjectRealmCache.CacheRecord createProjectRealm( Model model,
+ RepositoryRequest repositoryRequest )
throws ArtifactResolutionException, PluginVersionResolutionException
{
ClassRealm projectRealm = null;
- Build build = model.getBuild();
-
- if ( build == null )
- {
- return projectRealm;
- }
-
List<Plugin> extensionPlugins = new ArrayList<Plugin>();
- for ( Plugin plugin : build.getPlugins() )
+ Build build = model.getBuild();
+
+ if ( build != null )
{
- if ( plugin.isExtensions() )
+ for ( Extension extension : build.getExtensions() )
{
+ Plugin plugin = new Plugin();
+ plugin.setGroupId( extension.getGroupId() );
+ plugin.setArtifactId( extension.getArtifactId() );
+ plugin.setVersion( extension.getVersion() );
extensionPlugins.add( plugin );
}
+
+ for ( Plugin plugin : build.getPlugins() )
+ {
+ if ( plugin.isExtensions() )
+ {
+ extensionPlugins.add( plugin );
+ }
+ }
}
- if ( build.getExtensions().isEmpty() && extensionPlugins.isEmpty() )
+ if ( extensionPlugins.isEmpty() )
{
- return projectRealm;
+ return new ProjectRealmCache.CacheRecord( null, null );
}
- projectRealm = classRealmManager.createProjectRealm( model );
+ List<ClassRealm> extensionRealms = new ArrayList<ClassRealm>();
- for ( Extension extension : build.getExtensions() )
- {
- if ( extension.getVersion() == null )
- {
- PluginVersionRequest versionRequest = new DefaultPluginVersionRequest( repositoryRequest );
- versionRequest.setGroupId( extension.getGroupId() );
- versionRequest.setArtifactId( extension.getArtifactId() );
- extension.setVersion( pluginVersionResolver.resolve( versionRequest ).getVersion() );
- }
+ Map<ClassRealm, List<String>> exportedPackages = new HashMap<ClassRealm, List<String>>();
- Artifact artifact =
- repositorySystem.createArtifact( extension.getGroupId(), extension.getArtifactId(),
- extension.getVersion(), "jar" );
+ Map<ClassRealm, List<String>> exportedArtifacts = new HashMap<ClassRealm, List<String>>();
- populateRealm( projectRealm, artifact, null, repositoryRequest );
- }
+ List<Artifact> publicArtifacts = new ArrayList<Artifact>();
for ( Plugin plugin : extensionPlugins )
{
@@ -168,73 +180,206 @@
plugin.setVersion( pluginVersionResolver.resolve( versionRequest ).getVersion() );
}
- Artifact artifact = repositorySystem.createPluginArtifact( plugin );
+ ClassRealm extensionRealm;
+ List<Artifact> artifacts;
+ ExtensionDescriptor extensionDescriptor = null;
+
+ ExtensionRealmCache.CacheRecord record = extensionRealmCache.get( plugin, repositoryRequest );
- Set<Artifact> dependencies = new LinkedHashSet<Artifact>();
- for ( Dependency dependency : plugin.getDependencies() )
+ if ( record != null )
{
- dependencies.add( repositorySystem.createDependencyArtifact( dependency ) );
+ extensionRealm = record.realm;
+ artifacts = record.artifacts;
+ extensionDescriptor = record.desciptor;
}
+ else
+ {
+ artifacts = resolveExtensionArtifacts( plugin, repositoryRequest );
- populateRealm( projectRealm, artifact, dependencies, repositoryRequest );
- }
+ extensionRealm = classRealmManager.createExtensionRealm( plugin );
- try
- {
- container.discoverComponents( projectRealm );
- }
- catch ( Exception e )
- {
- throw new IllegalStateException( "Failed to discover components in project realm " + projectRealm.getId(),
- e );
- }
+ if ( logger.isDebugEnabled() )
+ {
+ logger.debug( "Populating extension realm for " + plugin.getId() );
+ }
- return projectRealm;
- }
+ for ( Artifact artifact : artifacts )
+ {
+ if ( artifact.getFile() != null )
+ {
+ if ( logger.isDebugEnabled() )
+ {
+ logger.debug( " Included: " + artifact.getId() );
+ }
+
+ try
+ {
+ extensionRealm.addURL( artifact.getFile().toURI().toURL() );
+ }
+ catch ( MalformedURLException e )
+ {
+ // Not going to happen
+ }
+ }
+ else
+ {
+ if ( logger.isDebugEnabled() )
+ {
+ logger.debug( " Excluded: " + artifact.getId() );
+ }
+ }
+ }
- private void populateRealm( ClassRealm realm, Artifact artifact, Set<Artifact> dependencies,
- RepositoryRequest repositoryRequest )
- throws ArtifactResolutionException
- {
- ArtifactResolutionRequest request = new ArtifactResolutionRequest( repositoryRequest );
- request.setArtifact( artifact );
- request.setArtifactDependencies( dependencies );
- request.setResolveTransitively( true );
- // FIXME setTransferListener
+ try
+ {
+ container.discoverComponents( extensionRealm );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalStateException( "Failed to discover components in extension realm "
+ + extensionRealm.getId(), e );
+ }
- ArtifactResolutionResult result = repositorySystem.resolve( request );
+ Artifact extensionArtifact = artifacts.get( 0 );
+ try
+ {
+ extensionDescriptor = extensionDescriptorBuilder.build( extensionArtifact.getFile() );
+ }
+ catch ( IOException e )
+ {
+ String message = "Invalid extension descriptor for " + plugin.getId() + ": " + e.getMessage();
+ if ( logger.isDebugEnabled() )
+ {
+ logger.error( message, e );
+ }
+ else
+ {
+ logger.error( message );
+ }
+ }
- resolutionErrorHandler.throwErrors( request, result );
+ extensionRealmCache.put( plugin, repositoryRequest, extensionRealm, artifacts, extensionDescriptor );
+ }
- ArtifactFilter filter = artifactFilterManager.getCoreArtifactFilter();
+ extensionRealms.add( extensionRealm );
+ if ( extensionDescriptor != null )
+ {
+ exportedPackages.put( extensionRealm, extensionDescriptor.getExportedPackages() );
+ exportedArtifacts.put( extensionRealm, extensionDescriptor.getExportedArtifacts() );
+ }
- for ( Artifact resultArtifact : result.getArtifacts() )
+ if ( !plugin.isExtensions() && artifacts.size() == 1 && artifacts.get( 0 ).getFile() != null )
+ {
+ /*
+ * This is purely for backward-compat with 2.x where <extensions> consisting of a single artifact where
+ * loaded into the core and hence available to plugins, in contrast to bigger extensions that were
+ * loaded into a dedicated realm which is invisible to plugins.
+ */
+ publicArtifacts.addAll( artifacts );
+ }
+ }
+
+ ProjectRealmCache.CacheRecord record = projectRealmCache.get( extensionRealms );
+
+ if ( record == null )
{
- if ( filter.include( resultArtifact ) )
+ projectRealm = classRealmManager.createProjectRealm( model );
+
+ if ( logger.isDebugEnabled() )
+ {
+ logger.debug( "Populating project realm for " + model.getId() );
+ }
+
+ for ( Artifact publicArtifact : publicArtifacts )
{
if ( logger.isDebugEnabled() )
{
- logger.debug( " Included: " + resultArtifact.getId() );
+ logger.debug( " Included: " + publicArtifact.getId() );
}
try
{
- realm.addURL( resultArtifact.getFile().toURI().toURL() );
+ projectRealm.addURL( publicArtifact.getFile().toURI().toURL() );
}
catch ( MalformedURLException e )
{
- throw new IllegalStateException( "Failed to populate project realm " + realm.getId() + " with "
- + artifact.getFile(), e );
+ // can't happen
}
}
- else
+
+ Set<String> exclusions = new LinkedHashSet<String>();
+
+ for ( ClassRealm extensionRealm : extensionRealms )
{
- if ( logger.isDebugEnabled() )
+ List<String> excludes = exportedArtifacts.get( extensionRealm );
+
+ if ( excludes != null )
+ {
+ exclusions.addAll( excludes );
+ }
+
+ List<String> exports = exportedPackages.get( extensionRealm );
+
+ if ( exports == null || exports.isEmpty() )
+ {
+ /*
+ * Most existing extensions don't define exported packages, i.e. no classes are to be exposed to
+ * plugins, yet the components provided by the extension (e.g. artifact handlers) must be
+ * accessible, i.e. we still must import the extension realm into the project realm.
+ */
+ exports = Arrays.asList( extensionRealm.getId() );
+ }
+
+ for ( String export : exports )
{
- logger.debug( " Excluded: " + resultArtifact.getId() );
+ projectRealm.importFrom( extensionRealm, export );
}
}
+
+ ArtifactFilter extensionArtifactFilter = null;
+ if ( !exclusions.isEmpty() )
+ {
+ extensionArtifactFilter = new ExclusionSetFilter( exclusions );
+ }
+
+ projectRealmCache.put( extensionRealms, projectRealm, extensionArtifactFilter );
+
+ record = new ProjectRealmCache.CacheRecord( projectRealm, extensionArtifactFilter );
+ }
+
+ return record;
+ }
+
+ private List<Artifact> resolveExtensionArtifacts( Plugin extensionPlugin, RepositoryRequest repositoryRequest )
+ throws ArtifactResolutionException
+ {
+ Artifact extensionArtifact = repositorySystem.createPluginArtifact( extensionPlugin );
+
+ Set<Artifact> overrideArtifacts = new LinkedHashSet<Artifact>();
+ for ( Dependency dependency : extensionPlugin.getDependencies() )
+ {
+ overrideArtifacts.add( repositorySystem.createDependencyArtifact( dependency ) );
}
+
+ ArtifactFilter collectionFilter = new ScopeArtifactFilter( Artifact.SCOPE_RUNTIME_PLUS_SYSTEM );
+
+ ArtifactFilter resolutionFilter = artifactFilterManager.getCoreArtifactFilter();
+
+ ArtifactResolutionRequest request = new ArtifactResolutionRequest( repositoryRequest );
+ request.setArtifact( extensionArtifact );
+ request.setArtifactDependencies( overrideArtifacts );
+ request.setCollectionFilter( collectionFilter );
+ request.setResolutionFilter( resolutionFilter );
+ request.setResolveRoot( true );
+ request.setResolveTransitively( true );
+
+ ArtifactResolutionResult result = repositorySystem.resolve( request );
+
+ resolutionErrorHandler.throwErrors( request, result );
+
+ List<Artifact> extensionArtifacts = new ArrayList<Artifact>( result.getArtifacts() );
+
+ return extensionArtifacts;
}
}
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectRealmCache.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectRealmCache.java?rev=819540&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectRealmCache.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectRealmCache.java Mon Sep 28 13:56:25 2009
@@ -0,0 +1,110 @@
+package org.apache.maven.project;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
+import org.codehaus.plexus.classworlds.realm.ClassRealm;
+import org.codehaus.plexus.component.annotations.Component;
+
+/**
+ * Default project realm cache implementation. Assumes cached data does not change.
+ */
+@Component( role = ProjectRealmCache.class )
+public class DefaultProjectRealmCache
+ implements ProjectRealmCache
+{
+
+ private static class CacheKey
+ {
+
+ private final List<? extends ClassRealm> extensionRealms;
+
+ private final int hashCode;
+
+ public CacheKey( List<? extends ClassRealm> extensionRealms )
+ {
+ this.extensionRealms = ( extensionRealms != null ) ? extensionRealms : Collections.<ClassRealm> emptyList();
+
+ this.hashCode = this.extensionRealms.hashCode();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if ( o == this )
+ {
+ return true;
+ }
+
+ if ( !( o instanceof CacheKey ) )
+ {
+ return false;
+ }
+
+ CacheKey other = (CacheKey) o;
+
+ return extensionRealms.equals( other.extensionRealms );
+ }
+
+ }
+
+ private final Map<CacheKey, CacheRecord> cache = new HashMap<CacheKey, CacheRecord>();
+
+ public CacheRecord get( List<? extends ClassRealm> extensionRealms )
+ {
+ return cache.get( new CacheKey( extensionRealms ) );
+ }
+
+ public void put( List<? extends ClassRealm> extensionRealms, ClassRealm projectRealm,
+ ArtifactFilter extensionArtifactFilter )
+ {
+ if ( projectRealm == null )
+ {
+ throw new NullPointerException();
+ }
+
+ CacheKey key = new CacheKey( extensionRealms );
+
+ if ( cache.containsKey( key ) )
+ {
+ throw new IllegalStateException( "Duplicate project realm for extensions " + extensionRealms );
+ }
+
+ CacheRecord record = new CacheRecord( projectRealm, extensionArtifactFilter );
+ cache.put( key, record );
+ }
+
+ public void flush()
+ {
+ cache.clear();
+ }
+
+}
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectRealmCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectRealmCache.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptor.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptor.java?rev=819540&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptor.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptor.java Mon Sep 28 13:56:25 2009
@@ -0,0 +1,88 @@
+package org.apache.maven.project;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides metadata about a build extension. <strong>Warning:</strong> This is an internal utility class that is only
+ * public for technical reasons, it is not part of the public API. In particular, this class can be changed or deleted
+ * without prior notice.
+ *
+ * @author Benjamin Bentmann
+ */
+public class ExtensionDescriptor
+{
+
+ private List<String> exportedPackages;
+
+ private List<String> exportedArtifacts;
+
+ ExtensionDescriptor()
+ {
+ // hide constructor
+ }
+
+ public List<String> getExportedPackages()
+ {
+ if ( exportedPackages == null )
+ {
+ exportedPackages = new ArrayList<String>();
+ }
+
+ return exportedPackages;
+ }
+
+ public void setExportedPackages( List<String> exportedPackages )
+ {
+ if ( exportedPackages == null )
+ {
+ this.exportedPackages = null;
+ }
+ else
+ {
+ this.exportedPackages = new ArrayList<String>( exportedPackages );
+ }
+ }
+
+ public List<String> getExportedArtifacts()
+ {
+ if ( exportedArtifacts == null )
+ {
+ exportedArtifacts = new ArrayList<String>();
+ }
+
+ return exportedArtifacts;
+ }
+
+ public void setExportedArtifacts( List<String> exportedArtifacts )
+ {
+ if ( exportedArtifacts == null )
+ {
+ this.exportedArtifacts = null;
+ }
+ else
+ {
+ this.exportedArtifacts = new ArrayList<String>( exportedArtifacts );
+ }
+ }
+
+}
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptor.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java?rev=819540&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java Mon Sep 28 13:56:25 2009
@@ -0,0 +1,159 @@
+package org.apache.maven.project;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+
+/**
+ * Creates an extension descriptor from some XML stream.
+ *
+ * @author Benjamin Bentmann
+ */
+class ExtensionDescriptorBuilder
+{
+
+ private String getExtensionDescriptorLocation()
+ {
+ return "META-INF/maven/extension.xml";
+ }
+
+ /**
+ * Extracts the extension descriptor (if any) from the specified JAR file.
+ *
+ * @param extensionJar The JAR file or directory to extract the descriptor from, must not be {@code null}.
+ * @return The extracted descriptor or {@code null} if no descriptor was found.
+ * @throws IOException If the descriptor is present but could not be parsed.
+ */
+ public ExtensionDescriptor build( File extensionJar )
+ throws IOException
+ {
+ ExtensionDescriptor extensionDescriptor = null;
+
+ if ( extensionJar.isFile() )
+ {
+ JarFile pluginJar = new JarFile( extensionJar, false );
+ try
+ {
+ ZipEntry pluginDescriptorEntry = pluginJar.getEntry( getExtensionDescriptorLocation() );
+
+ if ( pluginDescriptorEntry != null )
+ {
+ InputStream is = pluginJar.getInputStream( pluginDescriptorEntry );
+
+ extensionDescriptor = build( is );
+ }
+ }
+ finally
+ {
+ pluginJar.close();
+ }
+ }
+ else
+ {
+ File pluginXml = new File( extensionJar, getExtensionDescriptorLocation() );
+
+ if ( pluginXml.canRead() )
+ {
+ InputStream is = new BufferedInputStream( new FileInputStream( pluginXml ) );
+ try
+ {
+ extensionDescriptor = build( is );
+ }
+ finally
+ {
+ IOUtil.close( is );
+ }
+ }
+ }
+
+ return extensionDescriptor;
+ }
+
+ ExtensionDescriptor build( InputStream is )
+ throws IOException
+ {
+ ExtensionDescriptor extensionDescriptor = new ExtensionDescriptor();
+
+ Xpp3Dom dom;
+ try
+ {
+ dom = Xpp3DomBuilder.build( ReaderFactory.newXmlReader( is ) );
+ }
+ catch ( XmlPullParserException e )
+ {
+ throw (IOException) new IOException( e.getMessage() ).initCause( e );
+ }
+ finally
+ {
+ IOUtil.close( is );
+ }
+
+ if ( !"extension".equals( dom.getName() ) )
+ {
+ throw new IOException( "Unexpected root element \"" + dom.getName() + "\", expected \"extension\"" );
+ }
+
+ extensionDescriptor.setExportedPackages( parseStrings( dom.getChild( "exportedPackages" ) ) );
+
+ extensionDescriptor.setExportedArtifacts( parseStrings( dom.getChild( "exportedArtifacts" ) ) );
+
+ return extensionDescriptor;
+ }
+
+ private List<String> parseStrings( Xpp3Dom dom )
+ {
+ List<String> strings = null;
+
+ if ( dom != null )
+ {
+ strings = new ArrayList<String>();
+
+ for ( Xpp3Dom child : dom.getChildren() )
+ {
+ String string = child.getValue();
+ if ( string != null )
+ {
+ string = string.trim();
+ if ( string.length() > 0 )
+ {
+ strings.add( string );
+ }
+ }
+ }
+ }
+
+ return strings;
+ }
+
+}
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/MavenProject.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/MavenProject.java?rev=819540&r1=819539&r2=819540&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/MavenProject.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/MavenProject.java Mon Sep 28 13:56:25 2009
@@ -167,6 +167,8 @@
private ClassRealm classRealm;
+ private ArtifactFilter extensionArtifactFilter;
+
//
public MavenProject()
@@ -1948,7 +1950,9 @@
}
/**
- * Sets the project's class realm.
+ * Sets the project's class realm. <strong>Warning:</strong> This is an internal utility method that is only public
+ * for technical reasons, it is not part of the public API. In particular, this method can be changed or deleted
+ * without prior notice and must not be used by plugins.
*
* @param classRealm The class realm hosting the build extensions of this project, may be {@code null}.
*/
@@ -1959,6 +1963,9 @@
/**
* Gets the project's class realm. This class realm hosts the build extensions of the project.
+ * <strong>Warning:</strong> This is an internal utility method that is only public for technical reasons, it is not
+ * part of the public API. In particular, this method can be changed or deleted without prior notice and must not be
+ * used by plugins.
*
* @return The project's class realm or {@code null}.
*/
@@ -1967,4 +1974,28 @@
return classRealm;
}
+ /**
+ * Sets the artifact filter used to exclude shared extension artifacts from plugin realms. <strong>Warning:</strong>
+ * This is an internal utility method that is only public for technical reasons, it is not part of the public API.
+ * In particular, this method can be changed or deleted without prior notice and must not be used by plugins.
+ *
+ * @param extensionArtifactFilter The artifact filter to apply to plugins, may be {@code null}.
+ */
+ public void setExtensionArtifactFilter( ArtifactFilter extensionArtifactFilter )
+ {
+ this.extensionArtifactFilter = extensionArtifactFilter;
+ }
+
+ /**
+ * Gets the artifact filter used to exclude shared extension artifacts from plugin realms. <strong>Warning:</strong>
+ * This is an internal utility method that is only public for technical reasons, it is not part of the public API.
+ * In particular, this method can be changed or deleted without prior notice and must not be used by plugins.
+ *
+ * @return The artifact filter or {@code null}.
+ */
+ public ArtifactFilter getExtensionArtifactFilter()
+ {
+ return extensionArtifactFilter;
+ }
+
}
Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingHelper.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingHelper.java?rev=819540&r1=819539&r2=819540&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingHelper.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingHelper.java Mon Sep 28 13:56:25 2009
@@ -28,7 +28,6 @@
import org.apache.maven.model.Model;
import org.apache.maven.model.Repository;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
-import org.codehaus.plexus.classworlds.realm.ClassRealm;
/**
* Assists the project builder. <strong>Warning:</strong> This is an internal utility interface that is only public for
@@ -61,10 +60,10 @@
*
* @param model The model to create the project realm for, must not be {@code null}
* @param repositoryRequest The repository request to use for artifact resolution, must not be {@code null}.
- * @return The project realm or {@code null} if the project uses no extensions.
+ * @return The record with the project realm and extension artifact filter, never {@code null}.
* @throws ArtifactResolutionException If any build extension could not be resolved.
*/
- ClassRealm createProjectRealm( Model model, RepositoryRequest repositoryRequest )
+ ProjectRealmCache.CacheRecord createProjectRealm( Model model, RepositoryRequest repositoryRequest )
throws ArtifactResolutionException, PluginVersionResolutionException;
}
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ProjectRealmCache.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ProjectRealmCache.java?rev=819540&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ProjectRealmCache.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ProjectRealmCache.java Mon Sep 28 13:56:25 2009
@@ -0,0 +1,60 @@
+package org.apache.maven.project;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.List;
+
+import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
+import org.codehaus.plexus.classworlds.realm.ClassRealm;
+
+/**
+ * Caches project class realms. <strong>Warning:</strong> This is an internal utility interface that is only public for
+ * technical reasons, it is not part of the public API. In particular, this interface can be changed or deleted without
+ * prior notice.
+ *
+ * @author Igor Fedorenko
+ * @author Benjamin Bentmann
+ */
+public interface ProjectRealmCache
+{
+
+ public static class CacheRecord
+ {
+
+ public final ClassRealm realm;
+
+ public final ArtifactFilter extensionArtifactFilter;
+
+ public CacheRecord( ClassRealm realm, ArtifactFilter extensionArtifactFilter )
+ {
+ this.realm = realm;
+ this.extensionArtifactFilter = extensionArtifactFilter;
+ }
+
+ }
+
+ CacheRecord get( List<? extends ClassRealm> extensionRealms );
+
+ void put( List<? extends ClassRealm> extensionRealms, ClassRealm projectRealm,
+ ArtifactFilter extensionArtifactFilter );
+
+ void flush();
+
+}
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ProjectRealmCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/ProjectRealmCache.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Modified: maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/EmptyProjectBuildingHelper.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/EmptyProjectBuildingHelper.java?rev=819540&r1=819539&r2=819540&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/EmptyProjectBuildingHelper.java (original)
+++ maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/EmptyProjectBuildingHelper.java Mon Sep 28 13:56:25 2009
@@ -28,7 +28,6 @@
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.model.Model;
import org.apache.maven.model.Repository;
-import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.annotations.Component;
/**
@@ -56,10 +55,10 @@
}
}
- public ClassRealm createProjectRealm( Model model, RepositoryRequest repositoryRequest )
+ public ProjectRealmCache.CacheRecord createProjectRealm( Model model, RepositoryRequest repositoryRequest )
throws ArtifactResolutionException
{
- return null;
+ return new ProjectRealmCache.CacheRecord( null, null );
}
}
Added: maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/ExtensionDescriptorBuilderTest.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/ExtensionDescriptorBuilderTest.java?rev=819540&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/ExtensionDescriptorBuilderTest.java (added)
+++ maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/ExtensionDescriptorBuilderTest.java Mon Sep 28 13:56:25 2009
@@ -0,0 +1,101 @@
+package org.apache.maven.project;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests {@link ExtensionDescriptorBuilder}.
+ *
+ * @author Benjamin Bentmann
+ */
+public class ExtensionDescriptorBuilderTest
+ extends TestCase
+{
+
+ private ExtensionDescriptorBuilder builder;
+
+ @Override
+ protected void setUp()
+ throws Exception
+ {
+ super.setUp();
+
+ builder = new ExtensionDescriptorBuilder();
+ }
+
+ @Override
+ protected void tearDown()
+ throws Exception
+ {
+ builder = null;
+
+ super.tearDown();
+ }
+
+ private InputStream toStream( String xml )
+ {
+ try
+ {
+ return new ByteArrayInputStream( xml.getBytes( "UTF-8" ) );
+ }
+ catch ( UnsupportedEncodingException e )
+ {
+ throw new IllegalStateException( e );
+ }
+ }
+
+ public void testEmptyDescriptor()
+ throws Exception
+ {
+ String xml = "<extension></extension>";
+
+ ExtensionDescriptor ed = builder.build( toStream( xml ) );
+
+ assertNotNull( ed );
+ assertNotNull( ed.getExportedPackages() );
+ assertTrue( ed.getExportedPackages().isEmpty() );
+ assertNotNull( ed.getExportedArtifacts() );
+ assertTrue( ed.getExportedArtifacts().isEmpty() );
+ }
+
+ public void testCompleteDescriptor()
+ throws Exception
+ {
+ String xml =
+ "<?xml version='1.0' encoding='UTF-8'?>" + "<extension>" + "<exportedPackages>"
+ + "<exportedPackage>a</exportedPackage>" + "<exportedPackage>b</exportedPackage>"
+ + "<exportedPackage>c</exportedPackage>" + "</exportedPackages>" + "<exportedArtifacts>"
+ + "<exportedArtifact>x</exportedArtifact>" + "<exportedArtifact>y</exportedArtifact>"
+ + "<exportedArtifact> z </exportedArtifact>" + "</exportedArtifacts>" + "</extension>";
+
+ ExtensionDescriptor ed = builder.build( toStream( xml ) );
+
+ assertNotNull( ed );
+ assertEquals( Arrays.asList( "a", "b", "c" ), ed.getExportedPackages() );
+ assertEquals( Arrays.asList( "x", "y", "z" ), ed.getExportedArtifacts() );
+ }
+
+}
Propchange: maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/ExtensionDescriptorBuilderTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/ExtensionDescriptorBuilderTest.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Modified: maven/maven-3/trunk/pom.xml
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/pom.xml?rev=819540&r1=819539&r2=819540&view=diff
==============================================================================
--- maven/maven-3/trunk/pom.xml (original)
+++ maven/maven-3/trunk/pom.xml Mon Sep 28 13:56:25 2009
@@ -38,11 +38,11 @@
<inceptionYear>2001</inceptionYear>
<properties>
- <classWorldsVersion>2.1.0</classWorldsVersion>
+ <classWorldsVersion>2.2.0-SNAPSHOT</classWorldsVersion>
<commonsCliVersion>1.2</commonsCliVersion>
<easyMockVersion>1.2_Java1.3</easyMockVersion>
<junitVersion>3.8.2</junitVersion>
- <plexusVersion>1.2.1</plexusVersion>
+ <plexusVersion>1.3.0-SNAPSHOT</plexusVersion>
<plexusInterpolationVersion>1.11</plexusInterpolationVersion>
<plexusPluginManagerVersion>1.0-alpha-1</plexusPluginManagerVersion>
<plexusUtilsVersion>2.0.0</plexusUtilsVersion>
@@ -158,6 +158,14 @@
</site>
</distributionManagement>
+ <!-- FIXME: Remove once snapshots have been released -->
+ <repositories>
+ <repository>
+ <id>sonatype.public</id>
+ <url>http://repository.sonatype.org/content/groups/public/</url>
+ </repository>
+ </repositories>
+
<!--bootstrap-start-comment-->
<dependencyManagement>
<!--bootstrap-end-comment-->