diff --git a/maven-core/src/main/java/org/apache/maven/classrealm/ArtifactClassRealmConstituent.java b/maven-core/src/main/java/org/apache/maven/classrealm/ArtifactClassRealmConstituent.java new file mode 100644 index 0000000000..5eb1b501a9 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/classrealm/ArtifactClassRealmConstituent.java @@ -0,0 +1,70 @@ +package org.apache.maven.classrealm; + +/* + * 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.File; + +import org.apache.maven.artifact.Artifact; + +/** + * @author Benjamin Bentmann + */ +class ArtifactClassRealmConstituent + implements ClassRealmConstituent +{ + + private final Artifact artifact; + + public ArtifactClassRealmConstituent( Artifact artifact ) + { + this.artifact = artifact; + } + + public String getGroupId() + { + return artifact.getGroupId(); + } + + public String getArtifactId() + { + return artifact.getArtifactId(); + } + + public String getType() + { + return artifact.getType(); + } + + public String getClassifier() + { + return artifact.hasClassifier() ? artifact.getClassifier() : ""; + } + + public String getVersion() + { + return artifact.getBaseVersion(); + } + + public File getFile() + { + return artifact.getFile(); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmConstituent.java b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmConstituent.java new file mode 100644 index 0000000000..742b80fc8f --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmConstituent.java @@ -0,0 +1,74 @@ +package org.apache.maven.classrealm; + +/* + * 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.File; + +/** + * Describes a constituent of a class realm. + * + * @author Benjamin Bentmann + */ +public interface ClassRealmConstituent +{ + + /** + * Gets the group id of the constituent's artifact. + * + * @return The group id, never {@code null}. + */ + String getGroupId(); + + /** + * Gets the artifact id of the constituent's artifact. + * + * @return The artifact id, never {@code null}. + */ + String getArtifactId(); + + /** + * Gets the type of the constituent's artifact. + * + * @return The type, never {@code null}. + */ + String getType(); + + /** + * Gets the classifier of the constituent's artifact. + * + * @return The classifier or an empty string, never {@code null}. + */ + String getClassifier(); + + /** + * Gets the version of the constituent's artifact. + * + * @return The version, never {@code null}. + */ + String getVersion(); + + /** + * Gets the file of the constituent's artifact. + * + * @return The file, never {@code null}. + */ + File getFile(); + +} diff --git a/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java index 20c5f23538..61867a4dbf 100644 --- a/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java +++ b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java @@ -21,6 +21,7 @@ import java.util.List; +import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; import org.codehaus.plexus.classworlds.realm.ClassRealm; @@ -46,17 +47,21 @@ public interface ClassRealmManager * Creates a new class realm for the specified project and its build extensions. * * @param model The model of the project for which to create a realm, must not be {@code null}. + * @param artifacts The artifacts to add to the class realm, may be {@code null}. Unresolved artifacts (i.e. with a + * missing file) will automatically be excluded from the realm. * @return The new project realm, never {@code null}. */ - ClassRealm createProjectRealm( Model model ); + ClassRealm createProjectRealm( Model model, List artifacts ); /** * 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}. + * @param artifacts The artifacts to add to the class realm, may be {@code null}. Unresolved artifacts (i.e. with a + * missing file) will automatically be excluded from the realm. * @return The new extension realm, never {@code null}. */ - ClassRealm createExtensionRealm( Plugin extension ); + ClassRealm createExtensionRealm( Plugin extension, List artifacts ); /** * Creates a new class realm for the specified plugin. @@ -64,8 +69,10 @@ public interface ClassRealmManager * @param plugin The plugin for which to create a realm, must not be {@code null}. * @param parent The parent realm for the new realm, may be {@code null} to use the Maven core realm. * @param imports The packages/types to import from the parent realm, may be {@code null}. + * @param artifacts The artifacts to add to the class realm, may be {@code null}. Unresolved artifacts (i.e. with a + * missing file) will automatically be excluded from the realm. * @return The new plugin realm, never {@code null}. */ - ClassRealm createPluginRealm( Plugin plugin, ClassLoader parent, List imports ); + ClassRealm createPluginRealm( Plugin plugin, ClassLoader parent, List imports, List artifacts ); } diff --git a/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManagerDelegate.java b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManagerDelegate.java index a7340cb775..d882c99ede 100644 --- a/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManagerDelegate.java +++ b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManagerDelegate.java @@ -30,5 +30,7 @@ */ public interface ClassRealmManagerDelegate { - void setupRealm( ClassRealm classRealm ); + + void setupRealm( ClassRealm classRealm, ClassRealmRequest request ); + } diff --git a/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmRequest.java b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmRequest.java new file mode 100644 index 0000000000..2ae3d66e94 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmRequest.java @@ -0,0 +1,65 @@ +package org.apache.maven.classrealm; + +/* + * 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; + +/** + * Describes the requirements for a new class realm. + * + * @author Benjamin Bentmann + */ +public interface ClassRealmRequest +{ + + enum RealmType + { + Project, Extension, Plugin, + } + + /** + * Gets the type of the class realm. + * + * @return The type of the class realm, never {@code null}. + */ + RealmType getType(); + + /** + * Gets the parent class realm (if any). + * + * @return The parent class realm or {@code null} if using the Maven core realm as parent. + */ + ClassLoader getParent(); + + /** + * Gets the packages/types to import from the parent realm + * + * @return The modifiable list of packages/types to import from the parent realm, never {@code null}. + */ + List getImports(); + + /** + * Gets the constituents for the class realm. + * + * @return The modifiable list of constituents for the class realm, never {@code null}. + */ + List getConstituents(); + +} diff --git a/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java b/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java index 84bd1bc237..ac6f31f531 100644 --- a/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java +++ b/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java @@ -19,11 +19,18 @@ * under the License. */ +import java.io.File; +import java.net.MalformedURLException; +import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Random; +import java.util.Set; +import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.ArtifactUtils; +import org.apache.maven.classrealm.ClassRealmRequest.RealmType; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; import org.codehaus.plexus.MutablePlexusContainer; @@ -35,6 +42,7 @@ import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.util.StringUtils; /** * Manages the class realms used by Maven. Warning: This is an internal utility class that is only @@ -63,21 +71,52 @@ private ClassWorld getClassWorld() * Creates a new class realm with the specified parent and imports. * * @param baseRealmId The base id to use for the new realm, must not be {@code null}. + * @param type The type of the class realm, must not be {@code null}. * @param parent The parent realm for the new realm, may be {@code null} to use the Maven core realm. * @param imports The packages/types to import from the parent realm, may be {@code null}. + * @param artifacts The artifacts to add to the realm, may be {@code null}. Unresolved artifacts (i.e. with a + * missing file) will automatically be excluded from the realm. * @return The created class realm, never {@code null}. */ - private ClassRealm createRealm( String baseRealmId, ClassLoader parent, List imports, boolean importXpp3Dom ) + private ClassRealm createRealm( String baseRealmId, RealmType type, ClassLoader parent, List imports, + boolean importXpp3Dom, List artifacts ) { + Set artifactIds = new HashSet(); + + List constituents = new ArrayList(); + + if ( artifacts != null ) + { + for ( Artifact artifact : artifacts ) + { + artifactIds.add( artifact.getId() ); + if ( artifact.getFile() != null ) + { + constituents.add( new ArtifactClassRealmConstituent( artifact ) ); + } + } + } + + if ( imports != null ) + { + imports = new ArrayList( imports ); + } + else + { + imports = new ArrayList(); + } + + ClassRealmRequest request = new DefaultClassRealmRequest( type, parent, imports, constituents ); + + ClassRealm classRealm; + ClassWorld world = getClassWorld(); - String realmId = baseRealmId; - - Random random = new Random(); - synchronized ( world ) { - ClassRealm classRealm; + String realmId = baseRealmId; + + Random random = new Random(); while ( true ) { @@ -97,39 +136,84 @@ private ClassRealm createRealm( String baseRealmId, ClassLoader parent, List artifacts ) { if ( model == null ) { throw new IllegalArgumentException( "model missing" ); } - return createRealm( getKey( model ), null, null, false ); + return createRealm( getKey( model ), RealmType.Project, null, null, false, artifacts ); } - private String getKey( Model model ) + private static String getKey( Model model ) { return "project>" + model.getGroupId() + ":" + model.getArtifactId() + ":" + model.getVersion(); } - public ClassRealm createExtensionRealm( Plugin plugin ) + public ClassRealm createExtensionRealm( Plugin plugin, List artifacts ) { if ( plugin == null ) { throw new IllegalArgumentException( "extension plugin missing" ); } - return createRealm( getKey( plugin, true ), null, null, true ); + return createRealm( getKey( plugin, true ), RealmType.Extension, null, null, true, artifacts ); } - public ClassRealm createPluginRealm( Plugin plugin, ClassLoader parent, List imports ) + public ClassRealm createPluginRealm( Plugin plugin, ClassLoader parent, List imports, + List artifacts ) { if ( plugin == null ) { throw new IllegalArgumentException( "plugin missing" ); } - return createRealm( getKey( plugin, false ), parent, imports, true ); + return createRealm( getKey( plugin, false ), RealmType.Plugin, parent, imports, true, artifacts ); } - private String getKey( Plugin plugin, boolean extension ) + private static String getKey( Plugin plugin, boolean extension ) { String version = ArtifactUtils.toSnapshotVersion( plugin.getVersion() ); return ( extension ? "extension>" : "plugin>" ) + plugin.getGroupId() + ":" + plugin.getArtifactId() + ":" + version; } + private static String getId( ClassRealmConstituent constituent ) + { + return constituent.getGroupId() + ':' + constituent.getArtifactId() + ':' + constituent.getType() + + ( StringUtils.isNotEmpty( constituent.getClassifier() ) ? ':' + constituent.getClassifier() : "" ) + ':' + + constituent.getVersion(); + } + private List getDelegates() { try diff --git a/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmRequest.java b/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmRequest.java new file mode 100644 index 0000000000..e2917af9e5 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmRequest.java @@ -0,0 +1,68 @@ +package org.apache.maven.classrealm; + +/* + * 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; + +/** + * @author Benjamin Bentmann + */ +class DefaultClassRealmRequest + implements ClassRealmRequest +{ + + private final RealmType type; + + private final ClassLoader parent; + + private final List imports; + + private final List constituents; + + public DefaultClassRealmRequest( RealmType type, ClassLoader parent, List imports, + List constituents ) + { + this.type = type; + this.parent = parent; + this.imports = imports; + this.constituents = constituents; + } + + public RealmType getType() + { + return type; + } + + public ClassLoader getParent() + { + return parent; + } + + public List getImports() + { + return imports; + } + + public List getConstituents() + { + return constituents; + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java index 5b54d76d97..c6dbd04de0 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java @@ -27,7 +27,6 @@ import java.io.InputStream; import java.io.PrintStream; import java.io.Reader; -import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; @@ -360,12 +359,7 @@ else if ( filter != null ) List pluginArtifacts = resolvePluginArtifacts( plugin, pluginArtifact, request, dependencyFilter ); - ClassRealm pluginRealm = classRealmManager.createPluginRealm( plugin, parent, imports ); - - if ( logger.isDebugEnabled() ) - { - logger.debug( "Populating plugin realm for " + plugin.getId() ); - } + ClassRealm pluginRealm = classRealmManager.createPluginRealm( plugin, parent, imports, pluginArtifacts ); List exposedPluginArtifacts = new ArrayList(); @@ -373,28 +367,7 @@ else if ( filter != null ) { if ( artifact.getFile() != null ) { - if ( logger.isDebugEnabled() ) - { - logger.debug( " Included: " + artifact.getId() ); - } - exposedPluginArtifacts.add( artifact ); - - try - { - pluginRealm.addURL( artifact.getFile().toURI().toURL() ); - } - catch ( MalformedURLException e ) - { - // Not going to happen - } - } - else - { - if ( logger.isDebugEnabled() ) - { - logger.debug( " Excluded: " + artifact.getId() ); - } } } diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java index 7279fda2f4..b52dcf114c 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java @@ -20,7 +20,6 @@ */ import java.io.IOException; -import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -229,39 +228,7 @@ public synchronized ProjectRealmCache.CacheRecord createProjectRealm( MavenProje } else { - extensionRealm = classRealmManager.createExtensionRealm( plugin ); - - if ( logger.isDebugEnabled() ) - { - logger.debug( "Populating extension realm for " + plugin.getId() ); - } - - 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() ); - } - } - } + extensionRealm = classRealmManager.createExtensionRealm( plugin, artifacts ); try { @@ -323,29 +290,7 @@ public synchronized ProjectRealmCache.CacheRecord createProjectRealm( MavenProje if ( record == null ) { - 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: " + publicArtifact.getId() ); - } - - try - { - projectRealm.addURL( publicArtifact.getFile().toURI().toURL() ); - } - catch ( MalformedURLException e ) - { - // can't happen - } - } + projectRealm = classRealmManager.createProjectRealm( model, publicArtifacts ); Set exclusions = new LinkedHashSet();