You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ah...@apache.org on 2015/04/01 02:23:48 UTC
[06/50] [abbrv] maven git commit: MNG-5771 user-defined core
extensions
MNG-5771 user-defined core extensions
read ${maven.projectBasedir}/.mvn/extensions.xml and create core
extensions realms during maven runtime bootstrap. this required
short-lived bootstrap plexus container to resolve extensions.
individual extensions realms are wired to maven.ext realm according
to META-INF/maven/extension.xml exported packages specification
Signed-off-by: Igor Fedorenko <if...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/maven/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven/commit/6efacdb3
Tree: http://git-wip-us.apache.org/repos/asf/maven/tree/6efacdb3
Diff: http://git-wip-us.apache.org/repos/asf/maven/diff/6efacdb3
Branch: refs/heads/slf4j-log4j2
Commit: 6efacdb3fc5e8369fa3586c0603184dc785303da
Parents: e2a0792
Author: Igor Fedorenko <if...@apache.org>
Authored: Sat Feb 14 09:59:02 2015 -0500
Committer: Igor Fedorenko <if...@apache.org>
Committed: Fri Feb 20 14:05:54 2015 -0500
----------------------------------------------------------------------
.../maven/DefaultArtifactFilterManager.java | 26 +-
.../classrealm/DefaultClassRealmManager.java | 45 +---
.../maven/extension/internal/CoreExports.java | 75 ++++++
.../extension/internal/CoreExportsProvider.java | 53 ++++
.../extension/internal/CoreExtensionEntry.java | 141 +++++++++++
.../extension/internal/DefaultCoreExports.java | 97 --------
.../DefaultPluginDependenciesResolver.java | 33 ++-
maven-embedder/pom.xml | 14 ++
.../java/org/apache/maven/cli/MavenCli.java | 246 ++++++++++++++++---
.../internal/BootstrapCoreExtensionManager.java | 143 +++++++++++
maven-embedder/src/main/mdo/core-extensions.mdo | 74 ++++++
11 files changed, 765 insertions(+), 182 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven/blob/6efacdb3/maven-core/src/main/java/org/apache/maven/DefaultArtifactFilterManager.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/DefaultArtifactFilterManager.java b/maven-core/src/main/java/org/apache/maven/DefaultArtifactFilterManager.java
index 80bfd62..46f8af0 100644
--- a/maven-core/src/main/java/org/apache/maven/DefaultArtifactFilterManager.java
+++ b/maven-core/src/main/java/org/apache/maven/DefaultArtifactFilterManager.java
@@ -29,9 +29,7 @@ import javax.inject.Singleton;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ExclusionSetFilter;
-import org.apache.maven.extension.internal.DefaultCoreExports;
-
-import com.google.common.collect.ImmutableSet;
+import org.apache.maven.extension.internal.CoreExportsProvider;
/**
* @author Jason van Zyl
@@ -46,16 +44,24 @@ public class DefaultArtifactFilterManager
// this is a live injected collection
protected final List<ArtifactFilterManagerDelegate> delegates;
- protected final Set<String> coreArtifacts;
+ protected Set<String> excludedArtifacts;
- protected final Set<String> excludedArtifacts;
+ private final Set<String> coreArtifacts;
@Inject
- public DefaultArtifactFilterManager( List<ArtifactFilterManagerDelegate> delegates, DefaultCoreExports extensions )
+ public DefaultArtifactFilterManager( List<ArtifactFilterManagerDelegate> delegates, CoreExportsProvider coreExports )
{
this.delegates = delegates;
- this.coreArtifacts = ImmutableSet.copyOf( extensions.getExportedArtifacts() );
- this.excludedArtifacts = new LinkedHashSet<String>( extensions.getExportedArtifacts() );
+ this.coreArtifacts = coreExports.get().getExportedArtifacts();
+ }
+
+ private synchronized Set<String> getExcludedArtifacts()
+ {
+ if ( excludedArtifacts == null )
+ {
+ excludedArtifacts = new LinkedHashSet<String>( coreArtifacts );
+ }
+ return excludedArtifacts;
}
/**
@@ -65,7 +71,7 @@ public class DefaultArtifactFilterManager
*/
public ArtifactFilter getArtifactFilter()
{
- Set<String> excludes = new LinkedHashSet<String>( excludedArtifacts );
+ Set<String> excludes = new LinkedHashSet<String>( getExcludedArtifacts() );
for ( ArtifactFilterManagerDelegate delegate : delegates )
{
@@ -87,7 +93,7 @@ public class DefaultArtifactFilterManager
public void excludeArtifact( String artifactId )
{
- excludedArtifacts.add( artifactId );
+ getExcludedArtifacts().add( artifactId );
}
public Set<String> getCoreArtifactExcludes()
http://git-wip-us.apache.org/repos/asf/maven/blob/6efacdb3/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java
----------------------------------------------------------------------
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 206fa58..ab9607a 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
@@ -23,7 +23,6 @@ import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -37,7 +36,7 @@ import javax.inject.Singleton;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.classrealm.ClassRealmRequest.RealmType;
-import org.apache.maven.extension.internal.DefaultCoreExports;
+import org.apache.maven.extension.internal.CoreExportsProvider;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.codehaus.plexus.MutablePlexusContainer;
@@ -49,8 +48,6 @@ import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.StringUtils;
import org.eclipse.aether.artifact.Artifact;
-import com.google.common.collect.ImmutableMap;
-
/**
* Manages the class realms used by Maven. <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
@@ -63,6 +60,7 @@ import com.google.common.collect.ImmutableMap;
public class DefaultClassRealmManager
implements ClassRealmManager
{
+ public static final String API_REALMID = "maven.api";
/**
* During normal command line build, ClassWorld is loaded by jvm system classloader, which only includes
@@ -83,25 +81,22 @@ public class DefaultClassRealmManager
// this is a live injected collection
private final List<ClassRealmManagerDelegate> delegates;
- private final Map<String, ClassLoader> coreImports;
-
- private ClassRealm mavenRealm;
+ private final ClassRealm mavenApiRealm;
@Inject
public DefaultClassRealmManager( Logger logger, PlexusContainer container,
- List<ClassRealmManagerDelegate> delegates, DefaultCoreExports coreExtensions )
+ List<ClassRealmManagerDelegate> delegates, CoreExportsProvider exports )
{
this.logger = logger;
this.world = ( (MutablePlexusContainer) container ).getClassWorld();
this.containerRealm = container.getContainerRealm();
this.delegates = delegates;
- Map<String, ClassLoader> coreImports = new HashMap<String, ClassLoader>();
- for ( String corePackage : coreExtensions.getExportedPackages() )
- {
- coreImports.put( corePackage, containerRealm );
- }
- this.coreImports = ImmutableMap.copyOf( coreImports );
+ Map<String, ClassLoader> foreignImports = exports.get().getExportedPackages();
+
+ this.mavenApiRealm =
+ createRealm( API_REALMID, RealmType.Core, null /* parent */, null /* parentImports */,
+ foreignImports, null /* artifacts */ );
}
private ClassRealm newRealm( String id )
@@ -133,27 +128,9 @@ public class DefaultClassRealmManager
}
}
- public synchronized ClassRealm getMavenApiRealm()
+ public ClassRealm getMavenApiRealm()
{
- if ( mavenRealm == null )
- {
- mavenRealm = newRealm( "maven.api" );
-
- List<ClassRealmConstituent> constituents = new ArrayList<ClassRealmConstituent>();
-
- List<String> parentImports = new ArrayList<String>();
-
- Map<String, ClassLoader> foreignImports = new HashMap<String, ClassLoader>( coreImports );
-
- callDelegates( mavenRealm, RealmType.Core, mavenRealm.getParentClassLoader(), parentImports,
- foreignImports, constituents );
-
- wireRealm( mavenRealm, parentImports, foreignImports );
-
- populateRealm( mavenRealm, constituents );
- }
-
- return mavenRealm;
+ return mavenApiRealm;
}
/**
http://git-wip-us.apache.org/repos/asf/maven/blob/6efacdb3/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExports.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExports.java b/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExports.java
new file mode 100644
index 0000000..f1fa9e3
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExports.java
@@ -0,0 +1,75 @@
+package org.apache.maven.extension.internal;
+
+/*
+ * 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.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.codehaus.plexus.classworlds.realm.ClassRealm;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Provides information about artifacts (identified by groupId:artifactId string key) and classpath elements exported by
+ * Maven core itself and loaded Maven core extensions.
+ *
+ * @since 3.2.6
+ */
+public class CoreExports
+{
+ private final Set<String> artifacts;
+
+ private final Map<String, ClassLoader> packages;
+
+ public CoreExports( CoreExtensionEntry entry )
+ {
+ this( entry.getClassRealm(), entry.getExportedArtifacts(), entry.getExportedPackages() );
+ }
+
+ public CoreExports( ClassRealm realm, Set<String> exportedArtifacts, Set<String> exportedPackages )
+ {
+ Map<String, ClassLoader> packages = new LinkedHashMap<String, ClassLoader>();
+ for ( String pkg : exportedPackages )
+ {
+ packages.put( pkg, realm );
+ }
+ this.artifacts = ImmutableSet.copyOf( exportedArtifacts );
+ this.packages = ImmutableMap.copyOf( packages );
+ }
+
+ /**
+ * Returns artifacts exported by Maven core and core extensions. Artifacts are identified by their
+ * groupId:artifactId string key.
+ */
+ public Set<String> getExportedArtifacts()
+ {
+ return artifacts;
+ }
+
+ /**
+ * Returns packages exported by Maven core and core extensions.
+ */
+ public Map<String, ClassLoader> getExportedPackages()
+ {
+ return packages;
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven/blob/6efacdb3/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExportsProvider.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExportsProvider.java b/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExportsProvider.java
new file mode 100644
index 0000000..e7e4534
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExportsProvider.java
@@ -0,0 +1,53 @@
+package org.apache.maven.extension.internal;
+
+/*
+ * 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 javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.codehaus.plexus.PlexusContainer;
+import org.eclipse.sisu.Nullable;
+
+@Named
+@Singleton
+public class CoreExportsProvider
+{
+
+ private final CoreExports exports;
+
+ @Inject
+ public CoreExportsProvider( PlexusContainer container, @Nullable CoreExports exports )
+ {
+ if ( exports == null )
+ {
+ this.exports = new CoreExports( CoreExtensionEntry.discoverFrom( container.getContainerRealm() ) );
+ }
+ else
+ {
+ this.exports = exports;
+ }
+ }
+
+ public CoreExports get()
+ {
+ return exports;
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven/blob/6efacdb3/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExtensionEntry.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExtensionEntry.java b/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExtensionEntry.java
new file mode 100644
index 0000000..d74c390
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExtensionEntry.java
@@ -0,0 +1,141 @@
+package org.apache.maven.extension.internal;
+
+/*
+ * 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 java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.maven.project.ExtensionDescriptor;
+import org.apache.maven.project.ExtensionDescriptorBuilder;
+import org.codehaus.plexus.classworlds.realm.ClassRealm;
+import org.codehaus.plexus.util.IOUtil;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Provides information about artifacts (identified by groupId:artifactId string key) and classpath elements exported by
+ * Maven core itself or a Maven core extension.
+ *
+ * @since 3.2.6
+ */
+public class CoreExtensionEntry
+{
+ private final ClassRealm realm;
+
+ private final Set<String> artifacts;
+
+ private final Set<String> packages;
+
+ public CoreExtensionEntry( ClassRealm realm, Collection<String> artifacts, Collection<String> packages )
+ {
+ this.realm = realm;
+ this.artifacts = ImmutableSet.copyOf( artifacts );
+ this.packages = ImmutableSet.copyOf( packages );
+ }
+
+ /**
+ * Returns ClassLoader used to load extension classes.
+ */
+ public ClassRealm getClassRealm()
+ {
+ return realm;
+ }
+
+ /**
+ * Returns artifacts exported by the extension, identified by groupId:artifactId string key.
+ */
+ public Set<String> getExportedArtifacts()
+ {
+ return artifacts;
+ }
+
+ /**
+ * Returns classpath elements exported by the extension.
+ */
+ public Set<String> getExportedPackages()
+ {
+ return packages;
+ }
+
+ private static final ExtensionDescriptorBuilder builder = new ExtensionDescriptorBuilder();
+
+ public static CoreExtensionEntry discoverFrom( ClassRealm loader )
+ {
+ Set<String> artifacts = new LinkedHashSet<String>();
+ Set<String> packages = new LinkedHashSet<String>();
+
+ try
+ {
+ Enumeration<URL> urls = loader.getResources( builder.getExtensionDescriptorLocation() );
+ while ( urls.hasMoreElements() )
+ {
+ InputStream is = urls.nextElement().openStream();
+ try
+ {
+ ExtensionDescriptor descriptor = builder.build( is );
+ artifacts.addAll( descriptor.getExportedArtifacts() );
+ packages.addAll( descriptor.getExportedPackages() );
+ }
+ finally
+ {
+ IOUtil.close( is );
+ }
+ }
+ }
+ catch ( IOException ignored )
+ {
+ // exports descriptors are entirely optional
+ }
+
+ return new CoreExtensionEntry( loader, artifacts, packages );
+ }
+
+ public static CoreExtensionEntry discoverFrom( ClassRealm loader, Collection<File> classpath )
+ {
+ Set<String> artifacts = new LinkedHashSet<String>();
+ Set<String> packages = new LinkedHashSet<String>();
+
+ try
+ {
+ for ( File entry : classpath )
+ {
+ ExtensionDescriptor descriptor = builder.build( entry );
+ if ( descriptor != null )
+ {
+ artifacts.addAll( descriptor.getExportedArtifacts() );
+ packages.addAll( descriptor.getExportedPackages() );
+ }
+ }
+ }
+ catch ( IOException ignored )
+ {
+ // exports descriptors are entirely optional
+ }
+
+ return new CoreExtensionEntry( loader, artifacts, packages );
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven/blob/6efacdb3/maven-core/src/main/java/org/apache/maven/extension/internal/DefaultCoreExports.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/extension/internal/DefaultCoreExports.java b/maven-core/src/main/java/org/apache/maven/extension/internal/DefaultCoreExports.java
deleted file mode 100644
index c4253ee..0000000
--- a/maven-core/src/main/java/org/apache/maven/extension/internal/DefaultCoreExports.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.apache.maven.extension.internal;
-
-/*
- * 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.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Enumeration;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-import org.apache.maven.project.ExtensionDescriptor;
-import org.apache.maven.project.ExtensionDescriptorBuilder;
-import org.codehaus.plexus.PlexusContainer;
-import org.codehaus.plexus.util.IOUtil;
-
-import com.google.common.collect.ImmutableSet;
-
-/**
- * @since 3.2.6
- */
-@Named
-@Singleton
-public class DefaultCoreExports
-{
- private static final ExtensionDescriptorBuilder builder = new ExtensionDescriptorBuilder();
-
- private final Set<String> artifacts;
-
- private final Set<String> packages;
-
- @Inject
- public DefaultCoreExports( PlexusContainer container )
- throws IOException
- {
- Set<String> artifacts = new LinkedHashSet<String>();
- Set<String> packages = new LinkedHashSet<String>();
-
- Enumeration<URL> extensions =
- container.getContainerRealm().getResources( builder.getExtensionDescriptorLocation() );
- while ( extensions.hasMoreElements() )
- {
- InputStream is = extensions.nextElement().openStream();
- try
- {
- ExtensionDescriptor descriptor = builder.build( is );
-
- artifacts.addAll( descriptor.getExportedArtifacts() );
- packages.addAll( descriptor.getExportedPackages() );
- }
- finally
- {
- IOUtil.close( is );
- }
- }
- this.artifacts = ImmutableSet.copyOf( artifacts );
- this.packages = ImmutableSet.copyOf( packages );
- }
-
- /**
- * Returns artifacts exported by Maven core and core extensions. Artifacts are identified by their
- * groupId:artifactId.
- */
- public Set<String> getExportedArtifacts()
- {
- return artifacts;
- }
-
- /**
- * Returns packages exported by Maven core and core extensions.
- */
- public Set<String> getExportedPackages()
- {
- return packages;
- }
-}
http://git-wip-us.apache.org/repos/asf/maven/blob/6efacdb3/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
index 5a0edf5..885c8ec 100644
--- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
+++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
@@ -136,10 +136,32 @@ public class DefaultPluginDependenciesResolver
return pluginArtifact;
}
+ /**
+ * @since 3.2.6
+ */
+ public DependencyNode resolveCoreExtension( Plugin plugin, DependencyFilter dependencyFilter,
+ List<RemoteRepository> repositories, RepositorySystemSession session )
+ throws PluginResolutionException
+ {
+ return resolveInternal( plugin, null /* pluginArtifact */, dependencyFilter, null /* transformer */,
+ repositories, session );
+ }
+
public DependencyNode resolve( Plugin plugin, Artifact pluginArtifact, DependencyFilter dependencyFilter,
List<RemoteRepository> repositories, RepositorySystemSession session )
throws PluginResolutionException
{
+ DependencyFilter resolutionFilter =
+ new ExclusionsDependencyFilter( artifactFilterManager.getCoreArtifactExcludes() );
+ resolutionFilter = AndDependencyFilter.newInstance( resolutionFilter, dependencyFilter );
+ return resolveInternal( plugin, pluginArtifact, resolutionFilter, new PlexusUtilsInjector(), repositories, session );
+ }
+
+ private DependencyNode resolveInternal( Plugin plugin, Artifact pluginArtifact, DependencyFilter dependencyFilter,
+ DependencyGraphTransformer transformer,
+ List<RemoteRepository> repositories, RepositorySystemSession session )
+ throws PluginResolutionException
+ {
RequestTrace trace = RequestTrace.newChild( null, plugin );
if ( pluginArtifact == null )
@@ -148,11 +170,7 @@ public class DefaultPluginDependenciesResolver
}
DependencyFilter collectionFilter = new ScopeDependencyFilter( "provided", "test" );
-
- DependencyFilter resolutionFilter =
- new ExclusionsDependencyFilter( artifactFilterManager.getCoreArtifactExcludes() );
- resolutionFilter = AndDependencyFilter.newInstance( resolutionFilter, dependencyFilter );
- resolutionFilter = new AndDependencyFilter( collectionFilter, resolutionFilter );
+ DependencyFilter resolutionFilter = AndDependencyFilter.newInstance( collectionFilter, dependencyFilter );
DependencyNode node;
@@ -161,9 +179,8 @@ public class DefaultPluginDependenciesResolver
DependencySelector selector =
AndDependencySelector.newInstance( session.getDependencySelector(), new WagonExcluder() );
- DependencyGraphTransformer transformer =
- ChainedDependencyGraphTransformer.newInstance( session.getDependencyGraphTransformer(),
- new PlexusUtilsInjector() );
+ transformer =
+ ChainedDependencyGraphTransformer.newInstance( session.getDependencyGraphTransformer(), transformer );
DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession( session );
pluginSession.setDependencySelector( selector );
http://git-wip-us.apache.org/repos/asf/maven/blob/6efacdb3/maven-embedder/pom.xml
----------------------------------------------------------------------
diff --git a/maven-embedder/pom.xml b/maven-embedder/pom.xml
index cd3f583..2dc5fde 100644
--- a/maven-embedder/pom.xml
+++ b/maven-embedder/pom.xml
@@ -122,9 +122,23 @@
</pluginManagement>
<plugins>
<plugin>
+ <groupId>org.eclipse.sisu</groupId>
+ <artifactId>sisu-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-metadata</artifactId>
</plugin>
+ <plugin>
+ <groupId>org.codehaus.modello</groupId>
+ <artifactId>modello-maven-plugin</artifactId>
+ <configuration>
+ <version>1.0.0</version>
+ <models>
+ <model>src/main/mdo/core-extensions.mdo</model>
+ </models>
+ </configuration>
+ </plugin>
</plugins>
</build>
</project>
http://git-wip-us.apache.org/repos/asf/maven/blob/6efacdb3/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
----------------------------------------------------------------------
diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
index 3878dae..1c2ffc0 100644
--- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
+++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
@@ -19,11 +19,14 @@ package org.apache.maven.cli;
* under the License.
*/
+import java.io.BufferedInputStream;
import java.io.Console;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
@@ -47,6 +50,9 @@ import org.apache.maven.building.Problem;
import org.apache.maven.building.Source;
import org.apache.maven.cli.event.DefaultEventSpyContext;
import org.apache.maven.cli.event.ExecutionEventLogger;
+import org.apache.maven.cli.internal.BootstrapCoreExtensionManager;
+import org.apache.maven.cli.internal.extension.model.CoreExtension;
+import org.apache.maven.cli.internal.extension.model.io.xpp3.CoreExtensionsXpp3Reader;
import org.apache.maven.cli.logging.Slf4jConfiguration;
import org.apache.maven.cli.logging.Slf4jConfigurationFactory;
import org.apache.maven.cli.logging.Slf4jLoggerManager;
@@ -64,6 +70,8 @@ import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionRequestPopulationException;
import org.apache.maven.execution.MavenExecutionRequestPopulator;
import org.apache.maven.execution.MavenExecutionResult;
+import org.apache.maven.extension.internal.CoreExports;
+import org.apache.maven.extension.internal.CoreExtensionEntry;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.model.building.ModelProcessor;
import org.apache.maven.project.MavenProject;
@@ -87,7 +95,9 @@ import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.logging.LoggerManager;
+import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.eclipse.aether.transfer.TransferListener;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
@@ -134,6 +144,8 @@ public class MavenCli
private static final String EXT_CLASS_PATH = "maven.ext.class.path";
+ private static final String EXTENSIONS_FILENAME = ".mvn/extensions.xml";
+
private ClassWorld classWorld;
private LoggerManager plexusLoggerManager;
@@ -485,21 +497,44 @@ public class MavenCli
cliRequest.classWorld = new ClassWorld( "plexus.core", Thread.currentThread().getContextClassLoader() );
}
- DefaultPlexusContainer container;
+ ClassRealm coreRealm = cliRequest.classWorld.getClassRealm( "plexus.core" );
+ if ( coreRealm == null )
+ {
+ coreRealm = cliRequest.classWorld.getRealms().iterator().next();
+ }
+
+ List<File> extClassPath = parseExtClasspath( cliRequest );
+
+ CoreExtensionEntry coreEntry = CoreExtensionEntry.discoverFrom( coreRealm );
+ List<CoreExtensionEntry> extensions =
+ loadCoreExtensions( cliRequest, coreRealm, coreEntry.getExportedArtifacts() );
+
+ ClassRealm containerRealm = setupContainerRealm( cliRequest.classWorld, coreRealm, extClassPath, extensions );
ContainerConfiguration cc = new DefaultContainerConfiguration()
.setClassWorld( cliRequest.classWorld )
- .setRealm( setupContainerRealm( cliRequest ) )
+ .setRealm( containerRealm )
.setClassPathScanning( PlexusConstants.SCANNING_INDEX )
.setAutoWiring( true )
.setName( "maven" );
- container = new DefaultPlexusContainer( cc, new AbstractModule()
+ Set<String> exportedArtifacts = new HashSet<String>( coreEntry.getExportedArtifacts() );
+ Set<String> exportedPackages = new HashSet<String>( coreEntry.getExportedPackages() );
+ for ( CoreExtensionEntry extension : extensions )
+ {
+ exportedArtifacts.addAll( extension.getExportedArtifacts() );
+ exportedPackages.addAll( extension.getExportedPackages() );
+ }
+
+ final CoreExports exports = new CoreExports( containerRealm, exportedArtifacts, exportedPackages );
+
+ DefaultPlexusContainer container = new DefaultPlexusContainer( cc, new AbstractModule()
{
@Override
protected void configure()
{
bind( ILoggerFactory.class ).toInstance( slf4jLoggerFactory );
+ bind( CoreExports.class ).toInstance( exports );
}
} );
@@ -508,6 +543,11 @@ public class MavenCli
container.setLoggerManager( plexusLoggerManager );
+ for ( CoreExtensionEntry extension : extensions )
+ {
+ container.discoverComponents( extension.getClassRealm() );
+ }
+
customizeContainer( container );
container.getLoggerManager().setThresholds( cliRequest.request.getLoggingLevel() );
@@ -543,49 +583,170 @@ public class MavenCli
return container;
}
- private ClassRealm setupContainerRealm( CliRequest cliRequest )
- throws Exception
+ private List<CoreExtensionEntry> loadCoreExtensions( CliRequest cliRequest, ClassRealm containerRealm,
+ Set<String> providedArtifacts )
{
- ClassRealm containerRealm = null;
+ if ( cliRequest.projectBaseDirectory == null )
+ {
+ return Collections.emptyList();
+ }
- String extClassPath = cliRequest.userProperties.getProperty( EXT_CLASS_PATH );
- if ( extClassPath == null )
+ File extensionsFile = new File( cliRequest.projectBaseDirectory, EXTENSIONS_FILENAME );
+ if ( !extensionsFile.isFile() )
{
- extClassPath = cliRequest.systemProperties.getProperty( EXT_CLASS_PATH );
+ return Collections.emptyList();
}
- if ( StringUtils.isNotEmpty( extClassPath ) )
+ try
{
- String[] jars = StringUtils.split( extClassPath, File.pathSeparator );
+ List<CoreExtension> extensions = readCoreExtensionsDescriptor( extensionsFile );
+ if ( extensions.isEmpty() )
+ {
+ return Collections.emptyList();
+ }
+
+ ContainerConfiguration cc = new DefaultContainerConfiguration() //
+ .setClassWorld( cliRequest.classWorld ) //
+ .setRealm( containerRealm ) //
+ .setClassPathScanning( PlexusConstants.SCANNING_INDEX ) //
+ .setAutoWiring( true ) //
+ .setName( "maven" );
- if ( jars.length > 0 )
+ DefaultPlexusContainer container = new DefaultPlexusContainer( cc, new AbstractModule()
{
- ClassRealm coreRealm = cliRequest.classWorld.getClassRealm( "plexus.core" );
- if ( coreRealm == null )
+ @Override
+ protected void configure()
{
- coreRealm = cliRequest.classWorld.getRealms().iterator().next();
+ bind( ILoggerFactory.class ).toInstance( slf4jLoggerFactory );
}
+ } );
- ClassRealm extRealm = cliRequest.classWorld.newRealm( "maven.ext", null );
+ try
+ {
+ container.setLookupRealm( null );
- slf4jLogger.debug( "Populating class realm " + extRealm.getId() );
+ container.setLoggerManager( plexusLoggerManager );
- for ( String jar : jars )
- {
- File file = resolveFile( new File( jar ), cliRequest.workingDirectory );
+ container.getLoggerManager().setThresholds( cliRequest.request.getLoggingLevel() );
+
+ Thread.currentThread().setContextClassLoader( container.getContainerRealm() );
- slf4jLogger.debug( " Included " + file );
+ executionRequestPopulator = container.lookup( MavenExecutionRequestPopulator.class );
+ settingsBuilder = container.lookup( SettingsBuilder.class );
- extRealm.addURL( file.toURI().toURL() );
+ MavenExecutionRequest request = DefaultMavenExecutionRequest.copy( cliRequest.request );
+ settings( cliRequest, request );
+ request = populateRequest( cliRequest, request );
+ request = executionRequestPopulator.populateDefaults( request );
+
+ BootstrapCoreExtensionManager resolver = container.lookup( BootstrapCoreExtensionManager.class );
+ return resolver.loadCoreExtensions( request, providedArtifacts, extensions );
+ }
+ finally
+ {
+ executionRequestPopulator = null;
+ settingsBuilder = null;
+ container.dispose();
+ }
+ }
+ catch ( RuntimeException e )
+ {
+ // runtime exceptions are most likely bugs in maven, let them bubble up to the user
+ throw e;
+ }
+ catch ( Exception e )
+ {
+ slf4jLogger.warn( "Failed to read extensions descriptor " + extensionsFile + ": " + e.getMessage() );
+ }
+ return Collections.emptyList();
+ }
+
+ private List<CoreExtension> readCoreExtensionsDescriptor( File extensionsFile )
+ throws IOException, XmlPullParserException
+ {
+ CoreExtensionsXpp3Reader parser = new CoreExtensionsXpp3Reader();
+ InputStream is = null;
+ try
+ {
+ is = new BufferedInputStream( new FileInputStream( extensionsFile ) );
+ return parser.read( is ).getExtensions();
+ }
+ finally
+ {
+ IOUtil.close( is );
+ }
+ }
+
+ private ClassRealm setupContainerRealm( ClassWorld classWorld, ClassRealm coreRealm, List<File> extClassPath,
+ List<CoreExtensionEntry> extensions )
+ throws Exception
+ {
+ if ( !extClassPath.isEmpty() || !extensions.isEmpty() )
+ {
+ ClassRealm extRealm = classWorld.newRealm( "maven.ext", null );
+
+ extRealm.setParentRealm( coreRealm );
+
+ slf4jLogger.debug( "Populating class realm " + extRealm.getId() );
+
+ for ( File file : extClassPath )
+ {
+ slf4jLogger.debug( " Included " + file );
+
+ extRealm.addURL( file.toURI().toURL() );
+ }
+
+ for ( CoreExtensionEntry entry : reverse( extensions ) )
+ {
+ Set<String> exportedPackages = entry.getExportedPackages();
+ ClassRealm realm = entry.getClassRealm();
+ for ( String exportedPackage : exportedPackages )
+ {
+ extRealm.importFrom( realm, exportedPackage );
}
+ if ( exportedPackages.isEmpty() )
+ {
+ // sisu uses realm imports to establish component visibility
+ extRealm.importFrom( realm, realm.getId() );
+ }
+ }
+
+ return extRealm;
+ }
+
+ return coreRealm;
+ }
- extRealm.setParentRealm( coreRealm );
+ private static <T> List<T> reverse( List<T> list )
+ {
+ List<T> copy = new ArrayList<T>( list );
+ Collections.reverse( copy );
+ return copy;
+ }
- containerRealm = extRealm;
+ private List<File> parseExtClasspath( CliRequest cliRequest )
+ {
+ String extClassPath = cliRequest.userProperties.getProperty( EXT_CLASS_PATH );
+ if ( extClassPath == null )
+ {
+ extClassPath = cliRequest.systemProperties.getProperty( EXT_CLASS_PATH );
+ }
+
+ List<File> jars = new ArrayList<File>();
+
+ if ( StringUtils.isNotEmpty( extClassPath ) )
+ {
+ for ( String jar : StringUtils.split( extClassPath, File.pathSeparator ) )
+ {
+ File file = resolveFile( new File( jar ), cliRequest.workingDirectory );
+
+ slf4jLogger.debug( " Included " + file );
+
+ jars.add( file );
}
}
- return containerRealm;
+ return jars;
}
//
@@ -814,6 +975,12 @@ public class MavenCli
private void settings( CliRequest cliRequest )
throws Exception
{
+ settings( cliRequest, cliRequest.request );
+ }
+
+ private void settings( CliRequest cliRequest, MavenExecutionRequest request )
+ throws Exception
+ {
File userSettingsFile;
if ( cliRequest.commandLine.hasOption( CLIManager.ALTERNATE_USER_SETTINGS ) )
@@ -851,8 +1018,8 @@ public class MavenCli
globalSettingsFile = DEFAULT_GLOBAL_SETTINGS_FILE;
}
- cliRequest.request.setGlobalSettingsFile( globalSettingsFile );
- cliRequest.request.setUserSettingsFile( userSettingsFile );
+ request.setGlobalSettingsFile( globalSettingsFile );
+ request.setUserSettingsFile( userSettingsFile );
SettingsBuildingRequest settingsRequest = new DefaultSettingsBuildingRequest();
settingsRequest.setGlobalSettingsFile( globalSettingsFile );
@@ -860,7 +1027,10 @@ public class MavenCli
settingsRequest.setSystemProperties( cliRequest.systemProperties );
settingsRequest.setUserProperties( cliRequest.userProperties );
- eventSpyDispatcher.onEvent( settingsRequest );
+ if ( eventSpyDispatcher != null )
+ {
+ eventSpyDispatcher.onEvent( settingsRequest );
+ }
slf4jLogger.debug( "Reading global settings from "
+ getLocation( settingsRequest.getGlobalSettingsSource(),
@@ -870,9 +1040,12 @@ public class MavenCli
SettingsBuildingResult settingsResult = settingsBuilder.build( settingsRequest );
- eventSpyDispatcher.onEvent( settingsResult );
+ if ( eventSpyDispatcher != null )
+ {
+ eventSpyDispatcher.onEvent( settingsResult );
+ }
- executionRequestPopulator.populateFromSettings( cliRequest.request, settingsResult.getEffectiveSettings() );
+ executionRequestPopulator.populateFromSettings( request, settingsResult.getEffectiveSettings() );
if ( !settingsResult.getProblems().isEmpty() && slf4jLogger.isWarnEnabled() )
{
@@ -982,7 +1155,11 @@ public class MavenCli
private MavenExecutionRequest populateRequest( CliRequest cliRequest )
{
- MavenExecutionRequest request = cliRequest.request;
+ return populateRequest( cliRequest, cliRequest.request );
+ }
+
+ private MavenExecutionRequest populateRequest( CliRequest cliRequest, MavenExecutionRequest request )
+ {
CommandLine commandLine = cliRequest.commandLine;
String workingDirectory = cliRequest.workingDirectory;
boolean quiet = cliRequest.quiet;
@@ -1127,7 +1304,10 @@ public class MavenCli
}
ExecutionListener executionListener = new ExecutionEventLogger();
- executionListener = eventSpyDispatcher.chainListener( executionListener );
+ if ( eventSpyDispatcher != null )
+ {
+ executionListener = eventSpyDispatcher.chainListener( executionListener );
+ }
String alternatePomFile = null;
if ( commandLine.hasOption( CLIManager.ALTERNATE_POM_FILE ) )
@@ -1172,7 +1352,7 @@ public class MavenCli
request.setPom( pom );
}
- else
+ else if ( modelProcessor != null )
{
File pom = modelProcessor.locatePom( baseDirectory );
http://git-wip-us.apache.org/repos/asf/maven/blob/6efacdb3/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java
----------------------------------------------------------------------
diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java
new file mode 100644
index 0000000..a431bde
--- /dev/null
+++ b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java
@@ -0,0 +1,143 @@
+package org.apache.maven.cli.internal;
+
+/*
+ * 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 java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.apache.maven.RepositoryUtils;
+import org.apache.maven.cli.internal.extension.model.CoreExtension;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.extension.internal.CoreExtensionEntry;
+import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.plugin.PluginResolutionException;
+import org.apache.maven.plugin.internal.DefaultPluginDependenciesResolver;
+import org.codehaus.plexus.DefaultPlexusContainer;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.classworlds.ClassWorld;
+import org.codehaus.plexus.classworlds.realm.ClassRealm;
+import org.codehaus.plexus.logging.Logger;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.graph.DependencyFilter;
+import org.eclipse.aether.graph.DependencyNode;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.util.filter.ExclusionsDependencyFilter;
+import org.eclipse.aether.util.graph.visitor.PreorderNodeListGenerator;
+
+@Named
+public class BootstrapCoreExtensionManager
+{
+ private final Logger log;
+
+ private final DefaultPluginDependenciesResolver pluginDependenciesResolver;
+
+ private final DefaultRepositorySystemSessionFactory repositorySystemSessionFactory;
+
+ private final ClassWorld classWorld;
+
+ private final ClassRealm parentRealm;
+
+ @Inject
+ public BootstrapCoreExtensionManager( Logger log, DefaultPluginDependenciesResolver pluginDependenciesResolver,
+ DefaultRepositorySystemSessionFactory repositorySystemSessionFactory,
+ PlexusContainer container )
+ {
+ this.log = log;
+ this.pluginDependenciesResolver = pluginDependenciesResolver;
+ this.repositorySystemSessionFactory = repositorySystemSessionFactory;
+ this.classWorld = ( (DefaultPlexusContainer) container ).getClassWorld();
+ this.parentRealm = container.getContainerRealm();
+ }
+
+ public List<CoreExtensionEntry> loadCoreExtensions( MavenExecutionRequest request, Set<String> providedArtifacts,
+ List<CoreExtension> extensions )
+ throws Exception
+ {
+ RepositorySystemSession repoSession = repositorySystemSessionFactory.newRepositorySession( request );
+ List<RemoteRepository> repositories = RepositoryUtils.toRepos( request.getPluginArtifactRepositories() );
+
+ return resolveCoreExtensions( repoSession, repositories, providedArtifacts, extensions );
+ }
+
+ private List<CoreExtensionEntry> resolveCoreExtensions( RepositorySystemSession repoSession,
+ List<RemoteRepository> repositories,
+ Set<String> providedArtifacts,
+ List<CoreExtension> configuration )
+ throws Exception
+ {
+ List<CoreExtensionEntry> extensions = new ArrayList<CoreExtensionEntry>();
+
+ DependencyFilter dependencyFilter = new ExclusionsDependencyFilter( providedArtifacts );
+
+ for ( CoreExtension extension : configuration )
+ {
+ List<Artifact> artifacts = resolveExtension( extension, repoSession, repositories, dependencyFilter );
+ if ( !artifacts.isEmpty() )
+ {
+ extensions.add( createExtension( extension, artifacts ) );
+ }
+ }
+
+ return Collections.unmodifiableList( extensions );
+ }
+
+ private CoreExtensionEntry createExtension( CoreExtension extension, List<Artifact> artifacts )
+ throws Exception
+ {
+ String realmId =
+ "coreExtension>" + extension.getGroupId() + ":" + extension.getArtifactId() + ":" + extension.getVersion();
+ ClassRealm realm = classWorld.newRealm( realmId, null );
+ log.debug( "Populating class realm " + realm.getId() );
+ realm.setParentRealm( parentRealm );
+ for ( Artifact artifact : artifacts )
+ {
+ File file = artifact.getFile();
+ log.debug( " Included " + file );
+ realm.addURL( file.toURI().toURL() );
+ }
+ return CoreExtensionEntry.discoverFrom( realm, Collections.singleton( artifacts.get( 0 ).getFile() ) );
+ }
+
+ private List<Artifact> resolveExtension( CoreExtension extension, RepositorySystemSession repoSession,
+ List<RemoteRepository> repositories, DependencyFilter dependencyFilter )
+ throws PluginResolutionException
+ {
+ Plugin plugin = new Plugin();
+ plugin.setGroupId( extension.getGroupId() );
+ plugin.setArtifactId( extension.getArtifactId() );
+ plugin.setVersion( extension.getVersion() );
+
+ DependencyNode root =
+ pluginDependenciesResolver.resolveCoreExtension( plugin, dependencyFilter, repositories, repoSession );
+ PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
+ root.accept( nlg );
+ List<Artifact> artifacts = nlg.getArtifacts( false );
+
+ return artifacts;
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven/blob/6efacdb3/maven-embedder/src/main/mdo/core-extensions.mdo
----------------------------------------------------------------------
diff --git a/maven-embedder/src/main/mdo/core-extensions.mdo b/maven-embedder/src/main/mdo/core-extensions.mdo
new file mode 100644
index 0000000..f4b0215
--- /dev/null
+++ b/maven-embedder/src/main/mdo/core-extensions.mdo
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ 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.
+
+-->
+
+<model xmlns="http://modello.codehaus.org/MODELLO/1.4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <id>CoreExtensions</id>
+ <name>CoreExtensions</name>
+
+ <defaults>
+ <default>
+ <key>package</key>
+ <value>org.apache.maven.cli.internal.extension.model</value>
+ </default>
+ </defaults>
+
+ <classes>
+ <class rootElement="true" xml.tagName="extensions">
+ <name>CoreExtensions</name>
+ <version>1.0.0+</version>
+ <fields>
+ <field>
+ <name>extensions</name>
+ <version>1.0.0+</version>
+ <association xml.itemsStyle="flat">
+ <type>CoreExtension</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ </class>
+ <class xml.tagName="extension">
+ <name>CoreExtension</name>
+ <version>1.0.0+</version>
+ <fields>
+ <field>
+ <name>groupId</name>
+ <version>1.0.0+</version>
+ <required>true</required>
+ <type>String</type>
+ </field>
+ <field>
+ <name>artifactId</name>
+ <version>1.0.0+</version>
+ <required>true</required>
+ <type>String</type>
+ </field>
+ <field>
+ <name>version</name>
+ <version>1.0.0+</version>
+ <required>true</required>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ </classes>
+</model>