diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginRepository.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginRepository.java new file mode 100644 index 0000000000..006441a8de --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginRepository.java @@ -0,0 +1,58 @@ +package org.apache.maven.plugin; + +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; +import org.codehaus.plexus.util.xml.Xpp3DomBuilder; +import org.apache.maven.model.Plugin; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.MojoDescriptor; + +import java.util.List; +import java.io.StringReader; + +@Component( role = PluginRepository.class) +public class DefaultPluginRepository implements PluginRepository +{ + @Requirement + protected MavenPluginCollector pluginCollector; + + public Plugin findPluginById(String id, String mojoId) throws Exception + { + if(pluginCollector == null) + { + throw new IllegalArgumentException("pluginCollector: null"); + } + + if(id == null) + { + throw new IllegalArgumentException("id: null"); + } + + String[] token = id.split(":"); + if(token.length != 3) + { + throw new IllegalArgumentException("id: does not include complete id"); + } + + Plugin plugin = new Plugin(); + plugin.setGroupId(token[0]); + plugin.setArtifactId(token[1]); + plugin.setVersion(token[2]); + + PluginDescriptor descriptor = pluginCollector.getPluginDescriptor(plugin); + if(descriptor == null) + { + return null; + } + + for(MojoDescriptor mojo : (List) descriptor.getMojos()) + { + if(mojo.getId().equals(id + ":"+ mojoId) && mojo.getMojoConfiguration() != null) + { + plugin.setConfiguration(Xpp3DomBuilder.build( new StringReader( mojo.getMojoConfiguration().toString() ) )); + } + } + + return plugin; + } +} diff --git a/maven-core/src/main/java/org/apache/maven/plugin/PluginRepository.java b/maven-core/src/main/java/org/apache/maven/plugin/PluginRepository.java new file mode 100644 index 0000000000..f13e53f8dc --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/plugin/PluginRepository.java @@ -0,0 +1,10 @@ +package org.apache.maven.plugin; + +import org.apache.maven.model.Plugin; +import org.codehaus.plexus.configuration.PlexusConfigurationException; + + +public interface PluginRepository { + + Plugin findPluginById(String pluginId, String mojoId) throws Exception; +} diff --git a/maven-core/src/main/resources/META-INF/plexus/components.xml b/maven-core/src/main/resources/META-INF/plexus/components.xml index 3958661982..9c37c7b053 100644 --- a/maven-core/src/main/resources/META-INF/plexus/components.xml +++ b/maven-core/src/main/resources/META-INF/plexus/components.xml @@ -26,6 +26,16 @@ use a configuration source to pull in the lifecycle information. --> + + org.apache.maven.plugin.PluginRepository + default + org.apache.maven.plugin.DefaultPluginRepository + + + org.apache.maven.plugin.MavenPluginCollector + + + org.apache.maven.lifecycle.binding.LifecycleBindingManager default diff --git a/maven-embedder/src/main/java/org/apache/maven/embedder/MavenEmbedder.java b/maven-embedder/src/main/java/org/apache/maven/embedder/MavenEmbedder.java index 2801734b19..84fa894244 100644 --- a/maven-embedder/src/main/java/org/apache/maven/embedder/MavenEmbedder.java +++ b/maven-embedder/src/main/java/org/apache/maven/embedder/MavenEmbedder.java @@ -58,18 +58,16 @@ import org.apache.maven.model.io.xpp3.MavenXpp3Writer; import org.apache.maven.monitor.event.DefaultEventDispatcher; import org.apache.maven.monitor.event.EventDispatcher; -import org.apache.maven.plugin.InvalidPluginException; -import org.apache.maven.plugin.MavenPluginCollector; -import org.apache.maven.plugin.MavenPluginDiscoverer; -import org.apache.maven.plugin.PluginManager; -import org.apache.maven.plugin.PluginManagerException; -import org.apache.maven.plugin.PluginNotFoundException; +import org.apache.maven.plugin.*; import org.apache.maven.plugin.version.PluginVersionNotFoundException; import org.apache.maven.plugin.version.PluginVersionResolutionException; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectBuilder; import org.apache.maven.project.MavenProjectBuildingResult; import org.apache.maven.project.ProjectBuildingException; +import org.apache.maven.project.builder.ProjectBuilder; +import org.apache.maven.project.builder.Mixer; +import org.apache.maven.plugin.PluginRepository; import org.apache.maven.reactor.MavenExecutionException; import org.apache.maven.reactor.MissingModuleException; import org.apache.maven.settings.Settings; @@ -92,6 +90,7 @@ import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.component.repository.exception.ComponentRepositoryException; import org.codehaus.plexus.configuration.PlexusConfigurationException; +import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.logging.LoggerManager; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.ReaderFactory; @@ -147,6 +146,10 @@ public class MavenEmbedder private MavenExecutionRequestPopulator populator; private BuildPlanner buildPlanner; + + private PluginRepository pluginRepository; + + private Mixer mixer; // ---------------------------------------------------------------------- // Configuration @@ -246,6 +249,15 @@ public void writeModel( Writer writer, modelWriter.write( writer, model ); } + public PlexusConfiguration getPluginConfiguration(String pluginId, String mojoId, Model model) throws Exception + { + try { + return mixer.mixPluginAndReturnConfig(pluginRepository.findPluginById(pluginId, mojoId), model); + } catch (PlexusConfigurationException e) { + throw new IOException(e.getMessage()); + } + } + // ---------------------------------------------------------------------- // Settings // ---------------------------------------------------------------------- @@ -656,6 +668,10 @@ private void start( Configuration configuration ) artifactHandlerManager = container.lookup( ArtifactHandlerManager.class ); + pluginRepository = container.lookup( PluginRepository.class ); + + mixer = (Mixer) container.lookup( ProjectBuilder.class ); + // This is temporary as we can probably cache a single request and use it for default values and // simply cascade values in from requests used for individual executions. request = new DefaultMavenExecutionRequest(); diff --git a/maven-project-builder/src/main/java/org/apache/maven/project/builder/PomTransformer.java b/maven-project-builder/src/main/java/org/apache/maven/project/builder/PomTransformer.java index 72abaed782..bfc0b80df0 100644 --- a/maven-project-builder/src/main/java/org/apache/maven/project/builder/PomTransformer.java +++ b/maven-project-builder/src/main/java/org/apache/maven/project/builder/PomTransformer.java @@ -162,8 +162,7 @@ public PomTransformer(DomainModelFactory factory) ProjectUri.Build.Resources.Resource.directory, ProjectUri.Build.TestResources.TestResource.directory, ProjectUri.Build.Filters.filter, - ProjectUri.Reporting.outputDirectory ) ) ); - + ProjectUri.Reporting.outputDirectory ) ) ); /** * @see ModelTransformer#transformToDomainModel(java.util.List, java.util.List) */ diff --git a/maven-project/src/main/java/org/apache/maven/project/builder/Mixer.java b/maven-project/src/main/java/org/apache/maven/project/builder/Mixer.java new file mode 100644 index 0000000000..e3b4715975 --- /dev/null +++ b/maven-project/src/main/java/org/apache/maven/project/builder/Mixer.java @@ -0,0 +1,17 @@ +package org.apache.maven.project.builder; + +import org.apache.maven.project.MavenProject; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.Model; +import org.codehaus.plexus.configuration.PlexusConfiguration; + +import java.io.IOException; + + +public interface Mixer +{ + + Model mixPlugin(Plugin plugin, Model model) throws IOException; + + PlexusConfiguration mixPluginAndReturnConfig(Plugin plugin, Model model) throws IOException; +} diff --git a/maven-project/src/main/java/org/apache/maven/project/builder/PluginMixin.java b/maven-project/src/main/java/org/apache/maven/project/builder/PluginMixin.java new file mode 100644 index 0000000000..bc16dc2339 --- /dev/null +++ b/maven-project/src/main/java/org/apache/maven/project/builder/PluginMixin.java @@ -0,0 +1,116 @@ +package org.apache.maven.project.builder; + +import org.apache.maven.shared.model.InputStreamDomainModel; +import org.apache.maven.shared.model.ModelProperty; +import org.apache.maven.shared.model.ModelMarshaller; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.Model; +import org.apache.maven.model.Build; +import org.apache.maven.model.io.xpp3.MavenXpp3Writer; +import org.codehaus.plexus.util.WriterFactory; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.ReaderFactory; + +import java.io.*; +import java.util.List; +import java.util.Set; +import java.util.HashSet; +import java.util.ArrayList; + + +public class PluginMixin implements InputStreamDomainModel { + + + /** + * Bytes containing the underlying model + */ + private byte[] inputBytes; + + /** + * History of joins and deletes of model properties + */ + private String eventHistory; + + private List modelProperties; + + public PluginMixin(Plugin plugin) + throws IOException + { + if(plugin == null) + { + throw new IllegalArgumentException("plugin: null"); + } + Model model = new Model(); + Build build = new Build(); + build.addPlugin(plugin); + model.setBuild(build); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Writer out = null; + MavenXpp3Writer writer = new MavenXpp3Writer(); + try + { + out = WriterFactory.newXmlWriter( baos ); + writer.write( out, model ); + } + finally + { + if ( out != null ) + { + out.close(); + } + } + inputBytes = baos.toByteArray(); + } + + public InputStream getInputStream() { + byte[] copy = new byte[inputBytes.length]; + System.arraycopy( inputBytes, 0, copy, 0, inputBytes.length ); + return new ByteArrayInputStream( copy ); + } + + public List getModelProperties() throws IOException { + if(modelProperties == null) + { + Set s = new HashSet(); + //TODO: Should add all collections from ProjectUri + s.addAll(PomTransformer.URIS); + s.add(ProjectUri.Build.PluginManagement.Plugins.Plugin.Executions.xUri); + s.add(ProjectUri.DependencyManagement.Dependencies.Dependency.Exclusions.xUri); + s.add(ProjectUri.Dependencies.Dependency.Exclusions.xUri); + s.add(ProjectUri.Build.Plugins.Plugin.Executions.xUri); + s.add(ProjectUri.Build.Plugins.Plugin.Executions.Execution.Goals.xURI); + s.add(ProjectUri.Reporting.Plugins.Plugin.ReportSets.xUri); + s.add(ProjectUri.Reporting.Plugins.Plugin.ReportSets.ReportSet.configuration); + s.add(ProjectUri.Build.Plugins.Plugin.Executions.Execution.configuration); + modelProperties = ModelMarshaller.marshallXmlToModelProperties( + getInputStream(), ProjectUri.baseUri, s ); + } + return new ArrayList(modelProperties); + } + + public String getEventHistory() { + return eventHistory; + } + + public void setEventHistory(String eventHistory) { + this.eventHistory = eventHistory; + } + + /** + * Returns XML model as string + * + * @return XML model as string + */ + public String asString() + { + try + { + return IOUtil.toString( ReaderFactory.newXmlReader( new ByteArrayInputStream( inputBytes ) ) ); + } + catch ( IOException ioe ) + { + // should not occur: everything is in-memory + return ""; + } + } +} diff --git a/maven-project/src/main/java/org/apache/maven/project/builder/PomClassicTransformer.java b/maven-project/src/main/java/org/apache/maven/project/builder/PomClassicTransformer.java index aa41b80e2d..7c3c63103b 100644 --- a/maven-project/src/main/java/org/apache/maven/project/builder/PomClassicTransformer.java +++ b/maven-project/src/main/java/org/apache/maven/project/builder/PomClassicTransformer.java @@ -44,6 +44,10 @@ public void interpolateModelProperties(List modelProperties, DomainModel domainModel) throws IOException { + if(! ( domainModel instanceof PomClassicDomainModel ) ) + { + return; + } Interpolator.interpolateModelProperties( modelProperties, interpolatorProperties, (PomClassicDomainModel) domainModel); } } diff --git a/maven-project/src/main/java/org/apache/maven/project/builder/impl/DefaultProjectBuilder.java b/maven-project/src/main/java/org/apache/maven/project/builder/impl/DefaultProjectBuilder.java index 34cfad7867..3c7fe6cde1 100644 --- a/maven-project/src/main/java/org/apache/maven/project/builder/impl/DefaultProjectBuilder.java +++ b/maven-project/src/main/java/org/apache/maven/project/builder/impl/DefaultProjectBuilder.java @@ -23,7 +23,6 @@ import java.io.IOException; import java.io.Reader; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -34,34 +33,29 @@ import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.model.Model; import org.apache.maven.model.Parent; +import org.apache.maven.model.Plugin; import org.apache.maven.model.io.xpp3.MavenXpp3Reader; import org.apache.maven.project.MavenProject; import org.apache.maven.project.ProjectBuilderConfiguration; -import org.apache.maven.project.builder.ArtifactModelContainerFactory; -import org.apache.maven.project.builder.IdModelContainerFactory; -import org.apache.maven.project.builder.PomArtifactResolver; -import org.apache.maven.project.builder.PomClassicDomainModel; -import org.apache.maven.project.builder.PomClassicDomainModelFactory; -import org.apache.maven.project.builder.PomClassicTransformer; -import org.apache.maven.project.builder.PomTransformer; -import org.apache.maven.project.builder.ProjectBuilder; -import org.apache.maven.shared.model.DomainModel; -import org.apache.maven.shared.model.InterpolatorProperty; -import org.apache.maven.shared.model.ModelEventListener; -import org.apache.maven.shared.model.ModelTransformerContext; +import org.apache.maven.project.builder.*; +import org.apache.maven.shared.model.*; +import org.apache.maven.shared.model.impl.DefaultModelDataSource; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.logging.LogEnabled; import org.codehaus.plexus.logging.Logger; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.configuration.PlexusConfiguration; +import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; +import org.apache.maven.shared.model.ModelMarshaller; /** * Default implementation of the project builder. */ @Component(role = ProjectBuilder.class) public class DefaultProjectBuilder - implements ProjectBuilder, LogEnabled + implements ProjectBuilder, Mixer, LogEnabled { @Requirement private ArtifactFactory artifactFactory; @@ -371,5 +365,85 @@ public Model getSuperModel() } return superModel; - } + } + + public Model mixPlugin(Plugin plugin, Model model) throws IOException + { + //TODO - interpolation + List domainModels = new ArrayList(); + domainModels.add( new PluginMixin(plugin) ); + domainModels.add( new PomClassicDomainModel(model) ); + + PomClassicTransformer transformer = new PomClassicTransformer( new PomClassicDomainModelFactory() ); + + ModelTransformerContext ctx = new ModelTransformerContext(PomTransformer.MODEL_CONTAINER_INFOS ); + + PomClassicDomainModel transformedDomainModel = ( (PomClassicDomainModel) ctx.transform( domainModels, + transformer, + transformer, + Collections.EMPTY_LIST, + null, + listeners ) ); + return transformedDomainModel.getModel(); + // List pluginProperties = ModelMarshaller.marshallXmlToModelProperties( + // (new PluginMixin(plugin)).getInputStream(), ProjectUri.Build.Plugins.xUri, null); + + } + + public PlexusConfiguration mixPluginAndReturnConfig(Plugin plugin, Model model) throws IOException + { + List domainModels = new ArrayList(); + domainModels.add( new PluginMixin(plugin) ); + domainModels.add( new PomClassicDomainModel(model) ); + + PomClassicTransformer transformer = new PomClassicTransformer( new PomClassicDomainModelFactory() ); + + ModelTransformerContext ctx = new ModelTransformerContext(PomTransformer.MODEL_CONTAINER_INFOS ); + + PomClassicDomainModel transformedDomainModel = ( (PomClassicDomainModel) ctx.transform( domainModels, + transformer, + transformer, + Collections.EMPTY_LIST, + null, + listeners ) ); + ModelDataSource source = + new DefaultModelDataSource(transformedDomainModel.getModelProperties(), PomTransformer.MODEL_CONTAINER_FACTORIES); + for(ModelContainer pluginContainer : source.queryFor(ProjectUri.Build.Plugins.Plugin.xUri)) + { + if(matchesIdOfPlugin(pluginContainer, plugin)) + { + List config = new ArrayList(); + for(ModelProperty mp : pluginContainer.getProperties()) + { + if(mp.getUri().startsWith(ProjectUri.Build.Plugins.Plugin.configuration)) + { + config.add(mp); + } + } + return new XmlPlexusConfiguration(ModelMarshaller.unmarshalModelPropertiesToXml(config, ProjectUri.Build.Plugins.Plugin.xUri)); + + } + } + return null; + } + + private static boolean matchesIdOfPlugin(ModelContainer mc, Plugin plugin) + { + List props = mc.getProperties(); + return getValueByUri(ProjectUri.Build.Plugins.Plugin.groupId, props).equals(plugin.getGroupId()) + && getValueByUri(ProjectUri.Build.Plugins.Plugin.artifactId, props).equals(plugin.getArtifactId()) + && getValueByUri(ProjectUri.Build.Plugins.Plugin.version, props).equals(plugin.getVersion()); + } + + private static String getValueByUri(String uri, List modelProperties) + { + for(ModelProperty mp : modelProperties) + { + if(mp.getUri().equals(uri)) + { + return mp.getResolvedValue(); + } + } + return ""; + } } diff --git a/maven-project/src/test/java/org/apache/maven/project/builder/PluginBuilderTest.java b/maven-project/src/test/java/org/apache/maven/project/builder/PluginBuilderTest.java new file mode 100644 index 0000000000..10378dc80a --- /dev/null +++ b/maven-project/src/test/java/org/apache/maven/project/builder/PluginBuilderTest.java @@ -0,0 +1,4 @@ +package org.apache.maven.project.builder; + +public class PluginBuilderTest { +} diff --git a/maven-project/src/test/java/org/apache/maven/project/builder/PomConstructionTest.java b/maven-project/src/test/java/org/apache/maven/project/builder/PomConstructionTest.java index 7811ab1dc0..bf15e66ec1 100644 --- a/maven-project/src/test/java/org/apache/maven/project/builder/PomConstructionTest.java +++ b/maven-project/src/test/java/org/apache/maven/project/builder/PomConstructionTest.java @@ -21,34 +21,51 @@ import java.io.File; import java.io.IOException; +import java.io.FileInputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.maven.MavenTools; +import org.apache.maven.model.Model; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.io.xpp3.MavenXpp3Reader; import org.apache.maven.artifact.Artifact; import org.apache.maven.project.harness.PomTestWrapper; import org.codehaus.plexus.PlexusTestCase; +import org.codehaus.plexus.configuration.PlexusConfiguration; +import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; public class PomConstructionTest extends PlexusTestCase { - private static String BASE_POM_DIR = "src/test/resources-project-builder"; + private static String BASE_DIR = "src/test"; + + private static String BASE_POM_DIR = BASE_DIR + "/resources-project-builder"; + + private static String BASE_MIXIN_DIR = BASE_DIR + "/resources-mixins"; private ProjectBuilder projectBuilder; + private Mixer mixer; + private MavenTools mavenTools; private PomArtifactResolver pomArtifactResolver; private File testDirectory; + private File testMixinDirectory; + protected void setUp() throws Exception { testDirectory = new File( getBasedir(), BASE_POM_DIR ); + testMixinDirectory = new File( getBasedir(), BASE_MIXIN_DIR ); projectBuilder = lookup( ProjectBuilder.class ); + mixer = (Mixer) projectBuilder; mavenTools = lookup( MavenTools.class ); pomArtifactResolver = new PomArtifactResolver() { @@ -62,6 +79,18 @@ public void resolve( Artifact artifact ) }; } + public void testPluginMergeSimple() + throws Exception + { + Model model = buildPom( "plugin-merge-simple" ).getDomainModel().getModel(); + Model plugin = buildMixin("plugins/simple"); + + model = mixer.mixPlugin((Plugin) plugin.getBuild().getPlugins().get(0), model); + + PomTestWrapper pom = new PomTestWrapper( model ); + assertEquals( "FAILED", pom.getValue( "build/plugins[1]/configuration[1]/propertiesFile" ) ); + } + // Some better conventions for the test poms needs to be created and each of these tests // that represent a verification of a specification item needs to be a couple lines at most. // The expressions help a lot, but we need a clean to pick up a directory of POMs, automatically load @@ -731,11 +760,24 @@ private PomTestWrapper buildPom( String pomPath ) return new PomTestWrapper( pomFile, projectBuilder.buildModel( pomFile, null, pomArtifactResolver ) ); } + private Model buildMixin( String mixinPath ) + throws IOException, XmlPullParserException + { + File mixinFile = new File( testMixinDirectory , mixinPath ); + if ( mixinFile.isDirectory() ) + { + mixinFile = new File( mixinFile, "mixin.xml" ); + } + FileInputStream pluginStream = new FileInputStream( mixinFile ); + MavenXpp3Reader reader = new MavenXpp3Reader(); + return reader.read(pluginStream, false); + } + protected void assertModelEquals( PomTestWrapper pom, Object expected, String expression ) { assertEquals( expected, pom.getValue( expression ) ); } - + // Need to get this to walk around a directory and automatically build up the artifact set. If we // follow some standard conventions this can be simple. class FileBasedPomArtifactResolver diff --git a/maven-project/src/test/resources-mixins/plugins/simple/mixin.xml b/maven-project/src/test/resources-mixins/plugins/simple/mixin.xml new file mode 100644 index 0000000000..5bcd5714e8 --- /dev/null +++ b/maven-project/src/test/resources-mixins/plugins/simple/mixin.xml @@ -0,0 +1,14 @@ + + + + + org.apache.maven.its.plugins + maven-it-plugin-configuration + 2.1-SNAPSHOT + + FAILED + + + + + diff --git a/maven-project/src/test/resources-project-builder/plugin-merge-simple/pom.xml b/maven-project/src/test/resources-project-builder/plugin-merge-simple/pom.xml new file mode 100644 index 0000000000..10eac25fd4 --- /dev/null +++ b/maven-project/src/test/resources-project-builder/plugin-merge-simple/pom.xml @@ -0,0 +1,17 @@ + + 4.0.0 + + org.sonatype.nexus + nexus-indexer + 1.1.3-SNAPSHOT + + + + + org.apache.maven.its.plugins + maven-it-plugin-configuration + 2.1-SNAPSHOT + + + + \ No newline at end of file