diff --git a/maven-plugin-annotations/pom.xml b/maven-plugin-annotations/pom.xml new file mode 100644 index 0000000..c794392 --- /dev/null +++ b/maven-plugin-annotations/pom.xml @@ -0,0 +1,31 @@ + + + + 4.0.0 + + maven-plugin-tools + org.apache.maven.plugin-tools + 3.0-SNAPSHOT + + + + maven-plugin-annotations + + diff --git a/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Component.java b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Component.java new file mode 100644 index 0000000..f1607f1 --- /dev/null +++ b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Component.java @@ -0,0 +1,41 @@ +package org.apache.maven.plugins.annotations; +/* + * 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.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +@Documented +@Retention( RetentionPolicy.RUNTIME ) +@Target( { ElementType.FIELD, ElementType.METHOD } ) +@Inherited +public @interface Component +{ + String role() default ""; + + String roleHint() default ""; +} diff --git a/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java new file mode 100644 index 0000000..3d6cca4 --- /dev/null +++ b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java @@ -0,0 +1,43 @@ +package org.apache.maven.plugins.annotations; +/* + * 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.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +@Documented +@Retention( RetentionPolicy.RUNTIME ) +@Target( ElementType.TYPE ) +@Inherited +public @interface Execute +{ + LifecyclePhase phase() default LifecyclePhase.NONE; + + String goal() default ""; + + String lifecycle() default ""; +} diff --git a/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/LifecyclePhase.java b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/LifecyclePhase.java new file mode 100644 index 0000000..75bb163 --- /dev/null +++ b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/LifecyclePhase.java @@ -0,0 +1,75 @@ +package org.apache.maven.plugins.annotations; +/* + * 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. + */ + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public enum LifecyclePhase +{ + + VALIDATE( "validate" ), + INITIALIZE( "initialize" ), + GENERATE_SOURCES( "generate-sources" ), + PROCESS_SOURCES( "process-sources" ), + GENERATE_RESOURCES( "generate-resources" ), + PROCESS_RESOURCES( "process-resources" ), + COMPILE( "compile" ), + PROCESS_CLASSES( "process-classes" ), + GENERATE_TEST_SOURCES( "generate-test-sources" ), + PROCESS_TEST_SOURCES( "process-test-sources" ), + GENERATE_TEST_RESOURCES( "generate-test-resources" ), + PROCESS_TEST_RESOURCES( "process-test-resources" ), + TEST_COMPILE( "test-compile" ), + PROCESS_TEST_CLASSES( "process-test-classes" ), + TEST( "test" ), + PREPARE_PACKAGE( "prepare-package" ), + PACKAGE( "package" ), + PRE_INTEGRATION_TEST( "pre-integration-test" ), + INTEGRATION_TEST( "integration-test" ), + POST_INTEGRATION_TEST( "post-integration-test" ), + VERIFY( "verify" ), + INSTALL( "install" ), + DEPLOY( "deploy" ), + + PRE_CLEAN( "pre-clean" ), + CLEAN( "clean" ), + POST_CLEAN( "post-clean" ), + + PRE_SITE( "pre-site" ), + SITE( "site" ), + POST_SITE( "post-site" ), + SITE_DEPLOY( "site-deploy" ), + + NONE( "" ); + + private final String id; + + LifecyclePhase( String id ) + { + this.id = id; + } + + public String id() + { + return this.id; + } + +} diff --git a/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Mojo.java b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Mojo.java new file mode 100644 index 0000000..3eef3c8 --- /dev/null +++ b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Mojo.java @@ -0,0 +1,66 @@ +package org.apache.maven.plugins.annotations; +/* + * 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.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +@Documented +@Retention( RetentionPolicy.RUNTIME ) +@Target( ElementType.TYPE ) +@Inherited +public @interface Mojo +{ + String name(); + + LifecyclePhase defaultPhase() default LifecyclePhase.NONE; + + String requiresDependencyResolution() default "runtime"; + + String requiresDependencyCollection() default ""; + + String instantiationStrategy() default "per-lookup"; + + String executionStrategy() default "once-per-session"; + + boolean requiresProject() default true; + + boolean requiresReports() default false; + + boolean aggregator() default false; + + boolean requiresDirectInvocation() default false; + + boolean requiresOnline() default false; + + boolean inheritByDefault() default true; + + String configurator() default ""; + + boolean threadSafe() default false; +} diff --git a/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Parameter.java b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Parameter.java new file mode 100644 index 0000000..ae1cc0a --- /dev/null +++ b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Parameter.java @@ -0,0 +1,47 @@ +package org.apache.maven.plugins.annotations; +/* + * 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.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +@Documented +@Retention( RetentionPolicy.RUNTIME ) +@Target( { ElementType.FIELD, ElementType.METHOD } ) +@Inherited +public @interface Parameter +{ + String alias() default ""; + + String expression() default ""; + + String defaultValue() default ""; + + boolean required() default false; + + boolean readonly() default false; +} diff --git a/maven-plugin-plugin/pom.xml b/maven-plugin-plugin/pom.xml index 9fb212a..262c50e 100644 --- a/maven-plugin-plugin/pom.xml +++ b/maven-plugin-plugin/pom.xml @@ -28,7 +28,7 @@ maven-plugin-plugin - 2.10-SNAPSHOT + 3.0-SNAPSHOT maven-plugin Maven Plugin Plugin @@ -59,10 +59,10 @@ - 2.0.6 - 2.10-SNAPSHOT 1.2 1.2 + 2.0.6 + true @@ -72,22 +72,27 @@ org.apache.maven.plugin-tools maven-plugin-tools-api - ${pluginToolsVersion} + ${project.version} org.apache.maven.plugin-tools maven-plugin-tools-model - ${pluginToolsVersion} + ${project.version} org.apache.maven.plugin-tools maven-plugin-tools-java - ${pluginToolsVersion} + ${project.version} + + + org.apache.maven.plugin-tools + maven-plugin-tools-annotations + ${project.version} org.apache.maven.plugin-tools maven-plugin-tools-beanshell - ${pluginToolsVersion} + ${project.version} org.apache.maven @@ -101,6 +106,29 @@ plexus-utils 2.0.5 + + org.codehaus.plexus + plexus-archiver + 2.1.1 + + + org.codehaus.plexus + plexus-velocity + 1.1.8 + + + velocity + velocity + + + + + + + org.apache.velocity + velocity + 1.7 + @@ -161,6 +189,7 @@ org.apache.maven.plugin-tools maven-plugin-tools-api + org.apache.maven maven-artifact-manager @@ -196,11 +225,34 @@ runtime + + org.apache.maven.plugin-tools + maven-plugin-tools-annotations + runtime + + org.codehaus.plexus plexus-utils + + org.codehaus.plexus + plexus-velocity + + + velocity + velocity + + + + + + + org.apache.velocity + velocity + + @@ -229,6 +281,15 @@ + + + + org.apache.maven.plugins + maven-plugin-plugin + 2.9 + + + @@ -277,10 +338,13 @@ + org.apache.maven.plugins maven-invoker-plugin + 1.6-SNAPSHOT ${project.build.directory}/it ${project.build.directory}/local-repo + ${it.debug} 3.0 @@ -292,6 +356,14 @@ + + + org.apache.maven.plugin-tools + maven-plugin-tools-annotations + ${project.version} + tests + + diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/invoker.properties b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/invoker.properties new file mode 100644 index 0000000..e3434ff --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/invoker.properties @@ -0,0 +1,3 @@ +invoker.goals.1 = install +invoker.goals.2 = org.apache.maven.its.annotation-with-inheritance-from-deps:annotation-with-inheritance-from-deps:1.0-SNAPSHOT:first +invoker.goals.3 = org.apache.maven.its.annotation-with-inheritance-from-deps:annotation-with-inheritance-from-deps:1.0-SNAPSHOT:help diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/pom.xml b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/pom.xml new file mode 100644 index 0000000..1e71de2 --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/pom.xml @@ -0,0 +1,125 @@ + + + + + + 4.0.0 + + org.apache.maven.its.annotation-with-inheritance-from-deps + annotation-with-inheritance-from-deps + 1.0-SNAPSHOT + maven-plugin + + Maven Integration Test :: annotation-with-inheritance-from-deps + + Test plugin-plugin, which tests maven-plugin-tools-api and + maven-plugin-tools-java. This will generate a plugin descriptor from + java-based mojo sources, install the plugin, and then use it. + + + + UTF-8 + 1.8.6 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.apache.maven + maven-project + @mavenVersion@ + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + compile + + + org.apache.maven.plugin-tools + maven-plugin-tools-annotations + @project.version@ + tests + + + org.codehaus.plexus + plexus-compiler-manager + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + org.codehaus.plexus + plexus-compiler-javac + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + mojo-descriptor + process-classes + + descriptor + + + + help-goal + + helpmojo + + + + + + + diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 0000000..70ecea5 --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,73 @@ +package org.apache.maven.plugin.coreit; + +/* + * 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 org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.tools.plugin.annotations.FooMojo; + +/** + * Touches a test file. + * + * @since 1.2 + * @deprecated Don't use! + */ +@Mojo( name = "first", requiresDependencyResolution = "test", defaultPhase = LifecyclePhase.INTEGRATION_TEST ) +public class FirstMojo + extends FooMojo +{ + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( alias = "alias" ) + private String aliasedParam; + + @Component( role = "org.apache.maven.project.MavenProjectHelper" )// , roleHint = "default" + private Object projectHelper; + + public void execute() + throws MojoExecutionException + { + if (bar == null) + { + throw new MojoExecutionException( "bar == null" ); + } + if (beer == null) + { + throw new MojoExecutionException( "beer == null" ); + } + if ( projectHelper == null ) + { + throw new MojoExecutionException( "projectHelper == null" ); + } + if ( compilerManager == null ) + { + throw new MojoExecutionException( "compilerManager == null" ); + } + + } + +} diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/resources/META-INF/maven/lifecycle.xml b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/resources/META-INF/maven/lifecycle.xml new file mode 100644 index 0000000..7b21d5a --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/resources/META-INF/maven/lifecycle.xml @@ -0,0 +1,17 @@ + + + my-lifecycle + + + process-classes + + + test + + ${project.build.directory}/generated-classes/cobertura + true + + + + + \ No newline at end of file diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy new file mode 100644 index 0000000..6aefc31 --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy @@ -0,0 +1,81 @@ + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +File oldHelpClass = new File( basedir, "target/classes/HelpMojo.class" ); +assert !oldHelpClass.exists() + +File newHelpClass = new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ); +assert newHelpClass.exists() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first"}[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Touches a test file.' +assert mojo.deprecated.text() == "Don't use!" +assert mojo.requiresDependencyResolution.text() == 'test' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == 'integration-test' +assert mojo.executePhase.text() == 'package' +assert mojo.executeLifecycle.text() == 'my-lifecycle' + +assert mojo.configuration.bar[0].text() == '${thebar}' +assert mojo.configuration.bar[0].'@implementation' == 'java.lang.String' +assert mojo.configuration.bar[0].'@default-value' == 'coolbar' + +assert mojo.configuration.beer[0].text() == '${thebeer}' +assert mojo.configuration.beer[0].'@implementation' == 'java.lang.String' +assert mojo.configuration.beer[0].'@default-value' == 'coolbeer' + +assert mojo.requirements.requirement.size() == 3 + +assert mojo.requirements.requirement[1].role.text() == 'org.codehaus.plexus.compiler.manager.CompilerManager' +assert mojo.requirements.requirement[1].'role-hint'.text() == '' +assert mojo.requirements.requirement[1].'field-name'.text() == 'compilerManager' + +assert mojo.requirements.requirement[2].role.text() == 'org.apache.maven.project.MavenProjectHelper' +//assert mojo.requirements.requirement[2].'role-hint'.text() == 'default' +assert mojo.requirements.requirement[2].'field-name'.text() == 'projectHelper' + +assert mojo.parameters.parameter.size() == 3 + +def parameter = mojo.parameters.parameter.findAll{ it.name.text() == "aliasedParam"}[0] + +assert parameter.name.text() == 'aliasedParam' +assert parameter.alias.text() == 'alias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == 'As of 0.2' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "beer"}[0] + +assert parameter.name.text() == 'beer' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == "wine is better" +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == 'beer for non french folks' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "bar"}[0] + +assert parameter.name.text() == 'bar' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == 'the cool bar to go' + +return true; diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/invoker.properties b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/invoker.properties new file mode 100644 index 0000000..c3906a8 --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/invoker.properties @@ -0,0 +1,3 @@ +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.annotation-with-inheritance-reactor:module-mojo:1.0-SNAPSHOT:it0014 +invoker.goals.3 = org.apache.maven.its.annotation-with-inheritance-reactor:module-mojo:1.0-SNAPSHOT:first diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/pom.xml b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/pom.xml new file mode 100644 index 0000000..ab6d5ed --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/pom.xml @@ -0,0 +1,32 @@ + + + + + + 4.0.0 + + org.apache.maven.its.annotation-with-inheritance-reactor + annotation-with-inheritance-reactor + 1.0-SNAPSHOT + + module-abstract-mojo + + + diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/src/main/java/org/apache/maven/plugins/AbstractFirstMojo.java b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/src/main/java/org/apache/maven/plugins/AbstractFirstMojo.java new file mode 100644 index 0000000..bfc8a4e --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/src/main/java/org/apache/maven/plugins/AbstractFirstMojo.java @@ -0,0 +1,66 @@ +package org.apache.maven.plugins; + +/* + * 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 org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.codehaus.plexus.compiler.manager.CompilerManager; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; + +import java.io.File; + +/** + * Touches a test file. + * + */ +public abstract class AbstractFirstMojo + extends AbstractMojo +{ + + /** + * Project directory. + */ + @Parameter( defaultValue = "${basedir}", readonly = true ) + protected File basedir; + + @Parameter( expression = "${first.touchFile}", defaultValue = "${project.build.directory}/touch.txt", + required = true ) + protected File touchFile; + + /** + * Plexus compiler manager. + */ + @Component + protected CompilerManager compilerManager; + + /** + * + */ + @Component(role = "org.apache.maven.artifact.metadata.ArtifactMetadataSource", roleHint = "maven") + protected ArtifactMetadataSource artifactMetadataSource; + + + +} diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/pom.xml b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/pom.xml new file mode 100644 index 0000000..4441a23 --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/pom.xml @@ -0,0 +1,59 @@ + + + + + + 4.0.0 + + org.apache.maven.its.annotation-with-inheritance-reactor + annotation-with-inheritance-reactor + 1.0-SNAPSHOT + + maven-plugin + module-mojo + + + org.apache.maven.its.annotation-with-inheritance-reactor + module-abstract-mojo + ${project.version} + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + mojo-descriptor + process-classes + + descriptor + + + + + + + diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java new file mode 100644 index 0000000..b6dc2fa --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java @@ -0,0 +1,66 @@ +package org.apache.maven.plugin.coreit; + +/* + * 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 org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.IOException; + +/** + * Touches a test file. + * + */ +@Mojo( name = "it0014") +public class CoreIt0014Mojo + extends AbstractMojo +{ + + @Parameter(expression ="${project.build.directory}", required = true) + private String outputDirectory; + + public void execute() + throws MojoExecutionException + { + getLog().info( "outputDirectory = " + outputDirectory ); + + File f = new File( outputDirectory ); + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try + { + touch.createNewFile(); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error writing verification file.", e ); + } + } + +} diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 0000000..a70cc1f --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,74 @@ +package org.apache.maven.plugin.coreit; + +/* + * 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 org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.AbstractFirstMojo; + +/** + * Touches a test file. + * + * @since 1.2 + * @deprecated Don't use! + */ +@Mojo( name = "first", requiresDependencyResolution = "test", defaultPhase = LifecyclePhase.INTEGRATION_TEST ) +@Execute( phase = LifecyclePhase.GENERATE_SOURCES, lifecycle = "cobertura" ) +public class FirstMojo + extends AbstractFirstMojo +{ + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( alias = "alias" ) + private String aliasedParam; + + @Component( role = "org.apache.maven.project.MavenProjectHelper") + private Object projectHelper; + + public void execute() + throws MojoExecutionException + { + if (basedir == null) + { + throw new MojoExecutionException( "basedir == null" ); + } + if (touchFile == null) + { + throw new MojoExecutionException( "touchFile == null" ); + } + if ( projectHelper == null ) + { + throw new MojoExecutionException( "projectHelper == null" ); + } + if ( compilerManager == null ) + { + throw new MojoExecutionException( "compilerManager == null" ); + } + + } + +} diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java new file mode 100644 index 0000000..8e28eba --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java @@ -0,0 +1,38 @@ +package org.apache.maven.plugin.coreit; + +/* + * 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 org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Mojo; + +/** + * Does nothing special. + * + */ +@Mojo( name = "second",requiresDependencyCollection = "compile", threadSafe = true) +public class SecondMojo + extends AbstractMojo +{ + + public void execute() + { + } + +} diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/resources/META-INF/maven/lifecycle.xml b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/resources/META-INF/maven/lifecycle.xml new file mode 100644 index 0000000..62d944b --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/resources/META-INF/maven/lifecycle.xml @@ -0,0 +1,17 @@ + + + cobertura + + + process-classes + + + test + + ${project.build.directory}/generated-classes/cobertura + true + + + + + \ No newline at end of file diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/pom.xml b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/pom.xml new file mode 100644 index 0000000..838ea70 --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/pom.xml @@ -0,0 +1,100 @@ + + + + + + 4.0.0 + + org.apache.maven.its.annotation-with-inheritance-reactor + annotation-with-inheritance-reactor + 1.0-SNAPSHOT + + Maven Integration Test :: annotation-with-inheritance + pom + + module-abstract-mojo + module-mojo + + + + UTF-8 + 1.8.6 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.apache.maven.plugin-tools + maven-plugin-tools-annotations + @project.version@ + tests + + + org.apache.maven + maven-project + @mavenVersion@ + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + compile + + + org.codehaus.plexus + plexus-compiler-manager + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + org.codehaus.plexus + plexus-compiler-javac + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/verify.groovy b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/verify.groovy new file mode 100644 index 0000000..7659c5d --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/verify.groovy @@ -0,0 +1,80 @@ +File touchFile = new File( basedir, "module-mojo/target/touch.txt" ) +assert touchFile.isFile() + +File descriptorFile = new File( basedir, "module-mojo/target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +assert pluginDescriptor.mojos.mojo.size() == 3 + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first"}[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Touches a test file.' +assert mojo.deprecated.text() == "Don't use!" +assert mojo.requiresDependencyResolution.text() == 'test' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == 'integration-test' +assert mojo.executePhase.text() == 'generate-sources' +assert mojo.executeLifecycle.text() == 'cobertura' + +assert mojo.configuration.basedir[0].text() == '' +assert mojo.configuration.basedir[0].'@implementation' == 'java.io.File' +assert mojo.configuration.basedir[0].'@default-value' == '${basedir}' + +assert mojo.configuration.touchFile[0].text() == '${first.touchFile}' +assert mojo.configuration.touchFile[0].'@implementation' == 'java.io.File' +assert mojo.configuration.touchFile[0].'@default-value' == '${project.build.directory}/touch.txt' + +assert mojo.requirements.requirement.size() == 3 + +assert mojo.requirements.requirement[2].role.text() == 'org.apache.maven.project.MavenProjectHelper' +//assert mojo.requirements.requirement[2].'role-hint'.text() == 'default' +assert mojo.requirements.requirement[2].'field-name'.text() == 'projectHelper' + +assert mojo.parameters.parameter.size() == 3 + +def parameter = mojo.parameters.parameter.findAll{ it.name.text() == "aliasedParam"}[0] + +assert parameter.name.text() == 'aliasedParam' +assert parameter.alias.text() == 'alias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == 'As of 0.2' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "touchFile"}[0] + +assert parameter.name.text() == 'touchFile' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "basedir"}[0] + +assert parameter.name.text() == 'basedir' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Project directory.' + +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "second"}[0] + +assert mojo.requiresDependencyCollection.text() == 'compile' +assert mojo.threadSafe.text() == 'true' + +return true; diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance/invoker.properties b/maven-plugin-plugin/src/it/annotation-with-inheritance/invoker.properties new file mode 100644 index 0000000..773daef --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance/invoker.properties @@ -0,0 +1,4 @@ +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.annotation-with-inheritance:annotation-with-inheritance:1.0-SNAPSHOT:it0014 +invoker.goals.3 = org.apache.maven.its.annotation-with-inheritance:annotation-with-inheritance:1.0-SNAPSHOT:first +invoker.goals.4 = org.apache.maven.its.annotation-with-inheritance:annotation-with-inheritance:1.0-SNAPSHOT:help diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance/pom.xml b/maven-plugin-plugin/src/it/annotation-with-inheritance/pom.xml new file mode 100644 index 0000000..945aaad --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance/pom.xml @@ -0,0 +1,119 @@ + + + + + + 4.0.0 + + org.apache.maven.its.annotation-with-inheritance + annotation-with-inheritance + 1.0-SNAPSHOT + maven-plugin + + Maven Integration Test :: annotation-with-inheritance + + Test plugin-plugin, which tests maven-plugin-tools-api and + maven-plugin-tools-java. This will generate a plugin descriptor from + java-based mojo sources, install the plugin, and then use it. + + + + UTF-8 + 1.8.6 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.apache.maven + maven-project + @mavenVersion@ + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + compile + + + org.codehaus.plexus + plexus-compiler-manager + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + org.codehaus.plexus + plexus-compiler-javac + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + mojo-descriptor + process-classes + + descriptor + + + + help-goal + + helpmojo + + + + + + + diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/AbstractFirstMojo.java b/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/AbstractFirstMojo.java new file mode 100644 index 0000000..6dcf140 --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/AbstractFirstMojo.java @@ -0,0 +1,66 @@ +package org.apache.maven.plugin.coreit; + +/* + * 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 org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.codehaus.plexus.compiler.manager.CompilerManager; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; + +import java.io.File; + +/** + * Touches a test file. + * + */ +public abstract class AbstractFirstMojo + extends AbstractMojo +{ + + /** + * Project directory. + */ + @Parameter( defaultValue = "${basedir}", readonly = true ) + protected File basedir; + + @Parameter( expression = "${first.touchFile}", defaultValue = "${project.build.directory}/touch.txt", + required = true ) + protected File touchFile; + + /** + * Plexus compiler manager. + */ + @Component + protected CompilerManager compilerManager; + + /** + * + */ + @Component(role = "org.apache.maven.artifact.metadata.ArtifactMetadataSource", roleHint = "maven") + protected ArtifactMetadataSource artifactMetadataSource; + + + +} diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java b/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java new file mode 100644 index 0000000..b6dc2fa --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java @@ -0,0 +1,66 @@ +package org.apache.maven.plugin.coreit; + +/* + * 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 org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.IOException; + +/** + * Touches a test file. + * + */ +@Mojo( name = "it0014") +public class CoreIt0014Mojo + extends AbstractMojo +{ + + @Parameter(expression ="${project.build.directory}", required = true) + private String outputDirectory; + + public void execute() + throws MojoExecutionException + { + getLog().info( "outputDirectory = " + outputDirectory ); + + File f = new File( outputDirectory ); + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try + { + touch.createNewFile(); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error writing verification file.", e ); + } + } + +} diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 0000000..adcb5e3 --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,73 @@ +package org.apache.maven.plugin.coreit; + +/* + * 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 org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +/** + * Touches a test file. + * + * @since 1.2 + * @deprecated Don't use! + */ +@Mojo( name = "first", requiresDependencyResolution = "test", defaultPhase = LifecyclePhase.INTEGRATION_TEST) +@Execute( phase = LifecyclePhase.GENERATE_SOURCES, lifecycle = "cobertura" ) +public class FirstMojo + extends AbstractFirstMojo +{ + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( alias = "alias" ) + private String aliasedParam; + + @Component( role = "org.apache.maven.project.MavenProjectHelper" )//, roleHint = "default" + private Object projectHelper; + + public void execute() + throws MojoExecutionException + { + if (basedir == null) + { + throw new MojoExecutionException( "basedir == null" ); + } + if (touchFile == null) + { + throw new MojoExecutionException( "touchFile == null" ); + } + if ( projectHelper == null ) + { + throw new MojoExecutionException( "projectHelper == null" ); + } + if ( compilerManager == null ) + { + throw new MojoExecutionException( "compilerManager == null" ); + } + + } + +} diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java b/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java new file mode 100644 index 0000000..8e28eba --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java @@ -0,0 +1,38 @@ +package org.apache.maven.plugin.coreit; + +/* + * 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 org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Mojo; + +/** + * Does nothing special. + * + */ +@Mojo( name = "second",requiresDependencyCollection = "compile", threadSafe = true) +public class SecondMojo + extends AbstractMojo +{ + + public void execute() + { + } + +} diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/resources/META-INF/maven/lifecycle.xml b/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/resources/META-INF/maven/lifecycle.xml new file mode 100644 index 0000000..62d944b --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/resources/META-INF/maven/lifecycle.xml @@ -0,0 +1,17 @@ + + + cobertura + + + process-classes + + + test + + ${project.build.directory}/generated-classes/cobertura + true + + + + + \ No newline at end of file diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy b/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy new file mode 100644 index 0000000..8554b25 --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy @@ -0,0 +1,84 @@ +File touchFile = new File( basedir, "target/touch.txt" ) +assert touchFile.isFile() + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +File oldHelpClass = new File( basedir, "target/classes/HelpMojo.class" ); +assert !oldHelpClass.exists() + +File newHelpClass = new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ); +assert newHelpClass.exists() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first"}[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Touches a test file.' +assert mojo.deprecated.text() == "Don't use!" +assert mojo.requiresDependencyResolution.text() == 'test' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == 'integration-test' +assert mojo.executePhase.text() == 'generate-sources' +assert mojo.executeLifecycle.text() == 'cobertura' + +assert mojo.configuration.basedir[0].text() == '' +assert mojo.configuration.basedir[0].'@implementation' == 'java.io.File' +assert mojo.configuration.basedir[0].'@default-value' == '${basedir}' + +assert mojo.configuration.touchFile[0].text() == '${first.touchFile}' +assert mojo.configuration.touchFile[0].'@implementation' == 'java.io.File' +assert mojo.configuration.touchFile[0].'@default-value' == '${project.build.directory}/touch.txt' + +assert mojo.requirements.requirement.size() == 3 + +assert mojo.requirements.requirement[2].role.text() == 'org.apache.maven.project.MavenProjectHelper' +//assert mojo.requirements.requirement[2].'role-hint'.text() == 'default' +assert mojo.requirements.requirement[2].'field-name'.text() == 'projectHelper' + +assert mojo.parameters.parameter.size() == 3 + +def parameter = mojo.parameters.parameter.findAll{ it.name.text() == "aliasedParam"}[0] + +assert parameter.name.text() == 'aliasedParam' +assert parameter.alias.text() == 'alias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == 'As of 0.2' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "touchFile"}[0] + +assert parameter.name.text() == 'touchFile' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "basedir"}[0] + +assert parameter.name.text() == 'basedir' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Project directory.' + +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "second"}[0] + +assert mojo.requiresDependencyCollection.text() == 'compile' +assert mojo.threadSafe.text() == 'true' + +return true; diff --git a/maven-plugin-plugin/src/it/help-basic/invoker.properties b/maven-plugin-plugin/src/it/help-basic/invoker.properties index 5b282bb..e384308 100644 --- a/maven-plugin-plugin/src/it/help-basic/invoker.properties +++ b/maven-plugin-plugin/src/it/help-basic/invoker.properties @@ -1,2 +1,2 @@ -invoker.goals.1 = install -invoker.goals.2 = org.apache.maven.its.plugin:help:1.0:help +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.plugin:help:1.0-SNAPSHOT:help diff --git a/maven-plugin-plugin/src/it/help-basic/pom.xml b/maven-plugin-plugin/src/it/help-basic/pom.xml index 0121194..c970246 100644 --- a/maven-plugin-plugin/src/it/help-basic/pom.xml +++ b/maven-plugin-plugin/src/it/help-basic/pom.xml @@ -24,7 +24,7 @@ under the License. org.apache.maven.its.plugin help - 1.0 + 1.0-SNAPSHOT maven-plugin @@ -41,9 +41,24 @@ under the License. maven-plugin-api 2.0 + + org.codehaus.plexus + plexus-utils + 3.0.1 + provided + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + org.apache.maven.plugins diff --git a/maven-plugin-plugin/src/it/help-package/invoker.properties b/maven-plugin-plugin/src/it/help-package/invoker.properties index 557f44a..6e222d4 100644 --- a/maven-plugin-plugin/src/it/help-package/invoker.properties +++ b/maven-plugin-plugin/src/it/help-package/invoker.properties @@ -1 +1 @@ -invoker.goals = compile +invoker.goals = clean compile diff --git a/maven-plugin-plugin/src/it/help-package/pom.xml b/maven-plugin-plugin/src/it/help-package/pom.xml index 3913245..1ae3c32 100644 --- a/maven-plugin-plugin/src/it/help-package/pom.xml +++ b/maven-plugin-plugin/src/it/help-package/pom.xml @@ -23,8 +23,8 @@ under the License. 4.0.0 org.apache.maven.its.plugin - help - 1.0 + help-package + 1.0-SNAPSHOT maven-plugin @@ -41,9 +41,24 @@ under the License. maven-plugin-api 2.0 + + org.codehaus.plexus + plexus-utils + 3.0.1 + provided + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + org.apache.maven.plugins diff --git a/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-a/pom.xml b/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-a/pom.xml index 8c772fe..4531045 100644 --- a/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-a/pom.xml +++ b/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-a/pom.xml @@ -25,7 +25,7 @@ under the License. org.apache.maven.its.plugin ipcr - 1.0 + 1.0-SNAPSHOT ipcr-dep-a diff --git a/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-b/pom.xml b/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-b/pom.xml index 254d8d6..8999cc2 100644 --- a/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-b/pom.xml +++ b/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-b/pom.xml @@ -25,7 +25,7 @@ under the License. org.apache.maven.its.plugin ipcr - 1.0 + 1.0-SNAPSHOT ipcr-dep-b @@ -42,7 +42,7 @@ under the License. org.apache.maven.its.plugin ipcr-dep-a - 1.0 + ${project.version} diff --git a/maven-plugin-plugin/src/it/ignore-plugin-class-realm/invoker.properties b/maven-plugin-plugin/src/it/ignore-plugin-class-realm/invoker.properties index 0fd616a..5270276 100644 --- a/maven-plugin-plugin/src/it/ignore-plugin-class-realm/invoker.properties +++ b/maven-plugin-plugin/src/it/ignore-plugin-class-realm/invoker.properties @@ -1,4 +1,4 @@ -invoker.goals.1 = clean install +invoker.goals.1 = clean install -DskipTests invoker.profiles.1 = setup invoker.goals.2 = clean process-classes diff --git a/maven-plugin-plugin/src/it/ignore-plugin-class-realm/pom.xml b/maven-plugin-plugin/src/it/ignore-plugin-class-realm/pom.xml index 1d9752d..7b98666 100644 --- a/maven-plugin-plugin/src/it/ignore-plugin-class-realm/pom.xml +++ b/maven-plugin-plugin/src/it/ignore-plugin-class-realm/pom.xml @@ -24,7 +24,7 @@ under the License. org.apache.maven.its.plugin ipcr - 1.0 + 1.0-SNAPSHOT pom Aggregator diff --git a/maven-plugin-plugin/src/it/ignore-plugin-class-realm/test/pom.xml b/maven-plugin-plugin/src/it/ignore-plugin-class-realm/test/pom.xml index df1dd9e..c616620 100644 --- a/maven-plugin-plugin/src/it/ignore-plugin-class-realm/test/pom.xml +++ b/maven-plugin-plugin/src/it/ignore-plugin-class-realm/test/pom.xml @@ -25,7 +25,7 @@ under the License. org.apache.maven.its.plugin ipcr - 1.0 + 1.0-SNAPSHOT ipcr-plugin @@ -45,7 +45,7 @@ under the License. org.apache.maven.its.plugin ipcr-dep-b - 1.0 + ${project.version} @@ -58,7 +58,7 @@ under the License. org.apache.maven.its.plugin ipcr-dep-b - 1.0 + 1.0-SNAPSHOT org.apache.maven.its.plugin diff --git a/maven-plugin-plugin/src/it/java-basic-annotations/invoker.properties b/maven-plugin-plugin/src/it/java-basic-annotations/invoker.properties new file mode 100644 index 0000000..96b1dca --- /dev/null +++ b/maven-plugin-plugin/src/it/java-basic-annotations/invoker.properties @@ -0,0 +1,3 @@ +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0-SNAPSHOT:it0014 +invoker.goals.3 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0-SNAPSHOT:help \ No newline at end of file diff --git a/maven-plugin-plugin/src/it/java-basic-annotations/pom.xml b/maven-plugin-plugin/src/it/java-basic-annotations/pom.xml new file mode 100644 index 0000000..bec1a1f --- /dev/null +++ b/maven-plugin-plugin/src/it/java-basic-annotations/pom.xml @@ -0,0 +1,96 @@ + + + + + + 4.0.0 + + org.apache.maven.its.basic-java-annotations + maven-it-basic-java-annotations + 1.0-SNAPSHOT + maven-plugin + + Maven Integration Test :: basic-java-annotations + + Test plugin-plugin, which tests maven-plugin-tools-api and + maven-plugin-tools-java. This will generate a plugin descriptor from + java-based mojo sources, install the plugin, and then use it. + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.codehaus.plexus + plexus-utils + 3.0.1 + provided + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + mojo-descriptor + process-classes + + descriptor + + + + help-goal + + helpmojo + + + + + + + diff --git a/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java b/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java new file mode 100644 index 0000000..b6dc2fa --- /dev/null +++ b/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java @@ -0,0 +1,66 @@ +package org.apache.maven.plugin.coreit; + +/* + * 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 org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.IOException; + +/** + * Touches a test file. + * + */ +@Mojo( name = "it0014") +public class CoreIt0014Mojo + extends AbstractMojo +{ + + @Parameter(expression ="${project.build.directory}", required = true) + private String outputDirectory; + + public void execute() + throws MojoExecutionException + { + getLog().info( "outputDirectory = " + outputDirectory ); + + File f = new File( outputDirectory ); + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try + { + touch.createNewFile(); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error writing verification file.", e ); + } + } + +} diff --git a/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 0000000..f7c64fd --- /dev/null +++ b/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,69 @@ +package org.apache.maven.plugin.coreit; + +/* + * 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 org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; + +/** + * Touches a test file. + * + * @since 1.2 + * @deprecated Don't use! + */ +@Mojo( name = "first", requiresDependencyResolution = "test", defaultPhase = LifecyclePhase.INTEGRATION_TEST ) +@Execute( phase = LifecyclePhase.GENERATE_SOURCES, lifecycle = "cobertura" ) +public class FirstMojo + extends AbstractMojo +{ + + /** + * Project directory. + */ + @Parameter( defaultValue = "${basedir}", readonly = true ) + private File basedir; + + @Parameter( expression = "${first.touchFile}", defaultValue = "${project.build.directory}/touch.txt", + required = true ) + private File touchFile; + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( alias = "alias" ) + private String aliasedParam; + + @Component( role = "org.apache.maven.project.MavenProjectHelper", roleHint = "test" ) + private Object projectHelper; + + public void execute() + throws MojoExecutionException + { + } + +} diff --git a/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java b/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java new file mode 100644 index 0000000..8e28eba --- /dev/null +++ b/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java @@ -0,0 +1,38 @@ +package org.apache.maven.plugin.coreit; + +/* + * 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 org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Mojo; + +/** + * Does nothing special. + * + */ +@Mojo( name = "second",requiresDependencyCollection = "compile", threadSafe = true) +public class SecondMojo + extends AbstractMojo +{ + + public void execute() + { + } + +} diff --git a/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy b/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy new file mode 100644 index 0000000..ef33aa5 --- /dev/null +++ b/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy @@ -0,0 +1,78 @@ +File touchFile = new File( basedir, "target/touch.txt" ) +assert touchFile.isFile() + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first"}[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Touches a test file.' +assert mojo.deprecated.text() == "Don't use!" +assert mojo.requiresDependencyResolution.text() == 'test' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == 'integration-test' +assert mojo.executePhase.text() == 'generate-sources' +assert mojo.executeLifecycle.text() == 'cobertura' + +assert mojo.configuration.basedir[0].text() == '' +assert mojo.configuration.basedir[0].'@implementation' == 'java.io.File' +assert mojo.configuration.basedir[0].'@default-value' == '${basedir}' + +assert mojo.configuration.touchFile[0].text() == '${first.touchFile}' +assert mojo.configuration.touchFile[0].'@implementation' == 'java.io.File' +assert mojo.configuration.touchFile[0].'@default-value' == '${project.build.directory}/touch.txt' + +assert mojo.requirements.requirement.size() == 1 + +assert mojo.requirements.requirement[0].role.text() == 'org.apache.maven.project.MavenProjectHelper' +assert mojo.requirements.requirement[0].'role-hint'.text() == 'test' +assert mojo.requirements.requirement[0].'field-name'.text() == 'projectHelper' + +assert mojo.parameters.parameter.size() == 3 + +def parameter = mojo.parameters.parameter.findAll{ it.name.text() == "aliasedParam"}[0] + +assert parameter.name.text() == 'aliasedParam' +assert parameter.alias.text() == 'alias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == 'As of 0.2' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "touchFile"}[0] + +assert parameter.name.text() == 'touchFile' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "basedir"}[0] + +assert parameter.name.text() == 'basedir' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Project directory.' + +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "second"}[0] + +assert mojo.requiresDependencyCollection.text() == 'compile' +assert mojo.threadSafe.text() == 'true' + +return true; diff --git a/maven-plugin-plugin/src/it/java-basic/invoker.properties b/maven-plugin-plugin/src/it/java-basic/invoker.properties index 71c2d75..f382771 100644 --- a/maven-plugin-plugin/src/it/java-basic/invoker.properties +++ b/maven-plugin-plugin/src/it/java-basic/invoker.properties @@ -1,2 +1,3 @@ -invoker.goals.1 = install -invoker.goals.2 = org.apache.maven.its.it0013:maven-it-it0013:1.0:it0013 +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.it0013:maven-it-it0013:1.0-SNAPSHOT:it0013 + diff --git a/maven-plugin-plugin/src/it/java-basic/pom.xml b/maven-plugin-plugin/src/it/java-basic/pom.xml index 651823b..d96ea92 100644 --- a/maven-plugin-plugin/src/it/java-basic/pom.xml +++ b/maven-plugin-plugin/src/it/java-basic/pom.xml @@ -24,7 +24,7 @@ under the License. org.apache.maven.its.it0013 maven-it-it0013 - 1.0 + 1.0-SNAPSHOT maven-plugin Maven Integration Test :: it0013 diff --git a/maven-plugin-plugin/src/it/mplugin-187/invoker.properties b/maven-plugin-plugin/src/it/mplugin-187/invoker.properties index 8762f0e..1b50bea 100644 --- a/maven-plugin-plugin/src/it/mplugin-187/invoker.properties +++ b/maven-plugin-plugin/src/it/mplugin-187/invoker.properties @@ -1 +1 @@ -invoker.goals = clean plugin:report +invoker.goals = clean plugin:report -DskipTests diff --git a/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/invoker.properties b/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/invoker.properties index 88bfb6d..8a7b3cb 100644 --- a/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/invoker.properties +++ b/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/invoker.properties @@ -1 +1 @@ -invoker.goals = clean site +invoker.goals = clean site -DskipTests diff --git a/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/pom.xml b/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/pom.xml index 18b0a36..42872ac 100644 --- a/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/pom.xml +++ b/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/pom.xml @@ -1,47 +1,48 @@ - - 4.0.0 - org.apache.maven.its - jdk-default-version - 1.0-SNAPSHOT - maven-plugin - - UTF-8 - - - - org.apache.maven - maven-plugin-api - 2.0 - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - - - org.apache.maven.plugins - maven-plugin-plugin - @project.version@ - - - org.apache.maven.plugins - maven-site-plugin - @sitePluginVersion@ - - - - + + 4.0.0 + org.apache.maven.its + jdk-default-version + 1.0-SNAPSHOT + maven-plugin + + UTF-8 + + + + org.apache.maven + maven-plugin-api + 2.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + org.apache.maven.plugins + maven-site-plugin + @sitePluginVersion@ + + + + diff --git a/maven-plugin-plugin/src/it/plugin-report/invoker.properties b/maven-plugin-plugin/src/it/plugin-report/invoker.properties index 88bfb6d..8a7b3cb 100644 --- a/maven-plugin-plugin/src/it/plugin-report/invoker.properties +++ b/maven-plugin-plugin/src/it/plugin-report/invoker.properties @@ -1 +1 @@ -invoker.goals = clean site +invoker.goals = clean site -DskipTests diff --git a/maven-plugin-plugin/src/it/plugin-report/pom.xml b/maven-plugin-plugin/src/it/plugin-report/pom.xml index f8f2f29..39d180f 100644 --- a/maven-plugin-plugin/src/it/plugin-report/pom.xml +++ b/maven-plugin-plugin/src/it/plugin-report/pom.xml @@ -30,7 +30,7 @@ under the License. org.apache.maven.its plugin-report - 1.0 + 1.0-SNAPSHOT maven-plugin MPLUGIN-105 diff --git a/maven-plugin-plugin/src/it/settings.xml b/maven-plugin-plugin/src/it/settings.xml index c8f77f0..44480e3 100644 --- a/maven-plugin-plugin/src/it/settings.xml +++ b/maven-plugin-plugin/src/it/settings.xml @@ -20,6 +20,13 @@ under the License. --> + it-repo diff --git a/maven-plugin-plugin/src/it/skip/invoker.properties b/maven-plugin-plugin/src/it/skip/invoker.properties index 4c83645..06b1654 100644 --- a/maven-plugin-plugin/src/it/skip/invoker.properties +++ b/maven-plugin-plugin/src/it/skip/invoker.properties @@ -1,2 +1,2 @@ -invoker.goals = install +invoker.goals = install -DskipTests invoker.mavenOpts = -Dmaven.plugin.skip=true \ No newline at end of file diff --git a/maven-plugin-plugin/src/it/skip/pom.xml b/maven-plugin-plugin/src/it/skip/pom.xml index a54c994..40a0893 100644 --- a/maven-plugin-plugin/src/it/skip/pom.xml +++ b/maven-plugin-plugin/src/it/skip/pom.xml @@ -24,7 +24,7 @@ under the License. org.apache.maven.its.it0013 mplugin-174 - 1.0 + 1.0-SNAPSHOT maven-plugin MPLUGIN-174 diff --git a/maven-plugin-plugin/src/it/source-encoding/latin-1/pom.xml b/maven-plugin-plugin/src/it/source-encoding/latin-1/pom.xml index b9e8530..e21d6ca 100644 --- a/maven-plugin-plugin/src/it/source-encoding/latin-1/pom.xml +++ b/maven-plugin-plugin/src/it/source-encoding/latin-1/pom.xml @@ -24,7 +24,7 @@ under the License. org.apache.maven.its.plugin latin-1 - 1.0 + 1.0-SNAPSHOT maven-plugin Latin-1 @@ -49,12 +49,12 @@ under the License. org.apache.maven.plugins maven-compiler-plugin - 2.0.2 + 2.4 org.apache.maven.plugins maven-resources-plugin - 2.2 + 2.5 org.apache.maven.plugins diff --git a/maven-plugin-plugin/src/it/source-encoding/pom.xml b/maven-plugin-plugin/src/it/source-encoding/pom.xml index 4b58ca5..57cff57 100644 --- a/maven-plugin-plugin/src/it/source-encoding/pom.xml +++ b/maven-plugin-plugin/src/it/source-encoding/pom.xml @@ -24,7 +24,7 @@ under the License. org.apache.maven.its.plugin aggregator - 1.0 + 1.0-SNAPSHOT pom Aggregator diff --git a/maven-plugin-plugin/src/it/source-encoding/utf-8/pom.xml b/maven-plugin-plugin/src/it/source-encoding/utf-8/pom.xml index 4e29ebc..a8ddf7f 100644 --- a/maven-plugin-plugin/src/it/source-encoding/utf-8/pom.xml +++ b/maven-plugin-plugin/src/it/source-encoding/utf-8/pom.xml @@ -24,7 +24,7 @@ under the License. org.apache.maven.its.plugin utf-8 - 1.0 + 1.0-SNAPSHOT maven-plugin UTF-8 @@ -49,12 +49,12 @@ under the License. org.apache.maven.plugins maven-compiler-plugin - 2.0.2 + 2.4 org.apache.maven.plugins maven-resources-plugin - 2.2 + 2.5 org.apache.maven.plugins diff --git a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java index 13d1704..fc696cf 100644 --- a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java +++ b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java @@ -19,6 +19,8 @@ package org.apache.maven.plugin.plugin; * under the License. */ +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; @@ -28,12 +30,15 @@ import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; import org.apache.maven.tools.plugin.PluginToolsRequest; import org.apache.maven.tools.plugin.extractor.ExtractionException; import org.apache.maven.tools.plugin.generator.Generator; +import org.apache.maven.tools.plugin.generator.GeneratorException; import org.apache.maven.tools.plugin.scanner.MojoScanner; import org.apache.maven.tools.plugin.util.PluginUtils; import org.codehaus.plexus.util.ReaderFactory; import java.io.File; import java.io.IOException; +import java.lang.annotation.Documented; +import java.util.List; import java.util.Set; /** @@ -41,7 +46,6 @@ import java.util.Set; * * @author Jason van Zyl * @version $Id$ - * * @threadSafe */ public abstract class AbstractGeneratorMojo @@ -66,7 +70,7 @@ public abstract class AbstractGeneratorMojo /** * The file encoding of the source files. - * + * * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}" * @since 2.5 */ @@ -79,6 +83,16 @@ public abstract class AbstractGeneratorMojo */ protected String goalPrefix; + /** + * By default an exception is throw if no mojo descriptor is found. As the maven-plugin is defined in core, the + * descriptor generator mojo is bound to generate-resources phase. + * But for annotations, the compiled classes are needed, so skip error + * + * @parameter expression="${maven.plugin.skipErrorNoDescriptorsFound}" default-value="false" + * @since 3.0 + */ + protected boolean skipErrorNoDescriptorsFound; + /** * The role names of mojo extractors to use. *

@@ -90,12 +104,12 @@ public abstract class AbstractGeneratorMojo *

      *  <!-- Use all mojo extractors -->
      *  <extractors/>
-     *  
+     *
      *  <!-- Use no mojo extractors -->
      *  <extractors>
      *      <extractor/>
      *  </extractors>
-     *  
+     *
      *  <!-- Use only bsh mojo extractor -->
      *  <extractors>
      *      <extractor>bsh</extractor>
@@ -114,6 +128,36 @@ public abstract class AbstractGeneratorMojo
      */
     protected boolean skip;
 
+    /**
+     * The set of dependencies for the current project
+     *
+     * @parameter default-value = "${project.artifacts}"
+     * @required
+     * @readonly
+     * @since 3.0
+     */
+    protected Set dependencies;
+
+    /**
+     * List of Remote Repositories used by the resolver
+     *
+     * @parameter expression="${project.remoteArtifactRepositories}"
+     * @readonly
+     * @required
+     * @since 3.0
+     */
+    protected List remoteRepos;
+
+    /**
+     * Location of the local repository.
+     *
+     * @parameter expression="${localRepository}"
+     * @readonly
+     * @required
+     * @since 3.0
+     */
+    protected ArtifactRepository local;
+
     /**
      * @return the output directory where files will be generated.
      */
@@ -124,7 +168,9 @@ public abstract class AbstractGeneratorMojo
      */
     protected abstract Generator createGenerator();
 
-    /** {@inheritDoc} */
+    /**
+     * {@inheritDoc}
+     */
     public void execute()
         throws MojoExecutionException
     {
@@ -138,11 +184,11 @@ public abstract class AbstractGeneratorMojo
             return;
         }
 
-        if ( project.getArtifactId().toLowerCase().startsWith( "maven-" ) 
-            && project.getArtifactId().toLowerCase().endsWith( "-plugin" )
-            && !"org.apache.maven.plugins".equals( project.getGroupId() ) )
+        if ( project.getArtifactId().toLowerCase().startsWith( "maven-" )
+            && project.getArtifactId().toLowerCase().endsWith( "-plugin" ) && !"org.apache.maven.plugins".equals(
+            project.getGroupId() ) )
         {
-            getLog().error( "\n\nArtifact Ids of the format maven-___-plugin are reserved for \n" 
+            getLog().error( "\n\nArtifact Ids of the format maven-___-plugin are reserved for \n"
                                 + "plugins in the Group Id org.apache.maven.plugins\n"
                                 + "Please change your artifactId to the format ___-maven-plugin\n"
                                 + "In the future this error will break the build.\n\n" );
@@ -156,8 +202,8 @@ public abstract class AbstractGeneratorMojo
         else if ( !goalPrefix.equals( defaultGoalPrefix ) )
         {
             getLog().warn(
-                           "\n\nGoal prefix is specified as: '" + goalPrefix + "'. "
-                               + "Maven currently expects it to be '" + defaultGoalPrefix + "'.\n" );
+                "\n\nGoal prefix is specified as: '" + goalPrefix + "'. " + "Maven currently expects it to be '"
+                    + defaultGoalPrefix + "'.\n" );
         }
 
         mojoScanner.setActiveExtractors( extractors );
@@ -180,19 +226,23 @@ public abstract class AbstractGeneratorMojo
         if ( encoding == null || encoding.length() < 1 )
         {
             getLog().warn( "Using platform encoding (" + ReaderFactory.FILE_ENCODING
-                                  + " actually) to read mojo metadata, i.e. build is platform dependent!" );
+                               + " actually) to read mojo metadata, i.e. build is platform dependent!" );
         }
         else
         {
             getLog().info( "Using '" + encoding + "' encoding to read mojo metadata." );
         }
-        
+
         try
         {
             pluginDescriptor.setDependencies( PluginUtils.toComponentDependencies( project.getRuntimeDependencies() ) );
-            
+
             PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor );
             request.setEncoding( encoding );
+            request.setSkipErrorNoDescriptorsFound( skipErrorNoDescriptorsFound );
+            request.setDependencies( dependencies );
+            request.setLocal( this.local );
+            request.setRemoteRepos( this.remoteRepos );
 
             mojoScanner.populatePluginDescriptor( request );
 
@@ -200,7 +250,7 @@ public abstract class AbstractGeneratorMojo
 
             createGenerator().execute( getOutputDirectory(), request );
         }
-        catch ( IOException e )
+        catch ( GeneratorException e )
         {
             throw new MojoExecutionException( "Error writing plugin descriptor", e );
         }
@@ -217,7 +267,8 @@ public abstract class AbstractGeneratorMojo
         catch ( LinkageError e )
         {
             throw new MojoExecutionException( "The API of the mojo scanner is not compatible with this plugin version."
-                + " Please check the plugin dependencies configured in the POM and ensure the versions match.", e );
+                                                  + " Please check the plugin dependencies configured in the POM and ensure the versions match.",
+                                              e );
         }
     }
 
diff --git a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java
index 1bac881..ae14d31 100644
--- a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java
+++ b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java
@@ -19,20 +19,21 @@ package org.apache.maven.plugin.plugin;
  * under the License.
  */
 
-import java.io.File;
-
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.tools.plugin.generator.Generator;
 import org.apache.maven.tools.plugin.generator.PluginHelpGenerator;
+import org.codehaus.plexus.velocity.VelocityComponent;
+
+import java.io.File;
 
 /**
  * Generates a HelpMojo class.
  *
  * @author Vincent Siveton
  * @version $Id$
- * @since 2.4
  * @goal helpmojo
  * @phase generate-sources
+ * @since 2.4
  */
 public class HelpGeneratorMojo
     extends AbstractGeneratorMojo
@@ -47,7 +48,7 @@ public class HelpGeneratorMojo
     /**
      * The name of the package for the generated HelpMojo. By default, the package will be calculated based
      * on the packages of the other plugin goals.
-     * 
+     *
      * @parameter
      * @since 2.6
      */
@@ -61,19 +62,35 @@ public class HelpGeneratorMojo
      */
     private boolean useJava5;
 
-    /** {@inheritDoc} */
+    /**
+     * Velocity component.
+     *
+     * @component
+     * @readonly
+     * @required
+     */
+    private VelocityComponent velocity;
+
+    /**
+     * {@inheritDoc}
+     */
     protected File getOutputDirectory()
     {
         return outputDirectory;
     }
 
-    /** {@inheritDoc} */
+    /**
+     * {@inheritDoc}
+     */
     protected Generator createGenerator()
     {
-        return new PluginHelpGenerator().setHelpPackageName( helpPackageName ).setUseJava5( useJava5 );
+        return new PluginHelpGenerator().setHelpPackageName( helpPackageName ).setUseJava5(
+            useJava5 ).setVelocityComponent( this.velocity );
     }
 
-    /** {@inheritDoc} */
+    /**
+     * {@inheritDoc}
+     */
     public void execute()
         throws MojoExecutionException
     {
@@ -83,5 +100,7 @@ public class HelpGeneratorMojo
         {
             project.addCompileSourceRoot( outputDirectory.getAbsolutePath() );
         }
+
     }
+
 }
diff --git a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/PluginReport.java b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/PluginReport.java
index b2ee032..ec0bbf1 100644
--- a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/PluginReport.java
+++ b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/PluginReport.java
@@ -19,15 +19,6 @@ package org.apache.maven.plugin.plugin;
  * under the License.
  */
 
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.ResourceBundle;
-
 import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.siterenderer.Renderer;
 import org.apache.maven.model.Plugin;
@@ -42,21 +33,30 @@ import org.apache.maven.reporting.MavenReportException;
 import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
 import org.apache.maven.tools.plugin.PluginToolsRequest;
 import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.generator.GeneratorException;
 import org.apache.maven.tools.plugin.generator.PluginXdocGenerator;
 import org.apache.maven.tools.plugin.scanner.MojoScanner;
 import org.apache.maven.tools.plugin.util.PluginUtils;
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+
 /**
  * Generates the Plugin's documentation report.
  *
  * @author Stephane Nicoll
  * @author Vincent Siveton
  * @version $Id$
- * @since 2.0
  * @goal report
  * @execute phase="compile"
+ * @since 2.0
  */
 public class PluginReport
     extends AbstractMavenReport
@@ -91,13 +91,12 @@ public class PluginReport
      */
     protected MojoScanner mojoScanner;
 
-   /**
-    * The file encoding of the source files.
-    *
-    * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
-    *
-    * @since 2.7
-    */
+    /**
+     * The file encoding of the source files.
+     *
+     * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
+     * @since 2.7
+     */
     private String encoding;
 
 
@@ -124,10 +123,10 @@ public class PluginReport
     private Requirements requirements;
 
     /**
-     * The goal prefix that will appear before the ":". 
-     * By default, this plugin applies a heuristic to derive a heuristic from 
-     * the plugin's artifactId. 
-     * 
+     * The goal prefix that will appear before the ":".
+     * By default, this plugin applies a heuristic to derive a heuristic from
+     * the plugin's artifactId.
+     * 

* It removes any occurrences of the regular expression -?maven-?, * and then removes any occurrences of -?plugin-?. *

@@ -158,31 +157,41 @@ public class PluginReport */ private boolean skipReport; - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ protected Renderer getSiteRenderer() { return siteRenderer; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ protected String getOutputDirectory() { return outputDirectory.getPath(); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ protected MavenProject getProject() { return project; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public boolean canGenerateReport() { return "maven-plugin".equals( project.getPackaging() ); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @SuppressWarnings( "unchecked" ) protected void executeReport( Locale locale ) throws MavenReportException @@ -205,8 +214,7 @@ public class PluginReport } else { - getLog().warn( - "\n\nGoal prefix is specified as: '" + goalPrefix + "'. Maven currently expects it to be '" + getLog().warn( "\n\nGoal prefix is specified as: '" + goalPrefix + "'. Maven currently expects it to be '" + defaultGoalPrefix + "'.\n" ); } @@ -224,11 +232,11 @@ public class PluginReport try { pluginDescriptor.setDependencies( PluginUtils.toComponentDependencies( project.getRuntimeDependencies() ) ); - + PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor ); request.setEncoding( encoding ); - try + try { mojoScanner.populatePluginDescriptor( request ); } @@ -243,11 +251,11 @@ public class PluginReport generatePluginDocumentation( pluginDescriptor, locale ); // Write the overview - PluginOverviewRenderer r = new PluginOverviewRenderer( project, requirements, getSink(), pluginDescriptor, - locale ); + PluginOverviewRenderer r = + new PluginOverviewRenderer( project, requirements, getSink(), pluginDescriptor, locale ); r.render(); } - + catch ( ExtractionException e ) { throw new MavenReportException( "Error extracting plugin descriptor: \'" + e.getLocalizedMessage() + "\'", @@ -255,19 +263,25 @@ public class PluginReport } } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getDescription( Locale locale ) { return getBundle( locale ).getString( "report.plugin.description" ); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getName( Locale locale ) { return getBundle( locale ).getString( "report.plugin.name" ); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getOutputName() { return "plugin-info"; @@ -275,7 +289,7 @@ public class PluginReport /** * @param pluginDescriptor not null - * @param locale not null + * @param locale not null * @throws MavenReportException if any */ private void generatePluginDocumentation( PluginDescriptor pluginDescriptor, Locale locale ) @@ -287,9 +301,10 @@ public class PluginReport outputDir.mkdirs(); PluginXdocGenerator generator = new PluginXdocGenerator( project, locale ); - generator.execute( outputDir, pluginDescriptor ); + PluginToolsRequest pluginToolsRequest = new DefaultPluginToolsRequest( project, pluginDescriptor ); + generator.execute( outputDir, pluginToolsRequest ); } - catch ( IOException e ) + catch ( GeneratorException e ) { throw new MavenReportException( "Error writing plugin documentation", e ); } @@ -321,11 +336,11 @@ public class PluginReport private final Locale locale; /** - * @param project not null - * @param requirements not null - * @param sink not null + * @param project not null + * @param requirements not null + * @param sink not null * @param pluginDescriptor not null - * @param locale not null + * @param locale not null */ public PluginOverviewRenderer( MavenProject project, Requirements requirements, Sink sink, PluginDescriptor pluginDescriptor, Locale locale ) @@ -341,13 +356,17 @@ public class PluginReport this.locale = locale; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getTitle() { return getBundle( locale ).getString( "report.plugin.title" ); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @SuppressWarnings( { "unchecked", "rawtypes" } ) public void renderBody() { @@ -362,7 +381,6 @@ public class PluginReport paragraph( getBundle( locale ).getString( "report.plugin.goals.intro" ) ); - boolean hasMavenReport = false; for ( Iterator i = pluginDescriptor.getMojos().iterator(); i.hasNext(); ) { @@ -381,11 +399,11 @@ public class PluginReport String descriptionColumnName = getBundle( locale ).getString( "report.plugin.goals.column.description" ); if ( hasMavenReport ) { - tableHeader( new String[] { goalColumnName, isMavenReport, descriptionColumnName } ); + tableHeader( new String[]{ goalColumnName, isMavenReport, descriptionColumnName } ); } else { - tableHeader( new String[] { goalColumnName, descriptionColumnName } ); + tableHeader( new String[]{ goalColumnName, descriptionColumnName } ); } List mojos = new ArrayList(); @@ -449,15 +467,16 @@ public class PluginReport String maven = discoverMavenRequirement( project, requirements ); sink.tableRow(); tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.maven" ) ); - tableCell( ( maven != null ? maven : getBundle( locale ) - .getString( "report.plugin.systemrequirements.nominimum" ) ) ); + tableCell( ( maven != null + ? maven + : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) ); sink.tableRow_(); String jdk = discoverJdkRequirement( project, requirements ); sink.tableRow(); tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.jdk" ) ); - tableCell( ( jdk != null ? jdk : getBundle( locale ) - .getString( "report.plugin.systemrequirements.nominimum" ) ) ); + tableCell( + ( jdk != null ? jdk : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) ); sink.tableRow_(); sink.tableRow(); @@ -482,9 +501,9 @@ public class PluginReport sink.tableRow(); tableCell( key ); - tableCell( ( StringUtils.isNotEmpty( requirements.getOthers().getProperty( key ) ) ? requirements - .getOthers().getProperty( key ) : getBundle( locale ) - .getString( "report.plugin.systemrequirements.nominimum" ) ) ); + tableCell( ( StringUtils.isNotEmpty( requirements.getOthers().getProperty( key ) ) + ? requirements.getOthers().getProperty( key ) + : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) ); sink.tableRow_(); } } @@ -515,31 +534,32 @@ public class PluginReport sb.append( "" ).append( '\n' ); sb.append( " ..." ).append( '\n' ); sb.append( " " ).append( '\n' ); - sb.append( " " ) - .append( '\n' ); + sb.append( + " " ).append( + '\n' ); sb.append( " " ).append( '\n' ); sb.append( " " ).append( '\n' ); sb.append( " " ).append( '\n' ); - sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( "" ) - .append( '\n' ); - sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append( "" ) - .append( '\n' ); - sb.append( " " ).append( pluginDescriptor.getVersion() ).append( "" ) - .append( '\n' ); + sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( "" ).append( + '\n' ); + sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append( + "" ).append( '\n' ); + sb.append( " " ).append( pluginDescriptor.getVersion() ).append( "" ).append( + '\n' ); sb.append( " " ).append( '\n' ); sb.append( " ..." ).append( '\n' ); sb.append( " " ).append( '\n' ); sb.append( " " ).append( '\n' ); - sb.append( " " ) - .append( '\n' ); + sb.append( " " ).append( + '\n' ); sb.append( " " ).append( '\n' ); sb.append( " " ).append( '\n' ); - sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( "" ) - .append( '\n' ); - sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append( "" ) - .append( '\n' ); - sb.append( " " ).append( pluginDescriptor.getVersion() ).append( "" ) - .append( '\n' ); + sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( "" ).append( + '\n' ); + sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append( + "" ).append( '\n' ); + sb.append( " " ).append( pluginDescriptor.getVersion() ).append( "" ).append( + '\n' ); sb.append( " " ).append( '\n' ); sb.append( " ..." ).append( '\n' ); sb.append( " " ).append( '\n' ); @@ -548,17 +568,18 @@ public class PluginReport if ( hasMavenReport ) { sb.append( " ..." ).append( '\n' ); - sb.append( " " ) - .append( '\n' ); + sb.append( + " " ).append( + '\n' ); sb.append( " " ).append( '\n' ); sb.append( " " ).append( '\n' ); sb.append( " " ).append( '\n' ); - sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( "" ) - .append( '\n' ); - sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append( "" ) - .append( '\n' ); - sb.append( " " ).append( pluginDescriptor.getVersion() ).append( "" ) - .append( '\n' ); + sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( "" ).append( + '\n' ); + sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append( + "" ).append( '\n' ); + sb.append( " " ).append( pluginDescriptor.getVersion() ).append( "" ).append( + '\n' ); sb.append( " " ).append( '\n' ); sb.append( " ..." ).append( '\n' ); sb.append( " " ).append( '\n' ); @@ -581,7 +602,7 @@ public class PluginReport * Try to lookup on the Maven prerequisites property. * If not specified, uses the value defined by the user. * - * @param project not null + * @param project not null * @param requirements not null * @return the Maven version */ @@ -606,7 +627,7 @@ public class PluginReport * If not specified, uses the value defined by the user. * If not specified, uses the value of the system property java.specification.version. * - * @param project not null + * @param project not null * @param requirements not null * @return the JDK version */ @@ -686,11 +707,11 @@ public class PluginReport jdk = pluginConf.getChild( "target" ).getValue(); } - if ( jdk == null ) + if ( jdk == null ) { return backupJdk; } - else + else { return jdk; } diff --git a/maven-plugin-tools-annotations/pom.xml b/maven-plugin-tools-annotations/pom.xml new file mode 100644 index 0000000..bef9e8a --- /dev/null +++ b/maven-plugin-tools-annotations/pom.xml @@ -0,0 +1,125 @@ + + + + 4.0.0 + + org.apache.maven.plugin-tools + maven-plugin-tools + 3.0-SNAPSHOT + + + maven-plugin-tools-annotations + + Maven Plugin Tools Annotations + + + + + + org.apache.maven + maven-project + + + org.apache.maven + maven-model + + + org.apache.maven + maven-plugin-descriptor + + + org.apache.maven.plugin-tools + maven-plugin-tools-api + + + org.apache.maven.plugin-tools + maven-plugin-annotations + + + + org.codehaus.plexus + plexus-utils + + + org.codehaus.plexus + plexus-container-default + + + asm + asm + + + asm + asm-commons + + + + org.codehaus.plexus + plexus-archiver + + + + com.thoughtworks.qdox + qdox + + + + org.codehaus.plexus + plexus-compiler-manager + 1.8.6 + + + org.codehaus.plexus + plexus-component-api + + + test + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + org.apache.maven.plugins + maven-source-plugin + + + + test-jar-no-fork + + + + + + + + diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/JavaAnnotationsMojoDescriptorExtractor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/JavaAnnotationsMojoDescriptorExtractor.java new file mode 100644 index 0000000..e24eb5e --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/JavaAnnotationsMojoDescriptorExtractor.java @@ -0,0 +1,647 @@ +package org.apache.maven.tools.plugin.annotations; +/* + * 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 com.thoughtworks.qdox.JavaDocBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.plugin.descriptor.DuplicateParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.annotations.datamodel.ComponentAnnotationContent; +import org.apache.maven.tools.plugin.annotations.datamodel.ExecuteAnnotationContent; +import org.apache.maven.tools.plugin.annotations.datamodel.MojoAnnotationContent; +import org.apache.maven.tools.plugin.annotations.datamodel.ParameterAnnotationContent; +import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotatedClass; +import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner; +import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScannerRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.codehaus.plexus.archiver.UnArchiver; +import org.codehaus.plexus.archiver.manager.ArchiverManager; +import org.codehaus.plexus.archiver.manager.NoSuchArchiverException; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class JavaAnnotationsMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor +{ + + /** + * @requirement + */ + private MojoAnnotationsScanner mojoAnnotationsScanner; + + /** + * @requirement + */ + private ArtifactResolver artifactResolver; + + /** + * @requirement + */ + private ArtifactFactory artifactFactory; + + /** + * @requirement + */ + private ArchiverManager archiverManager; + + public List execute( MavenProject project, PluginDescriptor pluginDescriptor ) + throws ExtractionException, InvalidPluginDescriptorException + { + return execute( new DefaultPluginToolsRequest( project, pluginDescriptor ) ); + } + + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + + MojoAnnotationsScannerRequest mojoAnnotationsScannerRequest = new MojoAnnotationsScannerRequest(); + + mojoAnnotationsScannerRequest.setClassesDirectories( + Arrays.asList( new File( request.getProject().getBuild().getOutputDirectory() ) ) ); + + mojoAnnotationsScannerRequest.setDependencies( request.getDependencies() ); + + mojoAnnotationsScannerRequest.setProject( request.getProject() ); + + Map mojoAnnotatedClasses = + mojoAnnotationsScanner.scan( mojoAnnotationsScannerRequest ); + + // found artifact from reactors to scan sources + // we currently only scan sources from reactors + List mavenProjects = new ArrayList(); + + // if we need to scan sources from external artifacts + Set externalArtifacts = new HashSet(); + + for ( MojoAnnotatedClass mojoAnnotatedClass : mojoAnnotatedClasses.values() ) + { + if ( !StringUtils.equals( mojoAnnotatedClass.getArtifact().getArtifactId(), + request.getProject().getArtifact().getArtifactId() ) ) + { + MavenProject mavenProject = + getFromProjectReferences( mojoAnnotatedClass.getArtifact(), request.getProject() ); + if ( mavenProject != null ) + { + mavenProjects.add( mavenProject ); + } + else + { + externalArtifacts.add( mojoAnnotatedClass.getArtifact() ); + } + } + } + + Map javaClassesMap = new HashMap(); + + // try to get artifact with classifier sources + // extract somewhere then scan doclet for @since, @deprecated + for ( Artifact artifact : externalArtifacts ) + { + // parameter for test-sources too ?? olamy I need that for it test only + if ( StringUtils.equalsIgnoreCase( "tests", artifact.getClassifier() ) ) + { + javaClassesMap.putAll( discoverClassesFromSourcesJar( artifact, request, "test-sources" ) ); + } + else + { + javaClassesMap.putAll( discoverClassesFromSourcesJar( artifact, request, "sources" ) ); + } + + } + + for ( MavenProject mavenProject : mavenProjects ) + { + javaClassesMap.putAll( discoverClasses( request.getEncoding(), mavenProject ) ); + } + + javaClassesMap.putAll( discoverClasses( request ) ); + + populateDataFromJavadoc( mojoAnnotatedClasses, javaClassesMap ); + + return toMojoDescriptors( mojoAnnotatedClasses, request, javaClassesMap ); + + } + + + protected Map discoverClassesFromSourcesJar( Artifact artifact, PluginToolsRequest request, + String classifier ) + throws ExtractionException + { + try + { + Artifact sourcesArtifact = + artifactFactory.createArtifactWithClassifier( artifact.getGroupId(), artifact.getArtifactId(), + artifact.getVersion(), artifact.getType(), classifier ); + + artifactResolver.resolve( sourcesArtifact, request.getRemoteRepos(), request.getLocal() ); + if ( sourcesArtifact.getFile() != null && sourcesArtifact.getFile().exists() ) + { + File extractDirectory = new File( request.getProject().getBuild().getDirectory(), + "maven-plugin-plugin-sources/" + sourcesArtifact.getGroupId() + "/" + + sourcesArtifact.getArtifactId() + "/" + + sourcesArtifact.getVersion() + "/" + + sourcesArtifact.getClassifier() ); + if ( !extractDirectory.exists() ) + { + extractDirectory.mkdirs(); + } + // extract sources in a directory + //target/maven-plugin-plugin/${groupId}/${artifact}/sources + UnArchiver unArchiver = archiverManager.getUnArchiver( "jar" ); + unArchiver.setSourceFile( sourcesArtifact.getFile() ); + unArchiver.setDestDirectory( extractDirectory ); + unArchiver.extract(); + + return discoverClasses( request.getEncoding(), Arrays.asList( extractDirectory ) ); + } + } + catch ( ArtifactResolutionException e ) + { + throw new ExtractionException( e.getMessage(), e ); + } + catch ( ArtifactNotFoundException e ) + { + //throw new ExtractionException( e.getMessage(), e ); + getLogger().debug( "skip ArtifactNotFoundException:" + e.getMessage() ); + getLogger().warn( + "Impossible to get sources artifact for " + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + + artifact.getVersion() + ". Some javadoc tags (@since, @deprecated and comments) won't be used" ); + } + catch ( NoSuchArchiverException e ) + { + throw new ExtractionException( e.getMessage(), e ); + } + return Collections.emptyMap(); + } + + /** + * from sources scan to get @since and @deprecated and description of classes and fields. + * + * @param mojoAnnotatedClasses + * @param javaClassesMap + */ + protected void populateDataFromJavadoc( Map mojoAnnotatedClasses, + Map javaClassesMap ) + { + + for ( Map.Entry entry : mojoAnnotatedClasses.entrySet() ) + { + JavaClass javaClass = javaClassesMap.get( entry.getKey() ); + if ( javaClass != null ) + { + MojoAnnotationContent mojoAnnotationContent = entry.getValue().getMojo(); + if ( mojoAnnotationContent != null ) + { + mojoAnnotationContent.setDescription( javaClass.getComment() ); + DocletTag since = findInClassHierarchy( javaClass, "since" ); + if ( since != null ) + { + mojoAnnotationContent.setSince( since.getValue() ); + } + + DocletTag deprecated = findInClassHierarchy( javaClass, "deprecated" ); + if ( deprecated != null ) + { + mojoAnnotationContent.setDeprecated( deprecated.getValue() ); + } + } + Map fieldsMap = + extractFieldParameterTags( javaClass, javaClassesMap, mojoAnnotatedClasses ); + Map parameters = + getParametersParentHierarchy( entry.getValue(), new HashMap(), + mojoAnnotatedClasses ); + for ( Map.Entry parameter : new TreeMap( + parameters ).entrySet() ) + { + JavaField javaField = fieldsMap.get( parameter.getKey() ); + if ( javaField != null ) + { + ParameterAnnotationContent parameterAnnotationContent = parameter.getValue(); + DocletTag deprecated = javaField.getTagByName( "deprecated" ); + if ( deprecated != null ) + { + parameterAnnotationContent.setDeprecated( deprecated.getValue() ); + } + DocletTag since = javaField.getTagByName( "since" ); + if ( since != null ) + { + parameterAnnotationContent.setSince( since.getValue() ); + } + parameterAnnotationContent.setDescription( javaField.getComment() ); + } + } + + for ( Map.Entry component : entry.getValue().getComponents().entrySet() ) + { + JavaField javaField = fieldsMap.get( component.getKey() ); + if ( javaField != null ) + { + ComponentAnnotationContent componentAnnotationContent = component.getValue(); + DocletTag deprecated = javaField.getTagByName( "deprecated" ); + if ( deprecated != null ) + { + componentAnnotationContent.setDeprecated( deprecated.getValue() ); + } + DocletTag since = javaField.getTagByName( "since" ); + if ( since != null ) + { + componentAnnotationContent.setSince( since.getValue() ); + } + componentAnnotationContent.setDescription( javaField.getComment() ); + } + } + + } + } + + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass, + Map javaClassesMap, + Map mojoAnnotatedClasses ) + { + Map rawParams = new TreeMap(); + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + if ( superClass.getFields().length > 0 ) + { + rawParams = extractFieldParameterTags( superClass, javaClassesMap, mojoAnnotatedClasses ); + } + // maybe sources comes from scan of sources artifact + superClass = javaClassesMap.get( superClass.getFullyQualifiedName() ); + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass, javaClassesMap, mojoAnnotatedClasses ); + } + } + else + { + + rawParams = new TreeMap(); + } + + JavaField[] classFields = javaClass.getFields(); + + if ( classFields != null ) + { + for ( JavaField field : classFields ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + protected Map discoverClasses( final PluginToolsRequest request ) + { + return discoverClasses( request.getEncoding(), request.getProject() ); + } + + protected Map discoverClasses( final String encoding, final MavenProject project ) + { + List sources = new ArrayList(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + sources.add( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) + && generatedPlugin.exists() ) + { + sources.add( generatedPlugin ); + } + + return discoverClasses( encoding, sources ); + } + + protected Map discoverClasses( final String encoding, List sourceDirectories ) + { + JavaDocBuilder builder = new JavaDocBuilder(); + builder.setEncoding( encoding ); + + for ( File source : sourceDirectories ) + { + builder.addSourceTree( source ); + } + + JavaClass[] javaClasses = builder.getClasses(); + + if ( javaClasses == null || javaClasses.length < 1 ) + { + return Collections.emptyMap(); + } + + Map javaClassMap = new HashMap( javaClasses.length ); + + for ( JavaClass javaClass : javaClasses ) + { + javaClassMap.put( javaClass.getFullyQualifiedName(), javaClass ); + } + + return javaClassMap; + } + + private List toMojoDescriptors( Map mojoAnnotatedClasses, + PluginToolsRequest request, Map javaClassesMap ) + throws DuplicateParameterException + { + List mojoDescriptors = new ArrayList( mojoAnnotatedClasses.size() ); + for ( MojoAnnotatedClass mojoAnnotatedClass : mojoAnnotatedClasses.values() ) + { + // no mojo so skip it + if ( mojoAnnotatedClass.getMojo() == null ) + { + continue; + } + + ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor(); + + //mojoDescriptor.setRole( mojoAnnotatedClass.getClassName() ); + //mojoDescriptor.setRoleHint( "default" ); + mojoDescriptor.setImplementation( mojoAnnotatedClass.getClassName() ); + mojoDescriptor.setLanguage( "java" ); + + MojoAnnotationContent mojo = mojoAnnotatedClass.getMojo(); + + mojoDescriptor.setDescription( mojo.getDescription() ); + mojoDescriptor.setSince( mojo.getSince() ); + mojo.setDeprecated( mojo.getDeprecated() ); + + mojoDescriptor.setAggregator( mojo.aggregator() ); + mojoDescriptor.setDependencyResolutionRequired( mojo.requiresDependencyResolution() ); + mojoDescriptor.setDependencyCollectionRequired( mojo.requiresDependencyCollection() ); + + mojoDescriptor.setDirectInvocationOnly( mojo.requiresDirectInvocation() ); + mojoDescriptor.setDeprecated( mojo.getDeprecated() ); + mojoDescriptor.setThreadSafe( mojo.threadSafe() ); + + ExecuteAnnotationContent execute = findExecuteInParentHierarchy( mojoAnnotatedClass, mojoAnnotatedClasses ); + if ( execute != null ) + { + mojoDescriptor.setExecuteGoal( execute.goal() ); + mojoDescriptor.setExecuteLifecycle( execute.lifecycle() ); + mojoDescriptor.setExecutePhase( execute.phase().id() ); + } + + mojoDescriptor.setExecutionStrategy( mojo.executionStrategy() ); + // ??? + //mojoDescriptor.alwaysExecute(mojo.a) + + mojoDescriptor.setGoal( mojo.name() ); + mojoDescriptor.setOnlineRequired( mojo.requiresOnline() ); + + mojoDescriptor.setPhase( mojo.defaultPhase().id() ); + + Map parameters = + getParametersParentHierarchy( mojoAnnotatedClass, new HashMap(), + mojoAnnotatedClasses ); + + for ( ParameterAnnotationContent parameterAnnotationContent : new TreeSet( + parameters.values() ) ) + { + org.apache.maven.plugin.descriptor.Parameter parameter = + new org.apache.maven.plugin.descriptor.Parameter(); + parameter.setName( parameterAnnotationContent.getFieldName() ); + parameter.setAlias( parameterAnnotationContent.alias() ); + parameter.setDefaultValue( parameterAnnotationContent.defaultValue() ); + parameter.setDeprecated( parameterAnnotationContent.getDeprecated() ); + parameter.setDescription( parameterAnnotationContent.getDescription() ); + parameter.setEditable( !parameterAnnotationContent.readonly() ); + parameter.setExpression( parameterAnnotationContent.expression() ); + parameter.setType( parameterAnnotationContent.getClassName() ); + parameter.setSince( parameterAnnotationContent.getSince() ); + parameter.setRequired( parameterAnnotationContent.required() ); + + mojoDescriptor.addParameter( parameter ); + } + + Map components = + getComponentsParentHierarchy( mojoAnnotatedClass, new HashMap(), + mojoAnnotatedClasses ); + + for ( ComponentAnnotationContent componentAnnotationContent : new TreeSet( + components.values() ) ) + { + org.apache.maven.plugin.descriptor.Parameter parameter = + new org.apache.maven.plugin.descriptor.Parameter(); + parameter.setName( componentAnnotationContent.getFieldName() ); + parameter.setRequirement( + new Requirement( componentAnnotationContent.role(), componentAnnotationContent.roleHint() ) ); + parameter.setEditable( false ); + parameter.setDeprecated( componentAnnotationContent.getDeprecated() ); + parameter.setSince( componentAnnotationContent.getSince() ); + mojoDescriptor.addParameter( parameter ); + } + + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + mojoDescriptors.add( mojoDescriptor ); + } + return mojoDescriptors; + } + + + protected ExecuteAnnotationContent findExecuteInParentHierarchy( MojoAnnotatedClass mojoAnnotatedClass, + Map mojoAnnotatedClasses ) + { + + if ( mojoAnnotatedClass.getExecute() != null ) + { + return mojoAnnotatedClass.getExecute(); + } + String parentClassName = mojoAnnotatedClass.getParentClassName(); + if ( StringUtils.isEmpty( parentClassName ) ) + { + return null; + } + MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName ); + if ( parent == null ) + { + return null; + } + return findExecuteInParentHierarchy( parent, mojoAnnotatedClasses ); + } + + + protected Map getParametersParentHierarchy( + MojoAnnotatedClass mojoAnnotatedClass, Map parameters, + Map mojoAnnotatedClasses ) + { + List parameterAnnotationContents = new ArrayList(); + + parameterAnnotationContents = + getParametersParent( mojoAnnotatedClass, parameterAnnotationContents, mojoAnnotatedClasses ); + + // move to parent first to build the Map + Collections.reverse( parameterAnnotationContents ); + + Map map = + new HashMap( parameterAnnotationContents.size() ); + + for ( ParameterAnnotationContent parameterAnnotationContent : parameterAnnotationContents ) + { + map.put( parameterAnnotationContent.getFieldName(), parameterAnnotationContent ); + } + return map; + } + + protected List getParametersParent( MojoAnnotatedClass mojoAnnotatedClass, + List parameterAnnotationContents, + Map mojoAnnotatedClasses ) + { + parameterAnnotationContents.addAll( mojoAnnotatedClass.getParameters().values() ); + String parentClassName = mojoAnnotatedClass.getParentClassName(); + if ( parentClassName != null ) + { + MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName ); + if ( parent != null ) + { + return getParametersParent( parent, parameterAnnotationContents, mojoAnnotatedClasses ); + } + } + return parameterAnnotationContents; + } + + + protected Map getComponentsParentHierarchy( + MojoAnnotatedClass mojoAnnotatedClass, Map components, + Map mojoAnnotatedClasses ) + { + List componentAnnotationContents = new ArrayList(); + + componentAnnotationContents = + getComponentParent( mojoAnnotatedClass, componentAnnotationContents, mojoAnnotatedClasses ); + + // move to parent first to build the Map + Collections.reverse( componentAnnotationContents ); + + Map map = + new HashMap( componentAnnotationContents.size() ); + + for ( ComponentAnnotationContent componentAnnotationContent : componentAnnotationContents ) + { + map.put( componentAnnotationContent.getFieldName(), componentAnnotationContent ); + } + return map; + } + + protected List getComponentParent( MojoAnnotatedClass mojoAnnotatedClass, + List componentAnnotationContents, + Map mojoAnnotatedClasses ) + { + componentAnnotationContents.addAll( mojoAnnotatedClass.getComponents().values() ); + String parentClassName = mojoAnnotatedClass.getParentClassName(); + if ( parentClassName != null ) + { + MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName ); + if ( parent != null ) + { + return getComponentParent( parent, componentAnnotationContents, mojoAnnotatedClasses ); + } + } + return componentAnnotationContents; + } + + protected MavenProject getFromProjectReferences( Artifact artifact, MavenProject project ) + { + if ( project.getProjectReferences() == null || project.getProjectReferences().isEmpty() ) + { + return null; + } + Collection mavenProjects = project.getProjectReferences().values(); + for ( MavenProject mavenProject : mavenProjects ) + { + if ( StringUtils.equals( mavenProject.getId(), artifact.getId() ) ) + { + return mavenProject; + } + } + return null; + } + +} diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/AnnotatedContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/AnnotatedContent.java new file mode 100644 index 0000000..3869117 --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/AnnotatedContent.java @@ -0,0 +1,66 @@ +package org.apache.maven.tools.plugin.annotations.datamodel; +/* + * 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 org.apache.maven.artifact.Artifact; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class AnnotatedContent +{ + + private String description; + + private String since; + + private String deprecated; + + public String getDescription() + { + return description; + } + + public void setDescription( String description ) + { + this.description = description; + } + + public String getSince() + { + return since; + } + + public void setSince( String since ) + { + this.since = since; + } + + public String getDeprecated() + { + return deprecated; + } + + public void setDeprecated( String deprecated ) + { + this.deprecated = deprecated; + } + +} diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/AnnotatedField.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/AnnotatedField.java new file mode 100644 index 0000000..ec69326 --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/AnnotatedField.java @@ -0,0 +1,60 @@ +package org.apache.maven.tools.plugin.annotations.datamodel; +/* + * 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. + */ + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class AnnotatedField + extends AnnotatedContent + implements Comparable +{ + private String fieldName; + + public AnnotatedField( String fieldName ) + { + this.fieldName = fieldName; + } + + public String getFieldName() + { + return fieldName; + } + + public void setFieldName( String name ) + { + this.fieldName = name; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( "AnnotatedField" ); + sb.append( "{fieldName='" ).append( fieldName ).append( '\'' ); + sb.append( '}' ); + return sb.toString(); + } + + public int compareTo( AnnotatedField annotatedField ) + { + return getFieldName().compareTo( annotatedField.getFieldName() ); + } +} diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ComponentAnnotationContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ComponentAnnotationContent.java new file mode 100644 index 0000000..5fee961 --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ComponentAnnotationContent.java @@ -0,0 +1,86 @@ +package org.apache.maven.tools.plugin.annotations.datamodel; +/* + * 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 org.apache.maven.plugins.annotations.Component; + +import java.lang.annotation.Annotation; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class ComponentAnnotationContent + extends AnnotatedField + implements Component +{ + private String role; + + private String roleHint; + + public ComponentAnnotationContent( String fieldName ) + { + super( fieldName ); + } + + public ComponentAnnotationContent( String fieldName, String role, String roleHint ) + { + this( fieldName ); + this.role = role; + this.roleHint = roleHint; + } + + public String role() + { + return role == null ? "" : role; + } + + public void role( String role ) + { + this.role = role; + } + + public String roleHint() + { + return roleHint == null ? "" : roleHint; + } + + public void roleHint( String roleHint ) + { + this.roleHint = roleHint; + } + + public Class annotationType() + { + return null; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( super.toString() ); + sb.append( "ComponentAnnotationContent" ); + sb.append( "{role='" ).append( role ).append( '\'' ); + sb.append( ", roleHint='" ).append( roleHint ).append( '\'' ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ExecuteAnnotationContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ExecuteAnnotationContent.java new file mode 100644 index 0000000..c680f3b --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ExecuteAnnotationContent.java @@ -0,0 +1,87 @@ +package org.apache.maven.tools.plugin.annotations.datamodel; +/* + * 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 org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; + +import java.lang.annotation.Annotation; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class ExecuteAnnotationContent + implements Execute +{ + private String goal; + + private String lifecycle; + + private LifecyclePhase phase; + + public LifecyclePhase phase() + { + return this.phase; + } + + public String goal() + { + return this.goal; + } + + public String lifecycle() + { + return this.lifecycle; + } + + + public void phase( String phase ) + { + this.phase = LifecyclePhase.valueOf( phase ); + } + + public void goal( String goal ) + { + this.goal = goal; + } + + public void lifecycle( String lifecycle ) + { + this.lifecycle = lifecycle; + } + + + public Class annotationType() + { + return null; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( "ExecuteAnnotationContent" ); + sb.append( "{goal='" ).append( goal ).append( '\'' ); + sb.append( ", lifecycle='" ).append( lifecycle ).append( '\'' ); + sb.append( ", phase=" ).append( phase ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/MojoAnnotationContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/MojoAnnotationContent.java new file mode 100644 index 0000000..ea70331 --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/MojoAnnotationContent.java @@ -0,0 +1,229 @@ +package org.apache.maven.tools.plugin.annotations.datamodel; +/* + * 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 org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; + +import java.lang.annotation.Annotation; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class MojoAnnotationContent + extends AnnotatedContent + implements Mojo +{ + private String name; + + private LifecyclePhase defaultPhase = LifecyclePhase.NONE; + + private String requiresDependencyResolution = "runtime"; + + private String requiresDependencyCollection; + + private String instantiationStrategy = "per-lookup"; + + private String executionStrategy = "once-per-session"; + + private boolean requiresProject = true; + + private boolean requiresReports = false; + + private boolean aggregator = false; + + private boolean requiresDirectInvocation = false; + + private boolean requiresOnline = false; + + private boolean inheritByDefault = true; + + private String configurator; + + private boolean threadSafe = false; + + public Class annotationType() + { + return null; + } + + public LifecyclePhase defaultPhase() + { + return defaultPhase; + } + + public void defaultPhase( String phase ) + { + this.defaultPhase = LifecyclePhase.valueOf( phase ); + } + + public String requiresDependencyResolution() + { + return requiresDependencyResolution; + } + + public void requiresDependencyResolution( String requiresDependencyResolution ) + { + this.requiresDependencyResolution = requiresDependencyResolution; + } + + public String requiresDependencyCollection() + { + return requiresDependencyCollection == null ? "" : requiresDependencyCollection; + } + + public void requiresDependencyCollection( String requiresDependencyCollection ) + { + this.requiresDependencyCollection = requiresDependencyCollection; + } + + public String instantiationStrategy() + { + return instantiationStrategy; + } + + public void instantiationStrategy( String instantiationStrategy ) + { + this.instantiationStrategy = instantiationStrategy; + } + + public String executionStrategy() + { + return executionStrategy; + } + + public void executionStrategy( String executionStrategy ) + { + this.executionStrategy = executionStrategy; + } + + public boolean requiresProject() + { + return requiresProject; + } + + public void requiresProject( boolean requiresProject ) + { + this.requiresProject = requiresProject; + } + + public boolean requiresReports() + { + return requiresReports; + } + + public void requiresReports( boolean requiresReports ) + { + this.requiresReports = requiresReports; + } + + public boolean aggregator() + { + return aggregator; + } + + public void aggregator( boolean aggregator ) + { + this.aggregator = aggregator; + } + + public boolean requiresDirectInvocation() + { + return requiresDirectInvocation; + } + + public void requiresDirectInvocation( boolean requiresDirectInvocation ) + { + this.requiresDirectInvocation = requiresDirectInvocation; + } + + public boolean requiresOnline() + { + return requiresOnline; + } + + public void requiresOnline( boolean requiresOnline ) + { + this.requiresOnline = requiresOnline; + } + + public boolean inheritByDefault() + { + return inheritByDefault; + } + + public void inheritByDefault( boolean inheritByDefault ) + { + this.inheritByDefault = inheritByDefault; + } + + public String configurator() + { + return configurator; + } + + public void configurator( String configurator ) + { + this.configurator = configurator; + } + + public boolean threadSafe() + { + return threadSafe; + } + + public void threadSafe( boolean threadSafe ) + { + this.threadSafe = threadSafe; + } + + public String name() + { + return this.name; + } + + public void name( String name ) + { + this.name = name; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( "MojoAnnotationContent" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", defaultPhase=" ).append( defaultPhase ); + sb.append( ", requiresDependencyResolution='" ).append( requiresDependencyResolution ).append( '\'' ); + sb.append( ", requiresDependencyCollection='" ).append( requiresDependencyCollection ).append( '\'' ); + sb.append( ", instantiationStrategy='" ).append( instantiationStrategy ).append( '\'' ); + sb.append( ", executionStrategy='" ).append( executionStrategy ).append( '\'' ); + sb.append( ", requiresProject=" ).append( requiresProject ); + sb.append( ", requiresReports=" ).append( requiresReports ); + sb.append( ", aggregator=" ).append( aggregator ); + sb.append( ", requiresDirectInvocation=" ).append( requiresDirectInvocation ); + sb.append( ", requiresOnline=" ).append( requiresOnline ); + sb.append( ", inheritByDefault=" ).append( inheritByDefault ); + sb.append( ", configurator='" ).append( configurator ).append( '\'' ); + sb.append( ", threadSafe=" ).append( threadSafe ); + sb.append( '}' ); + return sb.toString(); + } +} \ No newline at end of file diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ParameterAnnotationContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ParameterAnnotationContent.java new file mode 100644 index 0000000..82a82bd --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ParameterAnnotationContent.java @@ -0,0 +1,198 @@ +package org.apache.maven.tools.plugin.annotations.datamodel; +/* + * 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 org.apache.maven.plugins.annotations.Parameter; + +import java.lang.annotation.Annotation; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class ParameterAnnotationContent + extends AnnotatedField + implements Parameter +{ + + private String alias; + + private String expression; + + private String defaultValue; + + private boolean required = false; + + private boolean readonly = false; + + private String className; + + public ParameterAnnotationContent( String fieldName, String className ) + { + super( fieldName ); + this.className = className; + } + + public ParameterAnnotationContent( String fieldName, String alias, String expression, String defaultValue, + boolean required, boolean readonly, String className ) + { + this( fieldName, className ); + this.alias = alias; + this.expression = expression; + this.defaultValue = defaultValue; + this.required = required; + this.readonly = readonly; + } + + public String alias() + { + return alias; + } + + public void alias( String alias ) + { + this.alias = alias; + } + + public String expression() + { + return expression; + } + + public void expression( String expression ) + { + this.expression = expression; + } + + public String defaultValue() + { + return defaultValue; + } + + public void defaultValue( String defaultValue ) + { + this.defaultValue = defaultValue; + } + + public boolean required() + { + return required; + } + + public void required( boolean required ) + { + this.required = required; + } + + public boolean readonly() + { + return readonly; + } + + public void readonly( boolean readonly ) + { + this.readonly = readonly; + } + + public Class annotationType() + { + return null; + } + + public String getClassName() + { + return className; + } + + public void setClassName( String className ) + { + this.className = className; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( super.toString() ); + sb.append( "ParameterAnnotationContent" ); + sb.append( "{alias='" ).append( alias ).append( '\'' ); + sb.append( ", expression='" ).append( expression ).append( '\'' ); + sb.append( ", defaultValue='" ).append( defaultValue ).append( '\'' ); + sb.append( ", required=" ).append( required ); + sb.append( ", readonly=" ).append( readonly ); + sb.append( '}' ); + return sb.toString(); + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( !( o instanceof ParameterAnnotationContent ) ) + { + return false; + } + + ParameterAnnotationContent that = (ParameterAnnotationContent) o; + + if ( readonly != that.readonly ) + { + return false; + } + if ( required != that.required ) + { + return false; + } + + if ( getFieldName() != null ? !getFieldName().equals( that.getFieldName() ) : that.getFieldName() != null ) + { + return false; + } + + if ( alias != null ? !alias.equals( that.alias ) : that.alias != null ) + { + return false; + } + if ( defaultValue != null ? !defaultValue.equals( that.defaultValue ) : that.defaultValue != null ) + { + return false; + } + if ( expression != null ? !expression.equals( that.expression ) : that.expression != null ) + { + return false; + } + + return true; + } + + @Override + public int hashCode() + { + int result = alias != null ? alias.hashCode() : 0; + result = 31 * result + ( getFieldName() != null ? getFieldName().hashCode() : 0 ); + result = 31 * result + ( expression != null ? expression.hashCode() : 0 ); + result = 31 * result + ( defaultValue != null ? defaultValue.hashCode() : 0 ); + result = 31 * result + ( required ? 1 : 0 ); + result = 31 * result + ( readonly ? 1 : 0 ); + return result; + } +} diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/DefaultMojoAnnotationsScanner.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/DefaultMojoAnnotationsScanner.java new file mode 100644 index 0000000..44e1788 --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/DefaultMojoAnnotationsScanner.java @@ -0,0 +1,321 @@ +package org.apache.maven.tools.plugin.annotations.scanner; +/* + * 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 org.apache.maven.artifact.Artifact; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.tools.plugin.annotations.datamodel.ComponentAnnotationContent; +import org.apache.maven.tools.plugin.annotations.datamodel.ExecuteAnnotationContent; +import org.apache.maven.tools.plugin.annotations.datamodel.MojoAnnotationContent; +import org.apache.maven.tools.plugin.annotations.datamodel.ParameterAnnotationContent; +import org.apache.maven.tools.plugin.annotations.scanner.visitors.MojoAnnotationVisitor; +import org.apache.maven.tools.plugin.annotations.scanner.visitors.MojoClassVisitor; +import org.apache.maven.tools.plugin.annotations.scanner.visitors.MojoFieldVisitor; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.DirectoryScanner; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.reflection.Reflector; +import org.objectweb.asm.ClassReader; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class DefaultMojoAnnotationsScanner + extends AbstractLogEnabled + implements MojoAnnotationsScanner +{ + private Reflector reflector = new Reflector(); + + public Map scan( MojoAnnotationsScannerRequest request ) + throws ExtractionException + { + Map mojoAnnotatedClasses = new HashMap(); + try + { + + for ( Artifact dependency : request.getDependencies() ) + { + File dependencyFile = dependency.getFile(); + if ( dependencyFile != null && dependencyFile.exists() ) + { + if ( dependencyFile.isDirectory() ) + { + mojoAnnotatedClasses.putAll( + scanDirectory( dependencyFile, request.getIncludePatterns(), dependency, true ) ); + } + else + { + mojoAnnotatedClasses.putAll( + scanFile( dependencyFile, request.getIncludePatterns(), dependency, true ) ); + } + } + } + + for ( File classDirectory : request.getClassesDirectories() ) + { + if ( classDirectory.exists() && classDirectory.isDirectory() ) + { + mojoAnnotatedClasses.putAll( + scanDirectory( classDirectory, request.getIncludePatterns(), request.getProject().getArtifact(), + false ) ); + } + } + + return mojoAnnotatedClasses; + } + catch ( IOException e ) + { + throw new ExtractionException( e.getMessage(), e ); + } + } + + /** + * @param archiveFile + * @param includePatterns + * @param artifact + * @param excludeMojo for dependencies we exclude Mojo annotations found + * @return + * @throws IOException + * @throws ExtractionException + */ + protected Map scanFile( File archiveFile, List includePatterns, + Artifact artifact, boolean excludeMojo ) + throws IOException, ExtractionException + { + if ( !archiveFile.exists() ) + { + return Collections.emptyMap(); + } + Map mojoAnnotatedClasses = new HashMap(); + ZipInputStream archiveStream = new ZipInputStream( new FileInputStream( archiveFile ) ); + + try + { + for ( ZipEntry zipEntry = archiveStream.getNextEntry(); zipEntry != null; + zipEntry = archiveStream.getNextEntry() ) + { + if ( zipEntry.getName().endsWith( ".class" ) ) + { + MojoClassVisitor mojoClassVisitor = new MojoClassVisitor( getLogger() ); + + ClassReader rdr = new ClassReader( archiveStream ); + rdr.accept( mojoClassVisitor, + ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG ); + analyzeVisitors( mojoClassVisitor ); + if ( excludeMojo ) + { + mojoClassVisitor.getMojoAnnotatedClass().setMojo( null ); + } + if ( isMojoAnnnotatedClassCandidate( mojoClassVisitor.getMojoAnnotatedClass() ) != null ) + { + getLogger().debug( + "found MojoAnnotatedClass:" + mojoClassVisitor.getMojoAnnotatedClass().getClassName() + ":" + + mojoClassVisitor.getMojoAnnotatedClass() ); + mojoClassVisitor.getMojoAnnotatedClass().setArtifact( artifact ); + mojoAnnotatedClasses.put( mojoClassVisitor.getMojoAnnotatedClass().getClassName(), + mojoClassVisitor.getMojoAnnotatedClass() ); + } + } + } + } + finally + { + IOUtil.close( archiveStream ); + } + return mojoAnnotatedClasses; + } + + /** + * @param classDirectory + * @param includePatterns + * @param artifact + * @param excludeMojo for dependencies we exclude Mojo annotations found + * @return + * @throws IOException + * @throws ExtractionException + */ + protected Map scanDirectory( File classDirectory, List includePatterns, + Artifact artifact, boolean excludeMojo ) + throws IOException, ExtractionException + { + if ( !classDirectory.exists() ) + { + return Collections.emptyMap(); + } + Map mojoAnnotatedClasses = new HashMap(); + DirectoryScanner scanner = new DirectoryScanner(); + scanner.setBasedir( classDirectory ); + scanner.addDefaultExcludes(); + if ( includePatterns != null ) + { + scanner.setIncludes( includePatterns.toArray( new String[includePatterns.size()] ) ); + } + scanner.scan(); + String[] classFiles = scanner.getIncludedFiles(); + + for ( String classFile : classFiles ) + { + InputStream is = new BufferedInputStream( new FileInputStream( new File( classDirectory, classFile ) ) ); + try + { + + if ( classFile.endsWith( ".class" ) ) + { + MojoClassVisitor mojoClassVisitor = new MojoClassVisitor( getLogger() ); + ClassReader rdr = new ClassReader( is ); + rdr.accept( mojoClassVisitor, + ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG ); + analyzeVisitors( mojoClassVisitor ); + if ( excludeMojo ) + { + mojoClassVisitor.getMojoAnnotatedClass().setMojo( null ); + } + if ( isMojoAnnnotatedClassCandidate( mojoClassVisitor.getMojoAnnotatedClass() ) != null ) + { + getLogger().debug( + "found MojoAnnotatedClass:" + mojoClassVisitor.getMojoAnnotatedClass().getClassName() + ":" + + mojoClassVisitor.getMojoAnnotatedClass() ); + mojoClassVisitor.getMojoAnnotatedClass().setArtifact( artifact ); + mojoAnnotatedClasses.put( mojoClassVisitor.getMojoAnnotatedClass().getClassName(), + mojoClassVisitor.getMojoAnnotatedClass() ); + } + + } + } + finally + { + IOUtil.close( is ); + } + + } + return mojoAnnotatedClasses; + } + + private MojoAnnotatedClass isMojoAnnnotatedClassCandidate( MojoAnnotatedClass mojoAnnotatedClass ) + { + if ( mojoAnnotatedClass == null ) + { + return null; + } + if ( !mojoAnnotatedClass.getComponents().isEmpty() || !mojoAnnotatedClass.getParameters().isEmpty() + || mojoAnnotatedClass.getExecute() != null || mojoAnnotatedClass.getMojo() != null ) + { + return mojoAnnotatedClass; + } + return null; + } + + protected void analyzeVisitors( MojoClassVisitor mojoClassVisitor ) + throws ExtractionException + { + + try + { + MojoAnnotationVisitor mojoAnnotationVisitor = + mojoClassVisitor.getAnnotationVisitorMap().get( Mojo.class.getName() ); + if ( mojoAnnotationVisitor != null ) + { + MojoAnnotationContent mojoAnnotationContent = new MojoAnnotationContent(); + for ( Map.Entry entry : mojoAnnotationVisitor.getAnnotationValues().entrySet() ) + { + reflector.invoke( mojoAnnotationContent, entry.getKey(), new Object[]{ entry.getValue() } ); + } + mojoClassVisitor.getMojoAnnotatedClass().setMojo( mojoAnnotationContent ); + } + + mojoAnnotationVisitor = mojoClassVisitor.getAnnotationVisitorMap().get( Execute.class.getName() ); + if ( mojoAnnotationVisitor != null ) + { + ExecuteAnnotationContent executeAnnotationContent = new ExecuteAnnotationContent(); + + for ( Map.Entry entry : mojoAnnotationVisitor.getAnnotationValues().entrySet() ) + { + reflector.invoke( executeAnnotationContent, entry.getKey(), new Object[]{ entry.getValue() } ); + } + mojoClassVisitor.getMojoAnnotatedClass().setExecute( executeAnnotationContent ); + } + + List mojoFieldVisitors = + mojoClassVisitor.findFieldWithAnnotationClass( Parameter.class.getName() ); + + for ( MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors ) + { + ParameterAnnotationContent parameterAnnotationContent = + new ParameterAnnotationContent( mojoFieldVisitor.getFieldName(), mojoFieldVisitor.getClassName() ); + if ( mojoFieldVisitor.getMojoAnnotationVisitor() != null ) + { + for ( Map.Entry entry : mojoFieldVisitor.getMojoAnnotationVisitor().getAnnotationValues().entrySet() ) + { + reflector.invoke( parameterAnnotationContent, entry.getKey(), + new Object[]{ entry.getValue() } ); + } + + } + mojoClassVisitor.getMojoAnnotatedClass().getParameters().put( parameterAnnotationContent.getFieldName(), + parameterAnnotationContent ); + } + + mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotationClass( Component.class.getName() ); + + for ( MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors ) + { + ComponentAnnotationContent componentAnnotationContent = + new ComponentAnnotationContent( mojoFieldVisitor.getFieldName() ); + + if ( mojoFieldVisitor.getMojoAnnotationVisitor() != null ) + { + for ( Map.Entry entry : mojoFieldVisitor.getMojoAnnotationVisitor().getAnnotationValues().entrySet() ) + { + reflector.invoke( componentAnnotationContent, entry.getKey(), + new Object[]{ entry.getValue() } ); + } + if ( StringUtils.isEmpty( componentAnnotationContent.role() ) ) + { + componentAnnotationContent.role( mojoFieldVisitor.getClassName() ); + } + } + mojoClassVisitor.getMojoAnnotatedClass().getComponents().put( componentAnnotationContent.getFieldName(), + componentAnnotationContent ); + } + + } + catch ( Exception e ) + { + throw new ExtractionException( e.getMessage(), e ); + } + } +} diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotatedClass.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotatedClass.java new file mode 100644 index 0000000..847634e --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotatedClass.java @@ -0,0 +1,162 @@ +package org.apache.maven.tools.plugin.annotations.scanner; +/* + * 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 org.apache.maven.artifact.Artifact; +import org.apache.maven.tools.plugin.annotations.datamodel.ComponentAnnotationContent; +import org.apache.maven.tools.plugin.annotations.datamodel.ExecuteAnnotationContent; +import org.apache.maven.tools.plugin.annotations.datamodel.MojoAnnotationContent; +import org.apache.maven.tools.plugin.annotations.datamodel.ParameterAnnotationContent; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class MojoAnnotatedClass +{ + private String className; + + private String parentClassName; + + private MojoAnnotationContent mojo; + + private ExecuteAnnotationContent execute; + + /** + * key is field name + */ + private Map parameters; + + /** + * key is field name + */ + private Map components; + + /** + * artifact which contains this annotation + */ + private Artifact artifact; + + public MojoAnnotatedClass() + { + // no op + } + + public String getClassName() + { + return className; + } + + public MojoAnnotatedClass setClassName( String className ) + { + this.className = className; + return this; + } + + public MojoAnnotationContent getMojo() + { + return mojo; + } + + public MojoAnnotatedClass setMojo( MojoAnnotationContent mojo ) + { + this.mojo = mojo; + return this; + } + + public ExecuteAnnotationContent getExecute() + { + return execute; + } + + public MojoAnnotatedClass setExecute( ExecuteAnnotationContent execute ) + { + this.execute = execute; + return this; + } + + public Map getParameters() + { + if ( this.parameters == null ) + { + this.parameters = new HashMap(); + } + return parameters; + } + + public MojoAnnotatedClass setParameters( Map parameters ) + { + this.parameters = parameters; + return this; + } + + public Map getComponents() + { + if ( this.components == null ) + { + this.components = new HashMap(); + } + return components; + } + + public MojoAnnotatedClass setComponents( Map components ) + { + this.components = components; + return this; + } + + public String getParentClassName() + { + return parentClassName; + } + + public MojoAnnotatedClass setParentClassName( String parentClassName ) + { + this.parentClassName = parentClassName; + return this; + } + + public Artifact getArtifact() + { + return artifact; + } + + public void setArtifact( Artifact artifact ) + { + this.artifact = artifact; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( "MojoAnnotatedClass" ); + sb.append( "{className='" ).append( className ).append( '\'' ); + sb.append( ", parentClassName='" ).append( parentClassName ).append( '\'' ); + sb.append( ", mojo=" ).append( mojo ); + sb.append( ", execute=" ).append( execute ); + sb.append( ", parameters=" ).append( parameters ); + sb.append( ", components=" ).append( components ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotationsScanner.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotationsScanner.java new file mode 100644 index 0000000..2bf9d9a --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotationsScanner.java @@ -0,0 +1,47 @@ +package org.apache.maven.tools.plugin.annotations.scanner; +/* + * 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 org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.tools.plugin.extractor.ExtractionException; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public interface MojoAnnotationsScanner +{ + String ROLE = MojoAnnotationsScanner.class.getName(); + + static final List acceptedClassLevelAnnotationClasses = + Arrays.asList( Mojo.class.getName(), Execute.class.getName() ); + + static final List acceptedFieldLevelAnnotationClasses = + Arrays.asList( Parameter.class.getName(), Component.class.getName() ); + + Map scan( MojoAnnotationsScannerRequest request ) + throws ExtractionException; +} diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotationsScannerRequest.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotationsScannerRequest.java new file mode 100644 index 0000000..af144d1 --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotationsScannerRequest.java @@ -0,0 +1,102 @@ +package org.apache.maven.tools.plugin.annotations.scanner; +/* + * 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 org.apache.maven.artifact.Artifact; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.artifact.ProjectArtifactMetadata; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class MojoAnnotationsScannerRequest +{ + private List classesDirectories = new ArrayList(); + + private Set dependencies = new HashSet(); + + private List includePatterns = Arrays.asList( "**/*.class" ); + + private List sourceDirectories = new ArrayList(); + + private MavenProject project; + + public MojoAnnotationsScannerRequest() + { + // no o + } + + public List getClassesDirectories() + { + return classesDirectories; + } + + public void setClassesDirectories( List classesDirectories ) + { + this.classesDirectories = classesDirectories; + } + + public Set getDependencies() + { + return dependencies; + } + + public void setDependencies( Set dependencies ) + { + this.dependencies = dependencies; + } + + public List getIncludePatterns() + { + return includePatterns; + } + + public void setIncludePatterns( List includePatterns ) + { + this.includePatterns = includePatterns; + } + + public List getSourceDirectories() + { + return sourceDirectories; + } + + public void setSourceDirectories( List sourceDirectories ) + { + this.sourceDirectories = sourceDirectories; + } + + public MavenProject getProject() + { + return project; + } + + public void setProject( MavenProject project ) + { + this.project = project; + } +} diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoAnnotationVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoAnnotationVisitor.java new file mode 100644 index 0000000..1367107 --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoAnnotationVisitor.java @@ -0,0 +1,84 @@ +package org.apache.maven.tools.plugin.annotations.scanner.visitors; +/* + * 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 org.codehaus.plexus.logging.Logger; +import org.objectweb.asm.AnnotationVisitor; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class MojoAnnotationVisitor + implements AnnotationVisitor +{ + private Logger logger; + + private String annotationClassName; + + private Map annotationValues = new HashMap(); + + MojoAnnotationVisitor( Logger logger, String annotationClassName ) + { + this.logger = logger; + this.annotationClassName = annotationClassName; + } + + public Map getAnnotationValues() + { + return annotationValues; + } + + public void visit( String name, Object value ) + { + annotationValues.put( name, value ); + logger.debug( "MojoAnnotationVisitor#visit:" + name + ":" + value ); + } + + public void visitEnum( String name, String desc, String value ) + { + annotationValues.put( name, value ); + logger.debug( "MojoAnnotationVisitor#visitEnum:" + name + ":" + desc + ":" + value ); + } + + public AnnotationVisitor visitAnnotation( String name, String desc ) + { + logger.debug( "MojoAnnotationVisitor#visitAnnotation:" + name + ":" + desc ); + return new MojoAnnotationVisitor( logger, this.annotationClassName ); + } + + public AnnotationVisitor visitArray( String s ) + { + logger.debug( "MojoAnnotationVisitor#visitArray" ); + return new MojoAnnotationVisitor( logger, this.annotationClassName ); + } + + public void visitEnd() + { + logger.debug( "MojoAnnotationVisitor#visitEnd" ); + } + + public String getAnnotationClassName() + { + return annotationClassName; + } +} diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoClassVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoClassVisitor.java new file mode 100644 index 0000000..5cec4b0 --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoClassVisitor.java @@ -0,0 +1,160 @@ +package org.apache.maven.tools.plugin.annotations.scanner.visitors; +/* + * 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 org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotatedClass; +import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.util.StringUtils; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Type; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class MojoClassVisitor + implements ClassVisitor +{ + private Logger logger; + + private MojoAnnotatedClass mojoAnnotatedClass; + + private Map annotationVisitorMap = new HashMap(); + + private List fieldVisitors = new ArrayList(); + + public MojoClassVisitor( Logger logger ) + { + this.logger = logger; + } + + public MojoAnnotatedClass getMojoAnnotatedClass() + { + return mojoAnnotatedClass; + } + + public void setMojoAnnotatedClass( MojoAnnotatedClass mojoAnnotatedClass ) + { + this.mojoAnnotatedClass = mojoAnnotatedClass; + } + + public Map getAnnotationVisitorMap() + { + return annotationVisitorMap; + } + + public void setAnnotationVisitorMap( Map annotationVisitorMap ) + { + this.annotationVisitorMap = annotationVisitorMap; + } + + public List getFieldVisitors() + { + return fieldVisitors; + } + + public void setFieldVisitors( List fieldVisitors ) + { + this.fieldVisitors = fieldVisitors; + } + + public List findFieldWithAnnotationClass( String annotationClassName ) + { + List mojoFieldVisitors = new ArrayList(); + + for ( MojoFieldVisitor mojoFieldVisitor : this.fieldVisitors ) + { + MojoAnnotationVisitor mojoAnnotationVisitor = mojoFieldVisitor.getMojoAnnotationVisitor(); + if ( mojoAnnotationVisitor != null && StringUtils.equals( annotationClassName, + mojoAnnotationVisitor.getAnnotationClassName() ) ) + { + mojoFieldVisitors.add( mojoFieldVisitor ); + } + } + + return mojoFieldVisitors; + } + + public void visit( int version, int access, String name, String signature, String superName, String[] interfaces ) + { + mojoAnnotatedClass = new MojoAnnotatedClass(); + mojoAnnotatedClass.setClassName( Type.getObjectType( name ).getClassName() ).setParentClassName( + Type.getObjectType( superName ).getClassName() ); + logger.debug( "MojoClassVisitor#visit" ); + } + + public AnnotationVisitor visitAnnotation( String desc, boolean visible ) + { + logger.debug( "MojoClassVisitor#visitAnnotation" ); + String annotationClassName = Type.getType( desc ).getClassName(); + if ( !MojoAnnotationsScanner.acceptedClassLevelAnnotationClasses.contains( annotationClassName ) ) + { + return null; + } + MojoAnnotationVisitor mojoAnnotationVisitor = new MojoAnnotationVisitor( logger, annotationClassName ); + annotationVisitorMap.put( annotationClassName, mojoAnnotationVisitor ); + return mojoAnnotationVisitor; + } + + public FieldVisitor visitField( int access, String name, String desc, String signature, Object value ) + { + logger.debug( "MojoClassVisitor#visitField" ); + MojoFieldVisitor mojoFieldVisitor = new MojoFieldVisitor( logger, name, Type.getType( desc ).getClassName() ); + fieldVisitors.add( mojoFieldVisitor ); + return mojoFieldVisitor; + } + + public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions ) + { + // we don't need methods informations + return null; + } + + public void visitAttribute( Attribute attr ) + { + } + + public void visitSource( String source, String debug ) + { + } + + public void visitOuterClass( String owner, String name, String desc ) + { + } + + public void visitInnerClass( String name, String outerName, String innerName, int access ) + { + } + + public void visitEnd() + { + logger.debug( "MojoClassVisitor#visitEnd" ); + } + +} diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoFieldVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoFieldVisitor.java new file mode 100644 index 0000000..2b82907 --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoFieldVisitor.java @@ -0,0 +1,91 @@ +package org.apache.maven.tools.plugin.annotations.scanner.visitors; +/* + * 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 org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner; +import org.codehaus.plexus.logging.Logger; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Type; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class MojoFieldVisitor + implements FieldVisitor +{ + private Logger logger; + + private String fieldName; + + private MojoAnnotationVisitor mojoAnnotationVisitor; + + private String className; + + MojoFieldVisitor( Logger logger, String fieldName, String className ) + { + this.logger = logger; + this.fieldName = fieldName; + this.className = className; + } + + public MojoAnnotationVisitor getMojoAnnotationVisitor() + { + return mojoAnnotationVisitor; + } + + public String getFieldName() + { + return fieldName; + } + + public AnnotationVisitor visitAnnotation( String desc, boolean visible ) + { + logger.debug( "MojoFieldVisitor#visitAnnotation:" + desc ); + String annotationClassName = Type.getType( desc ).getClassName(); + if ( !MojoAnnotationsScanner.acceptedFieldLevelAnnotationClasses.contains( annotationClassName ) ) + { + return null; + } + mojoAnnotationVisitor = new MojoAnnotationVisitor( logger, annotationClassName ); + return mojoAnnotationVisitor; + } + + public void visitAttribute( Attribute attribute ) + { + logger.debug( "MojoFieldVisitor#visitAttribute" ); + } + + public void visitEnd() + { + logger.debug( "MojoFieldVisitor#visitEnd" ); + } + + public String getClassName() + { + return className; + } + + public void setClassName( String className ) + { + this.className = className; + } +} diff --git a/maven-plugin-tools-annotations/src/main/resources/META-INF/plexus/components.xml b/maven-plugin-tools-annotations/src/main/resources/META-INF/plexus/components.xml new file mode 100644 index 0000000..9d6aa87 --- /dev/null +++ b/maven-plugin-tools-annotations/src/main/resources/META-INF/plexus/components.xml @@ -0,0 +1,56 @@ + + + + + + + + org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor + java-annotations + org.apache.maven.tools.plugin.annotations.JavaAnnotationsMojoDescriptorExtractor + + + org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner + + + org.apache.maven.artifact.resolver.ArtifactResolver + + + org.apache.maven.artifact.factory.ArtifactFactory + + + org.codehaus.plexus.archiver.manager.ArchiverManager + + + + + + org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner + default + org.apache.maven.tools.plugin.annotations.scanner.DefaultMojoAnnotationsScanner + + + + \ No newline at end of file diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/annotations/FooMojo.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/annotations/FooMojo.java new file mode 100644 index 0000000..1f9da50 --- /dev/null +++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/annotations/FooMojo.java @@ -0,0 +1,71 @@ +package org.apache.maven.tools.plugin.annotations; +/* + * 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 org.apache.maven.artifact.metadata.ArtifactMetadataSource; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.codehaus.plexus.compiler.manager.CompilerManager; + +/** + * @author Olivier Lamy + */ +@Mojo( name = "foo", defaultPhase = LifecyclePhase.COMPILE, threadSafe = true ) +@Execute( goal = "compiler", lifecycle = "my-lifecycle", phase = LifecyclePhase.PACKAGE ) +public class FooMojo + extends AbstractMojo +{ + /** + * the cool bar to go + * @since 1.0 + */ + @Parameter( expression = "${thebar}", required = true, defaultValue = "coolbar" ) + protected String bar; + + /** + * beer for non french folks + * @deprecated wine is better + */ + @Parameter( expression = "${thebeer}", defaultValue = "coolbeer" ) + protected String beer; + + /** + * Plexus compiler manager. + */ + @Component + protected CompilerManager compilerManager; + + /** + * + */ + @Component( role = "org.apache.maven.artifact.metadata.ArtifactMetadataSource", roleHint = "maven" ) + protected ArtifactMetadataSource artifactMetadataSource; + + public void execute() + throws MojoExecutionException, MojoFailureException + { + // nothing + } +} diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/annotations/TestAnnotationsReader.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/annotations/TestAnnotationsReader.java new file mode 100644 index 0000000..f51900f --- /dev/null +++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/annotations/TestAnnotationsReader.java @@ -0,0 +1,89 @@ +package org.apache.maven.tools.plugin.annotations; +/* + * 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 org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.annotations.datamodel.ComponentAnnotationContent; +import org.apache.maven.tools.plugin.annotations.datamodel.ParameterAnnotationContent; +import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotatedClass; +import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner; +import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScannerRequest; +import org.codehaus.plexus.PlexusTestCase; +import org.fest.assertions.Assertions; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +/** + * @author Olivier Lamy + */ +public class TestAnnotationsReader + extends PlexusTestCase +{ + public void testReadMojoClass() + throws Exception + { + MojoAnnotationsScanner mojoAnnotationsScanner = (MojoAnnotationsScanner) lookup( MojoAnnotationsScanner.ROLE ); + + MojoAnnotationsScannerRequest request = new MojoAnnotationsScannerRequest(); + request.setClassesDirectories( Collections.singletonList( new File( "target/test-classes" ) ) ); + request.setIncludePatterns( Arrays.asList( "**/FooMojo.class" ) ); + request.setProject( new MavenProject() ); + + Map mojoAnnotatedClasses = mojoAnnotationsScanner.scan( request ); + + System.out.println( "mojoAnnotatedClasses:" + mojoAnnotatedClasses ); + + Assertions.assertThat( mojoAnnotatedClasses ).isNotNull().isNotEmpty().hasSize( 1 ); + + MojoAnnotatedClass mojoAnnotatedClass = mojoAnnotatedClasses.values().iterator().next(); + + assertEquals( FooMojo.class.getName(), mojoAnnotatedClass.getClassName() ); + assertEquals( AbstractMojo.class.getName(), mojoAnnotatedClass.getParentClassName() ); + + Mojo mojo = mojoAnnotatedClass.getMojo(); + + assertEquals( "foo", mojo.name() ); + assertEquals( true, mojo.threadSafe() ); + assertEquals( false, mojo.aggregator() ); + assertEquals( LifecyclePhase.COMPILE, mojo.defaultPhase() ); + + Execute execute = mojoAnnotatedClass.getExecute(); + + assertEquals( "compiler", execute.goal() ); + assertEquals( "my-lifecycle", execute.lifecycle() ); + assertEquals( LifecyclePhase.PACKAGE, execute.phase() ); + + Collection components = mojoAnnotatedClass.getComponents().values(); + Assertions.assertThat( components ).isNotNull().isNotEmpty().hasSize( 2 ); + + Collection parameters = mojoAnnotatedClass.getParameters().values(); + Assertions.assertThat( parameters ).isNotNull().isNotEmpty().hasSize( 2 ).contains( + new ParameterAnnotationContent( "bar", null, "${thebar}", "coolbar", true, false, String.class.getName() ), + new ParameterAnnotationContent( "beer", null, "${thebeer}", "coolbeer", false, false, + String.class.getName() ) ); + } +} diff --git a/maven-plugin-tools-ant/pom.xml b/maven-plugin-tools-ant/pom.xml index ac1ef38..fb44f78 100644 --- a/maven-plugin-tools-ant/pom.xml +++ b/maven-plugin-tools-ant/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.plugin-tools maven-plugin-tools - 2.10-SNAPSHOT + 3.0-SNAPSHOT maven-plugin-tools-ant diff --git a/maven-plugin-tools-api/pom.xml b/maven-plugin-tools-api/pom.xml index 62e9700..6de6aa0 100644 --- a/maven-plugin-tools-api/pom.xml +++ b/maven-plugin-tools-api/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.plugin-tools maven-plugin-tools - 2.10-SNAPSHOT + 3.0-SNAPSHOT maven-plugin-tools-api @@ -71,6 +71,31 @@ org.codehaus.plexus plexus-container-default + + org.codehaus.plexus + plexus-velocity + + + velocity + velocity + + + + + + + org.apache.velocity + velocity + + + + asm + asm + + + asm + asm-commons + @@ -93,6 +118,20 @@ + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.build.outputDirectory} + + + + + + reporting diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java index fdbaa7f..9c70400 100644 --- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java +++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java @@ -19,23 +19,29 @@ package org.apache.maven.tools.plugin; * under the License. */ +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.StringUtils; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + /** * Default implementation of {@link PluginToolsRequest}, which is used to pass parameters to components used to extract * {@link MojoDescriptor} instances from different types of metadata for a given plugin. - * + * * @author jdcasey * @since 2.5 */ public class DefaultPluginToolsRequest implements PluginToolsRequest { - + private static final String DEFAULT_ENCODING = ReaderFactory.FILE_ENCODING; private PluginDescriptor pluginDescriptor; @@ -44,6 +50,14 @@ public class DefaultPluginToolsRequest private String encoding = DEFAULT_ENCODING; + private boolean skipErrorNoDescriptorsFound; + + private Set dependencies; + + private List remoteRepos; + + private ArtifactRepository local; + public DefaultPluginToolsRequest( MavenProject project, PluginDescriptor pluginDescriptor ) { this.project = project; @@ -57,7 +71,7 @@ public class DefaultPluginToolsRequest { return pluginDescriptor; } - + /** * {@inheritDoc} */ @@ -74,7 +88,7 @@ public class DefaultPluginToolsRequest { return project; } - + /** * {@inheritDoc} */ @@ -109,4 +123,57 @@ public class DefaultPluginToolsRequest return this; } + /** + * {@inheritDoc} + */ + public boolean isSkipErrorNoDescriptorsFound() + { + return skipErrorNoDescriptorsFound; + } + + /** + * {@inheritDoc} + */ + public PluginToolsRequest setSkipErrorNoDescriptorsFound( boolean skipErrorNoDescriptorsFound ) + { + this.skipErrorNoDescriptorsFound = skipErrorNoDescriptorsFound; + return this; + } + + public Set getDependencies() + { + if ( this.dependencies == null ) + { + this.dependencies = new HashSet(); + } + return dependencies; + } + + public PluginToolsRequest setDependencies( Set dependencies ) + { + this.dependencies = dependencies; + return this; + } + + public List getRemoteRepos() + { + return remoteRepos; + } + + public PluginToolsRequest setRemoteRepos( List remoteRepos ) + { + this.remoteRepos = remoteRepos; + return this; + } + + public ArtifactRepository getLocal() + { + return local; + } + + public PluginToolsRequest setLocal( ArtifactRepository local ) + { + this.local = local; + return this; + } } diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java index d670f12..03fe386 100644 --- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java +++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java @@ -19,30 +19,35 @@ package org.apache.maven.tools.plugin; * under the License. */ +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.project.MavenProject; +import java.util.List; +import java.util.Set; + /** * Request that encapsulates all information relevant to the process of extracting {@link MojoDescriptor} * instances from metadata for a certain type of mojo. - * + * * @author jdcasey * @since 2.5 */ public interface PluginToolsRequest { - + /** * Return the current {@link MavenProject} instance in use. */ MavenProject getProject(); - + /** * @see PluginToolsRequest#getProject() */ PluginToolsRequest setProject( MavenProject project ); - + /** * Return the {@link PluginDescriptor} currently being populated as part of the build of the * current plugin project. @@ -53,21 +58,81 @@ public interface PluginToolsRequest * @see PluginToolsRequest#getPluginDescriptor() */ PluginToolsRequest setPluginDescriptor( PluginDescriptor pluginDescriptor ); - + /** * Gets the file encoding of the source files. - * + * * @return The file encoding of the source files, never null. */ String getEncoding(); /** * Sets the file encoding of the source files. - * + * * @param encoding The file encoding of the source files, may be empty or null to use the platform's - * default encoding. + * default encoding. * @return This request. */ PluginToolsRequest setEncoding( String encoding ); + /** + * By default an exception is throw if no mojo descriptor is found. As the maven-plugin is defined in core, the + * descriptor generator mojo is bound to generate-resources phase. + * But for annotations, the compiled classes are needed, so skip error + * + * @since 3.0 + */ + PluginToolsRequest setSkipErrorNoDescriptorsFound( boolean skipErrorNoDescriptorsFound ); + + /** + * @return + * @since 3.0 + */ + boolean isSkipErrorNoDescriptorsFound(); + + /** + * Returns the list of {@link Artifact} used in class path scanning for annotations + * + * @return + * @since 3.0 + */ + Set getDependencies(); + + /** + * @param dependencies + * @return + * @since 3.0 + */ + PluginToolsRequest setDependencies( Set dependencies ); + + /** + * + * @return + * @since 3.0 + */ + List getRemoteRepos(); + + /** + * + * @param remoteRepos + * @return + * @since 3.0 + */ + PluginToolsRequest setRemoteRepos( List remoteRepos ); + + /** + * + * @return + * @since 3.0 + */ + ArtifactRepository getLocal(); + + /** + * + * @param local + * @return + * @since 3.0 + */ + PluginToolsRequest setLocal( ArtifactRepository local ); + } diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/Generator.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/Generator.java index 344183a..388dd78 100644 --- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/Generator.java +++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/Generator.java @@ -33,18 +33,7 @@ import java.io.IOException; */ public interface Generator { - /** - * Execute the generation for a given plugin descriptor. - * - * @param destinationDirectory required - * @param pluginDescriptor required - * @throws IOException if any - * - * @deprecated Use {@link Generator#execute(File, PluginToolsRequest)} instead. - */ - void execute( File destinationDirectory, PluginDescriptor pluginDescriptor ) - throws IOException; - + /** * Execute the generation for a given plugin descriptor. * @@ -55,5 +44,5 @@ public interface Generator * @since 2.5 */ void execute( File destinationDirectory, PluginToolsRequest request ) - throws IOException; + throws GeneratorException; } \ No newline at end of file diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorException.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorException.java new file mode 100644 index 0000000..10c6473 --- /dev/null +++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorException.java @@ -0,0 +1,32 @@ +package org.apache.maven.tools.plugin.generator; +/* + * 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. + */ + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class GeneratorException + extends Exception +{ + public GeneratorException( String s, Throwable throwable ) + { + super( s, throwable ); + } +} diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java index d41f341..1d3e1af 100644 --- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java +++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java @@ -19,11 +19,12 @@ package org.apache.maven.tools.plugin.generator; * under the License. */ +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.Parameter; import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.plugin.descriptor.Requirement; -import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; +import org.apache.maven.project.MavenProject; import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; import org.apache.maven.tools.plugin.PluginToolsRequest; import org.apache.maven.tools.plugin.util.PluginUtils; @@ -31,63 +32,130 @@ import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; import org.codehaus.plexus.util.xml.XMLWriter; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.commons.RemappingClassAdapter; +import org.objectweb.asm.commons.SimpleRemapper; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; /** + * @version $Id$ * @todo add example usage tag that can be shown in the doco * @todo need to add validation directives so that systems embedding maven2 can * get validation directives to help users in IDEs. - * - * @version $Id$ */ public class PluginDescriptorGenerator implements Generator { - /** {@inheritDoc} */ - public void execute( File destinationDirectory, PluginDescriptor pluginDescriptor ) - throws IOException - { - execute( destinationDirectory, new DefaultPluginToolsRequest( null, pluginDescriptor ) ); - } - - /** {@inheritDoc} */ + + /** + * {@inheritDoc} + */ public void execute( File destinationDirectory, PluginToolsRequest request ) - throws IOException + throws GeneratorException + { + + File tmpPropertiesFile = + new File( request.getProject().getBuild().getDirectory(), "maven-plugin-help.properties" ); + + if ( tmpPropertiesFile.exists() ) + { + Properties properties = new Properties(); + try + { + properties.load( new FileInputStream( tmpPropertiesFile ) ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + String helpPackageName = properties.getProperty( "helpPackageName" ); + // if helpPackageName property is empty we have to rewrite the class with a better package name than empty + if ( StringUtils.isEmpty( helpPackageName ) ) + { + String helpMojoImplementation = rewriteHelpClassToMojoPackage( request ); + if ( helpMojoImplementation != null ) + { + // rewrite plugin descriptor with new HelpMojo implementation class + rewriteDescriptor( request.getPluginDescriptor(), helpMojoImplementation ); + } + + } + } + + try + { + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + MavenProject mavenProject = request.getProject(); + String pluginDescriptionFilePath = + "META-INF/maven/" + mavenProject.getGroupId() + "/" + mavenProject.getArtifactId() + + "/plugin-description.xml"; + f = new File( request.getProject().getBuild().getOutputDirectory(), pluginDescriptionFilePath ); + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean cleanDescription ) + throws IOException, DuplicateMojoDescriptorException { PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); - - String encoding = "UTF-8"; - File f = new File( destinationDirectory, "plugin.xml" ); - - if ( !f.getParentFile().exists() ) + if ( destinationFile.exists() ) { - f.getParentFile().mkdirs(); + destinationFile.delete(); } + else + { + if ( !destinationFile.getParentFile().exists() ) + { + destinationFile.getParentFile().mkdirs(); + } + } + + String encoding = "UTF-8"; Writer writer = null; try { - writer = new OutputStreamWriter( new FileOutputStream( f ), encoding ); + writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), encoding ); XMLWriter w = new PrettyPrintXMLWriter( writer, encoding, null ); w.startElement( "plugin" ); PluginUtils.element( w, "name", pluginDescriptor.getName() ); - - PluginUtils.element( w, "description", pluginDescriptor.getDescription() ); + if ( cleanDescription ) + { + PluginUtils.element( w, "description", PluginUtils.toText( pluginDescriptor.getDescription() ) ); + } + else + { + PluginUtils.element( w, "description", pluginDescriptor.getDescription() ); + } PluginUtils.element( w, "groupId", pluginDescriptor.getGroupId() ); @@ -105,11 +173,11 @@ public class PluginDescriptorGenerator if ( pluginDescriptor.getMojos() != null ) { - for ( @SuppressWarnings( "unchecked" ) - Iterator it = pluginDescriptor.getMojos().iterator(); it.hasNext(); ) + for ( @SuppressWarnings( "unchecked" ) Iterator it = + pluginDescriptor.getMojos().iterator(); it.hasNext(); ) { MojoDescriptor descriptor = it.next(); - processMojoDescriptor( descriptor, w ); + processMojoDescriptor( descriptor, w, cleanDescription ); } } @@ -120,6 +188,7 @@ public class PluginDescriptorGenerator w.endElement(); writer.flush(); + } finally { @@ -128,10 +197,142 @@ public class PluginDescriptorGenerator } /** - * @param mojoDescriptor not null - * @param w not null + * Creates a minimalistic mojo descriptor for the generated help goal. + * + * @param pluginDescriptor The descriptor of the plugin for which to generate a help goal, must not be + * null. + * @return The mojo descriptor for the generated help goal, never null. */ + private MojoDescriptor makeHelpDescriptor( PluginDescriptor pluginDescriptor, String packageName ) + { + MojoDescriptor descriptor = new MojoDescriptor(); + + descriptor.setPluginDescriptor( pluginDescriptor ); + + descriptor.setLanguage( "java" ); + + descriptor.setGoal( "help" ); + + if ( StringUtils.isEmpty( packageName ) ) + { + packageName = discoverPackageName( pluginDescriptor ); + } + if ( StringUtils.isNotEmpty( packageName ) ) + { + descriptor.setImplementation( packageName + '.' + "HelpMojo" ); + } + else + { + descriptor.setImplementation( "HelpMojo" ); + } + + descriptor.setDescription( + "Display help information on " + pluginDescriptor.getArtifactId() + ".
Call

  mvn "
+                + descriptor.getFullGoalName()
+                + " -Ddetail=true -Dgoal=<goal-name>
to display parameter details." ); + + try + { + Parameter param = new Parameter(); + param.setName( "detail" ); + param.setType( "boolean" ); + param.setDescription( "If true, display all settable properties for each goal." ); + param.setDefaultValue( "false" ); + param.setExpression( "${detail}" ); + descriptor.addParameter( param ); + + param = new Parameter(); + param.setName( "goal" ); + param.setType( "java.lang.String" ); + param.setDescription( + "The name of the goal for which to show help." + " If unspecified, all goals will be displayed." ); + param.setExpression( "${goal}" ); + descriptor.addParameter( param ); + + param = new Parameter(); + param.setName( "lineLength" ); + param.setType( "int" ); + param.setDescription( "The maximum length of a display line, should be positive." ); + param.setDefaultValue( "80" ); + param.setExpression( "${lineLength}" ); + descriptor.addParameter( param ); + + param = new Parameter(); + param.setName( "indentSize" ); + param.setType( "int" ); + param.setDescription( "The number of spaces per indentation level, should be positive." ); + param.setDefaultValue( "2" ); + param.setExpression( "${indentSize}" ); + descriptor.addParameter( param ); + } + catch ( Exception e ) + { + throw new RuntimeException( "Failed to setup parameters for help goal", e ); + } + + return descriptor; + } + + /** + * Find the best package name, based on the number of hits of actual Mojo classes. + * + * @param pluginDescriptor not null + * @return the best name of the package for the generated mojo + */ + private static String discoverPackageName( PluginDescriptor pluginDescriptor ) + { + Map packageNames = new HashMap(); + for ( Iterator it = pluginDescriptor.getMojos().iterator(); it.hasNext(); ) + { + MojoDescriptor descriptor = (MojoDescriptor) it.next(); + + String impl = descriptor.getImplementation(); + if ( impl.lastIndexOf( '.' ) != -1 ) + { + String name = impl.substring( 0, impl.lastIndexOf( '.' ) ); + if ( packageNames.get( name ) != null ) + { + int next = ( (Integer) packageNames.get( name ) ).intValue() + 1; + packageNames.put( name, new Integer( next ) ); + } + else + { + packageNames.put( name, new Integer( 1 ) ); + } + } + else + { + packageNames.put( "", new Integer( 1 ) ); + } + } + + String packageName = ""; + int max = 0; + for ( Iterator it = packageNames.keySet().iterator(); it.hasNext(); ) + { + String key = it.next().toString(); + int value = ( (Integer) packageNames.get( key ) ).intValue(); + if ( value > max ) + { + max = value; + packageName = key; + } + } + + return packageName; + } + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param cleanDescription will clean html content from description fields + */ + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w, boolean cleanDescription ) { w.startElement( "mojo" ); @@ -152,7 +353,14 @@ public class PluginDescriptorGenerator if ( description != null ) { w.startElement( "description" ); - w.writeText( mojoDescriptor.getDescription() ); + if ( cleanDescription ) + { + w.writeText( PluginUtils.toText( mojoDescriptor.getDescription() ) ); + } + else + { + w.writeText( mojoDescriptor.getDescription() ); + } w.endElement(); } @@ -323,8 +531,7 @@ public class PluginDescriptorGenerator // Parameters // ---------------------------------------------------------------------- - @SuppressWarnings( "unchecked" ) - List parameters = mojoDescriptor.getParameters(); + @SuppressWarnings( "unchecked" ) List parameters = mojoDescriptor.getParameters(); w.startElement( "parameters" ); @@ -397,11 +604,17 @@ public class PluginDescriptorGenerator PluginUtils.element( w, "required", Boolean.toString( parameter.isRequired() ) ); PluginUtils.element( w, "editable", Boolean.toString( parameter.isEditable() ) ); + if ( cleanDescription ) + { + PluginUtils.element( w, "description", PluginUtils.toText( parameter.getDescription() ) ); + } + else + { + PluginUtils.element( w, "description", parameter.getDescription() ); + } - PluginUtils.element( w, "description", parameter.getDescription() ); - - if ( StringUtils.isNotEmpty( parameter.getDefaultValue() ) - || StringUtils.isNotEmpty( parameter.getExpression() ) ) + if ( StringUtils.isNotEmpty( parameter.getDefaultValue() ) || StringUtils.isNotEmpty( + parameter.getExpression() ) ) { configuration.add( parameter ); } @@ -480,4 +693,80 @@ public class PluginDescriptorGenerator w.endElement(); } + + protected String rewriteHelpClassToMojoPackage( PluginToolsRequest request ) + throws GeneratorException + { + String destinationPackage = PluginHelpGenerator.discoverPackageName( request.getPluginDescriptor() ); + if ( StringUtils.isEmpty( destinationPackage ) ) + { + return null; + } + File helpClassFile = new File( request.getProject().getBuild().getOutputDirectory(), "HelpMojo.class" ); + if ( !helpClassFile.exists() ) + { + return null; + } + File rewriteHelpClassFile = new File( + request.getProject().getBuild().getOutputDirectory() + "/" + StringUtils.replace( destinationPackage, ".", + "/" ), "HelpMojo.class" ); + if ( !rewriteHelpClassFile.getParentFile().exists() ) + { + rewriteHelpClassFile.getParentFile().mkdirs(); + } + + ClassReader cr = null; + try + { + cr = new ClassReader( new FileInputStream( helpClassFile ) ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + + ClassWriter cw = new ClassWriter( 0 ); + + ClassVisitor cv = new RemappingClassAdapter( cw, new SimpleRemapper( "HelpMojo", + StringUtils.replace( destinationPackage, + ".", "/" ) + + "/HelpMojo" ) ); + + try + { + cr.accept( cv, ClassReader.EXPAND_FRAMES ); + } + catch ( Throwable e ) + { + throw new GeneratorException( "ASM issue processing classFile " + helpClassFile.getPath(), e ); + } + + byte[] renamedClass = cw.toByteArray(); + FileOutputStream fos = null; + try + { + fos = new FileOutputStream( rewriteHelpClassFile ); + fos.write( renamedClass ); + } + catch ( IOException e ) + { + throw new GeneratorException( "Error rewriting help class: " + e.getMessage(), e ); + } + finally + { + IOUtil.close( fos ); + } + helpClassFile.delete(); + return destinationPackage + ".HelpMojo"; + } + + + private void rewriteDescriptor( PluginDescriptor pluginDescriptor, String helpMojoImplementation ) + { + MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( "help" ); + if ( mojoDescriptor != null ) + { + mojoDescriptor.setImplementation( helpMojoImplementation ); + } + } } diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java index a7ab865..8f48f64 100644 --- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java +++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java @@ -19,31 +19,32 @@ package org.apache.maven.tools.plugin.generator; * under the License. */ -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; - import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.Parameter; import org.apache.maven.plugin.descriptor.PluginDescriptor; -import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; +import org.apache.maven.project.MavenProject; import org.apache.maven.tools.plugin.PluginToolsRequest; -import org.apache.maven.tools.plugin.util.PluginUtils; +import org.apache.velocity.VelocityContext; import org.codehaus.plexus.logging.AbstractLogEnabled; import org.codehaus.plexus.logging.Logger; import org.codehaus.plexus.logging.console.ConsoleLogger; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.velocity.VelocityComponent; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; /** * Generates an HelpMojo class. @@ -56,20 +57,30 @@ public class PluginHelpGenerator extends AbstractLogEnabled implements Generator { - /** Line separator */ + /** + * Line separator + */ private static final String LS = System.getProperty( "line.separator" ); - /** Default generated class name */ + /** + * Default generated class name + */ private static final String HELP_MOJO_CLASS_NAME = "HelpMojo"; - /** Default goal */ + /** + * Default goal + */ private static final String HELP_GOAL = "help"; private String helpPackageName; - - /** Flag to indicate if the generated help mojo should use Java 5 features */ + + /** + * Flag to indicate if the generated help mojo should use Java 5 features + */ private boolean useJava5; + private VelocityComponent velocityComponent; + /** * Default constructor */ @@ -82,46 +93,67 @@ public class PluginHelpGenerator // Public methods // ---------------------------------------------------------------------- - /** {@inheritDoc} */ - public void execute( File destinationDirectory, PluginDescriptor pluginDescriptor ) - throws IOException - { - execute( destinationDirectory, new DefaultPluginToolsRequest( null, pluginDescriptor ) ); - } - - /** {@inheritDoc} */ + + /** + * {@inheritDoc} + */ public void execute( File destinationDirectory, PluginToolsRequest request ) - throws IOException + throws GeneratorException { PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); - - if ( pluginDescriptor.getMojos() == null || pluginDescriptor.getMojos().size() < 1 ) - { - return; - } MojoDescriptor helpDescriptor = makeHelpDescriptor( pluginDescriptor ); - // Verify that no help goal already exists - for ( @SuppressWarnings( "unchecked" ) - Iterator it = pluginDescriptor.getMojos().iterator(); it.hasNext(); ) + List mojoDescriptors = pluginDescriptor.getMojos(); + + if ( mojoDescriptors != null ) { - MojoDescriptor descriptor = it.next(); - - if ( descriptor.getGoal().equals( helpDescriptor.getGoal() ) - && !descriptor.getImplementation().equals( helpDescriptor.getImplementation() ) ) + // Verify that no help goal already exists + for ( MojoDescriptor descriptor : mojoDescriptors ) { - if ( getLogger().isWarnEnabled() ) + if ( descriptor.getGoal().equals( helpDescriptor.getGoal() ) && !descriptor.getImplementation().equals( + helpDescriptor.getImplementation() ) ) { - getLogger().warn( - "\n\nA help goal (" + descriptor.getImplementation() - + ") already exists in this plugin. SKIPPED THE " - + helpDescriptor.getImplementation() + " GENERATION.\n" ); - } + if ( getLogger().isWarnEnabled() ) + { + getLogger().warn( "\n\nA help goal (" + descriptor.getImplementation() + + ") already exists in this plugin. SKIPPED THE " + + helpDescriptor.getImplementation() + " GENERATION.\n" ); + } - return; + return; + } } } + Properties properties = new Properties(); + properties.put( "helpPackageName", helpPackageName == null ? "" : helpPackageName ); + + MavenProject mavenProject = request.getProject(); + + String propertiesFilePath = "META-INF/maven/" + mavenProject.getGroupId() + "/" + mavenProject.getArtifactId(); + + File tmpPropertiesFile = + new File( request.getProject().getBuild().getDirectory(), "maven-plugin-help.properties" ); + if ( tmpPropertiesFile.exists() ) + { + tmpPropertiesFile.delete(); + } + else + { + if ( !tmpPropertiesFile.getParentFile().exists() ) + { + tmpPropertiesFile.getParentFile().mkdirs(); + } + } + + try + { + properties.store( new FileOutputStream( tmpPropertiesFile ), "maven plugin help generation informations" ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } String sourcePath = helpDescriptor.getImplementation().replace( '.', File.separatorChar ) + ".java"; File helpClass = new File( destinationDirectory, sourcePath ); @@ -131,13 +163,19 @@ public class PluginHelpGenerator try { writer = new OutputStreamWriter( new FileOutputStream( helpClass ), request.getEncoding() ); - writeClass( writer, pluginDescriptor, helpDescriptor, useJava5 ); + writer.write( getHelpClassSources( propertiesFilePath ) ); writer.flush(); } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } finally { IOUtil.close( writer ); } + + } public PluginHelpGenerator setHelpPackageName( String helpPackageName ) @@ -152,15 +190,52 @@ public class PluginHelpGenerator return this; } + public VelocityComponent getVelocityComponent() + { + return velocityComponent; + } + + public PluginHelpGenerator setVelocityComponent( VelocityComponent velocityComponent ) + { + this.velocityComponent = velocityComponent; + return this; + } + // ---------------------------------------------------------------------- // Private methods // ---------------------------------------------------------------------- + protected String getHelpClassSources( String propertiesFilePath ) + { + Properties properties = new Properties(); + VelocityContext context = new VelocityContext( properties ); + if ( this.helpPackageName != null ) + { + properties.put( "helpPackageName", this.helpPackageName ); + } + else + { + properties.put( "helpPackageName", "" ); + } + properties.put( "propertiesFilePath", propertiesFilePath + "/plugin-description.xml" ); + // FIXME encoding ! + + StringWriter stringWriter = new StringWriter(); + + InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream( "help-class-source.vm" ); + InputStreamReader isReader = new InputStreamReader( is ); + velocityComponent.getEngine().evaluate( context, stringWriter, "", isReader ); + + return stringWriter.toString(); + + } + + /** * Creates a minimalistic mojo descriptor for the generated help goal. * * @param pluginDescriptor The descriptor of the plugin for which to generate a help goal, must not be - * null. + * null. * @return The mojo descriptor for the generated help goal, never null. */ private MojoDescriptor makeHelpDescriptor( PluginDescriptor pluginDescriptor ) @@ -187,9 +262,10 @@ public class PluginHelpGenerator descriptor.setImplementation( HELP_MOJO_CLASS_NAME ); } - descriptor.setDescription( "Display help information on " + pluginDescriptor.getArtifactId() - + ".
Call
  mvn " + descriptor.getFullGoalName()
-            + " -Ddetail=true -Dgoal=<goal-name>
to display parameter details." ); + descriptor.setDescription( + "Display help information on " + pluginDescriptor.getArtifactId() + ".
Call
  mvn "
+                + descriptor.getFullGoalName()
+                + " -Ddetail=true -Dgoal=<goal-name>
to display parameter details." ); try { @@ -204,8 +280,8 @@ public class PluginHelpGenerator param = new Parameter(); param.setName( "goal" ); param.setType( "java.lang.String" ); - param.setDescription( "The name of the goal for which to show help." - + " If unspecified, all goals will be displayed." ); + param.setDescription( + "The name of the goal for which to show help." + " If unspecified, all goals will be displayed." ); param.setExpression( "${goal}" ); descriptor.addParameter( param ); @@ -239,597 +315,55 @@ public class PluginHelpGenerator * @param pluginDescriptor not null * @return the best name of the package for the generated mojo */ - private static String discoverPackageName( PluginDescriptor pluginDescriptor ) + protected static String discoverPackageName( PluginDescriptor pluginDescriptor ) { Map packageNames = new HashMap(); - for ( @SuppressWarnings( "unchecked" ) - Iterator it = pluginDescriptor.getMojos().iterator(); it.hasNext(); ) + List mojoDescriptors = pluginDescriptor.getMojos(); + if ( mojoDescriptors == null ) + { + return ""; + } + for ( MojoDescriptor descriptor : mojoDescriptors ) { - MojoDescriptor descriptor = it.next(); - - String name = ""; - int next = 1; String impl = descriptor.getImplementation(); + if ( StringUtils.equals( descriptor.getGoal(), "help" ) && StringUtils.equals( "HelpMojo", impl ) ) + { + continue; + } if ( impl.lastIndexOf( '.' ) != -1 ) { - name = impl.substring( 0, impl.lastIndexOf( '.' ) ); - Integer count = packageNames.get( name ); - - if ( count != null ) + String name = impl.substring( 0, impl.lastIndexOf( '.' ) ); + if ( packageNames.get( name ) != null ) { - next = count.intValue() + 1; + int next = ( packageNames.get( name ) ).intValue() + 1; + packageNames.put( name, new Integer( next ) ); + } + else + { + packageNames.put( name, new Integer( 1 ) ); } } - - packageNames.put( name, next ); + else + { + packageNames.put( "", new Integer( 1 ) ); + } } String packageName = ""; int max = 0; - for ( Map.Entry entry : packageNames.entrySet() ) + for ( Iterator it = packageNames.keySet().iterator(); it.hasNext(); ) { - int value = entry.getValue().intValue(); + String key = it.next().toString(); + int value = ( packageNames.get( key ) ).intValue(); if ( value > max ) { max = value; - packageName = entry.getKey(); + packageName = key; } } return packageName; } - /** - * Generates the HelpMojo class. - * - * @param writer not null - * @param pluginDescriptor not null - * @param helpDescriptor not null - * @param useJava5 If the generated code should use Java5 features - * @throws IOException if any - */ - private static void writeClass( Writer writer, PluginDescriptor pluginDescriptor, MojoDescriptor helpDescriptor, - boolean useJava5 ) - throws IOException - { - String packageName = ""; - String simpleName = helpDescriptor.getImplementation(); - int dot = simpleName.lastIndexOf( '.' ); - if ( dot >= 0 ) - { - packageName = simpleName.substring( 0, dot ); - simpleName = simpleName.substring( dot + 1 ); - } - - if ( packageName.length() > 0 ) - { - writer.write( "package " + packageName + ";" + LS ); - writer.write( LS ); - } - - writeImports( writer ); - writer.write( LS ); - - writeMojoJavadoc( writer, pluginDescriptor, helpDescriptor ); - - if ( useJava5 ) - { - writer.write( "@SuppressWarnings( \"all\" )" + LS ); - } - - writer.write( "public class " + simpleName + LS ); - writer.write( " extends AbstractMojo" + LS ); - writer.write( "{" + LS ); - - writeVariables( writer, helpDescriptor ); - - writer.write( LS ); - - writeExecute( writer, pluginDescriptor, helpDescriptor ); - - writer.write( LS ); - writeUtilities( writer, useJava5 ); - writer.write( "}" + LS ); - } - - /** - * @param writer not null - * @throws IOException if any - */ - private static void writeImports( Writer writer ) - throws IOException - { - writer.write( "import java.util.ArrayList;" + LS ); - writer.write( "import java.util.Iterator;" + LS ); - writer.write( "import java.util.List;" + LS ); - writer.write( LS ); - writer.write( "import org.apache.maven.plugin.AbstractMojo;" + LS ); - writer.write( "import org.apache.maven.plugin.MojoExecutionException;" + LS ); - } - - /** - * @param writer not null - * @param pluginDescriptor not null - * @param helpDescriptor not null - * @throws IOException if any - */ - private static void writeMojoJavadoc( Writer writer, PluginDescriptor pluginDescriptor, - MojoDescriptor helpDescriptor ) - throws IOException - { - StringBuffer author = new StringBuffer(); - author.append( PluginHelpGenerator.class.getName() ); - - String resource = "META-INF/maven/org.apache.maven.plugin-tools/maven-plugin-tools-api/pom.properties"; - InputStream resourceAsStream = PluginHelpGenerator.class.getClassLoader().getResourceAsStream( resource ); - - if ( resourceAsStream != null ) - { - try - { - Properties properties = new Properties(); - properties.load( resourceAsStream ); - - author.append( " (version " ).append( properties.getProperty( "version", "unknown" ) ).append( ")" ); - } - catch ( IOException e ) - { - // nope - } - finally - { - IOUtil.close( resourceAsStream ); - } - } - - writer.write( "/**" + LS ); - writer.write( " * " + helpDescriptor.getDescription() + LS ); - writer.write( " *" + LS ); - writer.write( " * @version generated on " + new Date() + LS ); - writer.write( " * @author " + author.toString() + LS ); - writer.write( " * @goal " + helpDescriptor.getGoal() + LS ); - writer.write( " * @requiresProject false" + LS ); - writer.write( " * @threadSafe" + LS ); - writer.write( " */" + LS ); - } - - /** - * @param writer not null - * @param helpDescriptor not null - * @throws IOException if any - */ - private static void writeVariables( Writer writer, MojoDescriptor helpDescriptor ) - throws IOException - { - for ( @SuppressWarnings( "unchecked" ) - Iterator it = helpDescriptor.getParameters().iterator(); it.hasNext(); ) - { - Parameter param = it.next(); - writer.write( " /**" + LS ); - writer.write( " * " + StringUtils.escape( param.getDescription() ) + LS ); - writer.write( " * " + LS ); - writer.write( " * @parameter" ); - if ( StringUtils.isNotEmpty( param.getExpression() ) ) - { - writer.write( " expression=\"" ); - writer.write( StringUtils.escape( param.getExpression() ) ); - writer.write( "\"" ); - } - if ( StringUtils.isNotEmpty( param.getDefaultValue() ) ) - { - writer.write( " default-value=\"" ); - writer.write( StringUtils.escape( param.getDefaultValue() ) ); - writer.write( "\"" ); - } - writer.write( LS ); - writer.write( " */" + LS ); - writer.write( " private " + param.getType() + " " + param.getName() + ";" + LS ); - writer.write( LS ); - } - } - - /** - * @param writer not null - * @param pluginDescriptor not null - * @param helpDescriptor not null - * @throws IOException if any - */ - private static void writeExecute( Writer writer, PluginDescriptor pluginDescriptor, MojoDescriptor helpDescriptor ) - throws IOException - { - List mojoDescriptors = new ArrayList(); - - mojoDescriptors.add( helpDescriptor ); - for ( @SuppressWarnings( "unchecked" ) - Iterator it = pluginDescriptor.getMojos().iterator(); it.hasNext(); ) - { - MojoDescriptor mojoDescriptor = it.next(); - - if ( !helpDescriptor.getGoal().equals( mojoDescriptor.getGoal() ) ) - { - mojoDescriptors.add( mojoDescriptor ); - } - } - - PluginUtils.sortMojos( mojoDescriptors ); - - writer.write( " /** {@inheritDoc} */" + LS ); - writer.write( " public void execute()" + LS ); - writer.write( " throws MojoExecutionException" + LS ); - writer.write( " {" + LS ); - - writer.write( " if ( lineLength <= 0 )" + LS ); - writer.write( " {" + LS ); - writer.write( " getLog().warn( \"The parameter 'lineLength' should be positive, using '80' as " - + "default.\" );" + LS ); - writer.write( " lineLength = 80;" + LS ); - writer.write( " }" + LS ); - writer.write( " if ( indentSize <= 0 )" + LS ); - writer.write( " {" + LS ); - writer.write( " getLog().warn( \"The parameter 'indentSize' should be positive, using '2' as " - + "default.\" );" + LS ); - writer.write( " indentSize = 2;" + LS ); - writer.write( " }" + LS ); - writer.write( LS ); - - writer.write( " StringBuffer sb = new StringBuffer();" + LS ); - writer.write( LS ); - - writer.write( " append( sb, \"" + StringUtils.escape( pluginDescriptor.getId() ) + "\", 0 );" + LS ); - writer.write( " append( sb, \"\", 0 );" + LS ); - writer.write( LS ); - - if ( StringUtils.isNotEmpty( pluginDescriptor.getName() ) - && ( pluginDescriptor.getName().indexOf( pluginDescriptor.getId() ) != -1 ) ) - { - writer.write( " append( sb, \"" - + StringUtils.escape( pluginDescriptor.getName() + " " + pluginDescriptor.getVersion() ) - + "\", 0 );" + LS ); - } - else - { - if ( StringUtils.isNotEmpty( pluginDescriptor.getName() ) ) - { - writer.write( " append( sb, \"" + StringUtils.escape( pluginDescriptor.getName() ) - + "\", 0 );" + LS ); - } - else - { - writer.write( " append( sb, \"" + StringUtils.escape( pluginDescriptor.getId() ) - + "\", 0 );" + LS ); - } - } - writer.write( " append( sb, \"" + toDescription( pluginDescriptor.getDescription() ) + "\", 1 );" - + LS ); - writer.write( " append( sb, \"\", 0 );" + LS ); - writer.write( LS ); - - writer.write( " if ( goal == null || goal.length() <= 0 )" + LS ); - writer.write( " {" + LS ); - writer.write( " append( sb, \"This plugin has " + mojoDescriptors.size() + " " - + ( mojoDescriptors.size() > 1 ? "goals" : "goal" ) + ":\", 0 );" + LS ); - writer.write( " append( sb, \"\", 0 );" + LS ); - writer.write( " }" + LS ); - - writer.write( LS ); - - for ( MojoDescriptor descriptor : mojoDescriptors ) - { - writeGoal( writer, descriptor ); - } - - writer.write( " if ( getLog().isInfoEnabled() )" + LS ); - writer.write( " {" + LS ); - writer.write( " getLog().info( sb.toString() );" + LS ); - writer.write( " }" + LS ); - writer.write( " }" + LS ); - } - - /** - * @param writer not null - * @param descriptor not null - * @throws IOException if any - */ - private static void writeGoal( Writer writer, MojoDescriptor descriptor ) - throws IOException - { - String goalDescription = toDescription( descriptor.getDescription() ); - - writer.write( " if ( goal == null || goal.length() <= 0 || \"" - + StringUtils.escape( descriptor.getGoal() ) + "\".equals( goal ) )" + LS ); - writer.write( " {" + LS ); - writer.write( " append( sb, \"" + StringUtils.escape( descriptor.getFullGoalName() ) + "\", 0 );" - + LS ); - if ( StringUtils.isNotEmpty( descriptor.getDeprecated() ) ) - { - writer.write( " append( sb, \"Deprecated. " + toDescription( descriptor.getDeprecated() ) - + "\", 1 );" + LS ); - writer.write( " if ( detail )" + LS ); - writer.write( " {" + LS ); - writer.write( " append( sb, \"\", 0 );" + LS ); - writer.write( " append( sb, \"" + goalDescription + "\", 1 );" + LS ); - writer.write( " }" + LS ); - } - else - { - writer.write( " append( sb, \"" + goalDescription + "\", 1 );" + LS ); - } - writer.write( " append( sb, \"\", 0 );" + LS ); - - if ( descriptor.getParameters() != null && descriptor.getParameters().size() > 0 ) - { - @SuppressWarnings( "unchecked" ) - List params = descriptor.getParameters(); - - PluginUtils.sortMojoParameters( params ); - - writer.write( " if ( detail )" + LS ); - writer.write( " {" + LS ); - - writer.write( " append( sb, \"Available parameters:\", 1 );" + LS ); - writer.write( " append( sb, \"\", 0 );" + LS ); - - for ( Parameter parameter : params ) - { - if ( parameter.isEditable() ) - { - writer.write( LS ); - writeParameter( writer, parameter ); - } - } - - writer.write( " }" + LS ); - } - - writer.write( " }" + LS ); - writer.write( LS ); - } - - /** - * @param writer not null - * @param parameter not null - * @throws IOException if any - */ - private static void writeParameter( Writer writer, Parameter parameter ) - throws IOException - { - String expression = parameter.getExpression(); - - if ( expression == null || !expression.startsWith( "${component." ) ) - { - String parameterName = StringUtils.escape( parameter.getName() ); - String parameterDescription = toDescription( parameter.getDescription() ); - String parameterDefaultValue = ""; - if ( StringUtils.isNotEmpty( parameter.getDefaultValue() ) ) - { - parameterDefaultValue = " (Default: " + StringUtils.escape( parameter.getDefaultValue() ) + ")"; - } - writer.write( " append( sb, \"" + parameterName + parameterDefaultValue + "\", 2 );" + LS ); - if ( StringUtils.isNotEmpty( parameter.getDeprecated() ) ) - { - writer.write( " append( sb, \"Deprecated. " + toDescription( parameter.getDeprecated() ) - + "\", 3 );" + LS ); - writer.write( " append( sb, \"\", 0 );" + LS ); - } - writer.write( " append( sb, \"" + parameterDescription + "\", 3 );" + LS ); - if ( parameter.isRequired() ) - { - writer.write( " append( sb, \"Required: Yes\", 3 );" + LS ); - } - if ( StringUtils.isNotEmpty( parameter.getExpression() ) ) - { - writer.write( " append( sb, \"Expression: " - + StringUtils.escape( parameter.getExpression() ) + "\", 3 );" + LS ); - } - writer.write( " append( sb, \"\", 0 );" + LS ); - } - } - - /** - * @param writer not null - * @param useJava5 If the generated code should use Java5 features - * @throws IOException if any - */ - private static void writeUtilities( Writer writer, boolean useJava5 ) - throws IOException - { - writer.write( " /**" + LS ); - writer.write( " *

Repeat a String n times to form a new string.

" + LS ); - writer.write( " *" + LS ); - writer.write( " * @param str String to repeat" + LS ); - writer.write( " * @param repeat number of times to repeat str" + LS ); - writer.write( " * @return String with repeated String" + LS ); - writer.write( " * @throws NegativeArraySizeException if repeat < 0" + LS ); - writer.write( " * @throws NullPointerException if str is null" + LS ); - writer.write( " */" + LS ); - writer.write( " private static String repeat( String str, int repeat )" + LS ); - writer.write( " {" + LS ); - writer.write( " StringBuffer buffer = new StringBuffer( repeat * str.length() );" + LS ); - writer.write( LS ); - writer.write( " for ( int i = 0; i < repeat; i++ )" + LS ); - writer.write( " {" + LS ); - writer.write( " buffer.append( str );" + LS ); - writer.write( " }" + LS ); - writer.write( LS ); - writer.write( " return buffer.toString();" + LS ); - writer.write( " }" + LS ); - - writer.write( LS ); - writer.write( " /** " + LS ); - writer.write( " * Append a description to the buffer by respecting the indentSize and lineLength " - + "parameters." + LS ); - writer.write( " * Note: The last character is always a new line." + LS ); - writer.write( " * " + LS ); - writer.write( " * @param sb The buffer to append the description, not null." + LS ); - writer.write( " * @param description The description, not null." + LS ); - writer.write( " * @param indent The base indentation level of each line, must not be negative." + LS ); - writer.write( " */" + LS ); - writer.write( " private void append( StringBuffer sb, String description, int indent )" + LS ); - writer.write( " {" + LS ); - writer.write( " for ( Iterator it = toLines( description, indent, indentSize, lineLength )" - + ".iterator(); it.hasNext(); )" + LS ); - writer.write( " {" + LS ); - writer.write( " sb.append( it.next().toString() ).append( '\\n' );" + LS ); - writer.write( " }" + LS ); - writer.write( " }" + LS ); - - writer.write( LS ); - writer.write( " /** " + LS ); - writer.write( " * Splits the specified text into lines of convenient display length." + LS ); - writer.write( " * " + LS ); - writer.write( " * @param text The text to split into lines, must not be null." + LS ); - writer.write( " * @param indent The base indentation level of each line, must not be negative." + LS ); - writer.write( " * @param indentSize The size of each indentation, must not be negative." + LS ); - writer.write( " * @param lineLength The length of the line, must not be negative." + LS ); - writer.write( " * @return The sequence of display lines, never null." + LS ); - writer.write( " * @throws NegativeArraySizeException if indent < 0" + LS ); - writer.write( " */" + LS ); - writer.write( " private static List toLines( String text, int indent, int indentSize, int lineLength )" - + LS ); - writer.write( " {" + LS ); - if ( useJava5 ) - { - writer.write( " List lines = new ArrayList();" + LS ); - } - else - { - writer.write( " List lines = new ArrayList();" + LS ); - } - writer.write( LS ); - writer.write( " String ind = repeat( \"\\t\", indent );" + LS ); - writer.write( " String[] plainLines = text.split( \"(\\r\\n)|(\\r)|(\\n)\" );" + LS ); - writer.write( " for ( int i = 0; i < plainLines.length; i++ )" + LS ); - writer.write( " {" + LS ); - writer.write( " toLines( lines, ind + plainLines[i], indentSize, lineLength );" + LS ); - writer.write( " }" + LS ); - writer.write( LS ); - writer.write( " return lines;" + LS ); - writer.write( " }" + LS ); - - writer.write( LS ); - writer.write( " /** " + LS ); - writer.write( " * Adds the specified line to the output sequence, performing line wrapping if necessary." - + LS ); - writer.write( " * " + LS ); - writer.write( " * @param lines The sequence of display lines, must not be null." + LS ); - writer.write( " * @param line The line to add, must not be null." + LS ); - writer.write( " * @param indentSize The size of each indentation, must not be negative." + LS ); - writer.write( " * @param lineLength The length of the line, must not be negative." + LS ); - writer.write( " */" + LS ); - if ( useJava5 ) - { - writer.write( " private static void toLines( List lines, String line, int indentSize, int lineLength )" - + LS ); - } - else - { - writer.write( " private static void toLines( List lines, String line, int indentSize, int lineLength )" - + LS ); - } - writer.write( " {" + LS ); - writer.write( " int lineIndent = getIndentLevel( line );" + LS ); - writer.write( " StringBuffer buf = new StringBuffer( 256 );" + LS ); - writer.write( " String[] tokens = line.split( \" +\" );" + LS ); - writer.write( " for ( int i = 0; i < tokens.length; i++ )" + LS ); - writer.write( " {" + LS ); - writer.write( " String token = tokens[i];" + LS ); - writer.write( " if ( i > 0 )" + LS ); - writer.write( " {" + LS ); - writer.write( " if ( buf.length() + token.length() >= lineLength )" + LS ); - writer.write( " {" + LS ); - writer.write( " lines.add( buf.toString() );" + LS ); - writer.write( " buf.setLength( 0 );" + LS ); - writer.write( " buf.append( repeat( \" \", lineIndent * indentSize ) );" + LS ); - writer.write( " }" + LS ); - writer.write( " else" + LS ); - writer.write( " {" + LS ); - writer.write( " buf.append( ' ' );" + LS ); - writer.write( " }" + LS ); - writer.write( " }" + LS ); - writer.write( " for ( int j = 0; j < token.length(); j++ )" + LS ); - writer.write( " {" + LS ); - writer.write( " char c = token.charAt( j );" + LS ); - writer.write( " if ( c == '\\t' )" + LS ); - writer.write( " {" + LS ); - writer.write( " buf.append( repeat( \" \", indentSize - buf.length() % indentSize ) );" - + LS ); - writer.write( " }" + LS ); - writer.write( " else if ( c == '\\u00A0' )" + LS ); - writer.write( " {" + LS ); - writer.write( " buf.append( ' ' );" + LS ); - writer.write( " }" + LS ); - writer.write( " else" + LS ); - writer.write( " {" + LS ); - writer.write( " buf.append( c );" + LS ); - writer.write( " }" + LS ); - writer.write( " }" + LS ); - writer.write( " }" + LS ); - writer.write( " lines.add( buf.toString() );" + LS ); - writer.write( " }" + LS ); - - writer.write( LS ); - writer.write( " /** " + LS ); - writer.write( " * Gets the indentation level of the specified line." + LS ); - writer.write( " * " + LS ); - writer.write( " * @param line The line whose indentation level should be retrieved, must not be " - + "null." + LS ); - writer.write( " * @return The indentation level of the line." + LS ); - writer.write( " */" + LS ); - writer.write( " private static int getIndentLevel( String line )" + LS ); - writer.write( " {" + LS ); - writer.write( " int level = 0;" + LS ); - writer.write( " for ( int i = 0; i < line.length() && line.charAt( i ) == '\\t'; i++ )" + LS ); - writer.write( " {" + LS ); - writer.write( " level++;" + LS ); - writer.write( " }" + LS ); - writer.write( " for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )" + LS ); - writer.write( " {" + LS ); - writer.write( " if ( line.charAt( i ) == '\\t' )" + LS ); - writer.write( " {" + LS ); - writer.write( " level++;" + LS ); - writer.write( " break;" + LS ); - writer.write( " }" + LS ); - writer.write( " }" + LS ); - writer.write( " return level;" + LS ); - writer.write( " }" + LS ); - } - - /** - * Gets the effective string to use for the plugin/mojo/parameter description. - * - * @param description The description of the element, may be null. - * @return The effective description string, never null. - */ - private static String toDescription( String description ) - { - if ( StringUtils.isNotEmpty( description ) ) - { - return StringUtils.escape( PluginUtils.toText( description ) ); - } - - return "(no description available)"; - } - - /** - * Converts a HTML fragment as extracted from a javadoc comment to a plain text string. This method tries to retain - * as much of the text formatting as possible by means of the following transformations: - *
    - *
  • List items are converted to leading tabs (U+0009), followed by the item number/bullet, another tab and - * finally the item contents. Each tab denotes an increase of indentation.
  • - *
  • Flow breaking elements as well as literal line terminators in preformatted text are converted to a newline - * (U+000A) to denote a mandatory line break.
  • - *
  • Consecutive spaces and line terminators from character data outside of preformatted text will be normalized - * to a single space. The resulting space denotes a possible point for line wrapping.
  • - *
  • Each space in preformatted text will be converted to a non-breaking space (U+00A0).
  • - *
- * - * @param html The HTML fragment to convert to plain text, may be null. - * @return A string with HTML tags converted into pure text, never null. - * @deprecated since 2.4.3, using {@link PluginUtils#toText(String)} instead of. - */ - protected static String toText( String html ) - { - return PluginUtils.toText( html ); - } } diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java index 899d70e..fbd3a1c 100644 --- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java +++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java @@ -19,6 +19,17 @@ package org.apache.maven.tools.plugin.generator; * under the License. */ +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -32,30 +43,21 @@ import java.util.List; import java.util.Locale; import java.util.ResourceBundle; -import org.apache.maven.plugin.descriptor.MojoDescriptor; -import org.apache.maven.plugin.descriptor.Parameter; -import org.apache.maven.plugin.descriptor.PluginDescriptor; -import org.apache.maven.project.MavenProject; -import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; -import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; -import org.apache.maven.tools.plugin.PluginToolsRequest; -import org.apache.maven.tools.plugin.util.PluginUtils; -import org.codehaus.plexus.util.IOUtil; -import org.codehaus.plexus.util.StringUtils; -import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; -import org.codehaus.plexus.util.xml.XMLWriter; - /** - * @todo add example usage tag that can be shown in the doco * @version $Id$ + * @todo add example usage tag that can be shown in the doco */ public class PluginXdocGenerator implements Generator { - /** locale */ + /** + * locale + */ private final Locale locale; - /** project */ + /** + * project + */ private final MavenProject project; /** @@ -81,7 +83,7 @@ public class PluginXdocGenerator /** * @param project not null. - * @param locale not null wanted locale. + * @param locale not null wanted locale. */ public PluginXdocGenerator( MavenProject project, Locale locale ) { @@ -96,31 +98,35 @@ public class PluginXdocGenerator } } - /** {@inheritDoc} */ - public void execute( File destinationDirectory, PluginDescriptor pluginDescriptor ) - throws IOException - { - execute( destinationDirectory, new DefaultPluginToolsRequest( project, pluginDescriptor ) ); - } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public void execute( File destinationDirectory, PluginToolsRequest request ) - throws IOException + throws GeneratorException { - if ( request.getPluginDescriptor().getMojos() != null ) + try { - for ( @SuppressWarnings( "unchecked" ) - Iterator it = request.getPluginDescriptor().getMojos().iterator(); it.hasNext(); ) + if ( request.getPluginDescriptor().getMojos() != null ) { - MojoDescriptor descriptor = it.next(); + for ( @SuppressWarnings( "unchecked" ) Iterator it = + request.getPluginDescriptor().getMojos().iterator(); it.hasNext(); ) + { + MojoDescriptor descriptor = it.next(); - processMojoDescriptor( descriptor, destinationDirectory ); + processMojoDescriptor( descriptor, destinationDirectory ); + } } } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } /** - * @param mojoDescriptor not null + * @param mojoDescriptor not null * @param destinationDirectory not null * @throws IOException if any */ @@ -147,7 +153,7 @@ public class PluginXdocGenerator /** * @param mojo not null - * @param ext not null + * @param ext not null * @return the output file name */ private String getMojoFilename( MojoDescriptor mojo, String ext ) @@ -157,7 +163,7 @@ public class PluginXdocGenerator /** * @param mojoDescriptor not null - * @param w not null + * @param w not null */ private void writeBody( MojoDescriptor mojoDescriptor, XMLWriter w ) { @@ -196,8 +202,8 @@ public class PluginXdocGenerator w.endElement(); //p w.startElement( "p" ); w.writeMarkup( mojoDescriptor.getPluginDescriptor().getGroupId() + ":" - + mojoDescriptor.getPluginDescriptor().getArtifactId() + ":" - + mojoDescriptor.getPluginDescriptor().getVersion() + ":" + mojoDescriptor.getGoal() ); + + mojoDescriptor.getPluginDescriptor().getArtifactId() + ":" + + mojoDescriptor.getPluginDescriptor().getVersion() + ":" + mojoDescriptor.getGoal() ); w.endElement(); //p if ( StringUtils.isNotEmpty( mojoDescriptor.getDeprecated() ) ) @@ -237,7 +243,7 @@ public class PluginXdocGenerator /** * @param mojoDescriptor not null - * @param w not null + * @param w not null */ private void writeReportNotice( MojoDescriptor mojoDescriptor, XMLWriter w ) { @@ -252,7 +258,7 @@ public class PluginXdocGenerator /** * @param mojoDescriptor not null - * @param w not null + * @param w not null */ private void writeGoalAttributes( MojoDescriptor mojoDescriptor, XMLWriter w ) { @@ -273,12 +279,12 @@ public class PluginXdocGenerator w.writeMarkup( getString( "pluginxdoc.mojodescriptor.projectRequired" ) ); w.endElement(); //li } - + if ( mojoDescriptor.isRequiresReports() ) { if ( !addedUl ) { - w.startElement( "ul" ); + w.startElement( "ul" ); addedUl = true; } w.startElement( "li" ); @@ -451,12 +457,11 @@ public class PluginXdocGenerator /** * @param mojoDescriptor not null - * @param w not null + * @param w not null */ private void writeGoalParameterTable( MojoDescriptor mojoDescriptor, XMLWriter w ) { - @SuppressWarnings( "unchecked" ) - List parameterList = mojoDescriptor.getParameters(); + @SuppressWarnings( "unchecked" ) List parameterList = mojoDescriptor.getParameters(); //remove components and read-only parameters List list = filterParameters( parameterList ); @@ -490,7 +495,7 @@ public class PluginXdocGenerator if ( parameterList != null ) { - for ( Parameter parameter : parameterList ) + for ( Parameter parameter : parameterList ) { if ( parameter.isEditable() ) { @@ -509,8 +514,8 @@ public class PluginXdocGenerator /** * @param mojoDescriptor not null - * @param parameterList not null - * @param w not null + * @param parameterList not null + * @param w not null */ private void writeParameterDetails( MojoDescriptor mojoDescriptor, List parameterList, XMLWriter w ) { @@ -570,8 +575,8 @@ public class PluginXdocGenerator w.startElement( "ul" ); addedUl = true; } - writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.since" ), - mojoDescriptor.getSince(), w ); + writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.since" ), mojoDescriptor.getSince(), + w ); } } @@ -582,8 +587,8 @@ public class PluginXdocGenerator w.startElement( "ul" ); addedUl = true; } - writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.required" ), - getString( "pluginxdoc.yes" ), w ); + writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.required" ), getString( "pluginxdoc.yes" ), + w ); } else { @@ -592,8 +597,8 @@ public class PluginXdocGenerator w.startElement( "ul" ); addedUl = true; } - writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.required" ), - getString( "pluginxdoc.no" ), w ); + writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.required" ), getString( "pluginxdoc.no" ), + w ); } if ( !addedUl && StringUtils.isNotEmpty( parameter.getExpression() ) ) @@ -628,7 +633,7 @@ public class PluginXdocGenerator /** * @param param not null * @param value could be null - * @param w not null + * @param w not null */ private void writeDetail( String param, String value, XMLWriter w ) { @@ -642,8 +647,8 @@ public class PluginXdocGenerator /** * @param mojoDescriptor not null - * @param parameterList not null - * @param w not null + * @param parameterList not null + * @param w not null */ private void writeParameterSummary( MojoDescriptor mojoDescriptor, List parameterList, XMLWriter w ) { @@ -664,11 +669,12 @@ public class PluginXdocGenerator /** * @param mojoDescriptor not null - * @param title not null - * @param parameterList not null - * @param w not null + * @param title not null + * @param parameterList not null + * @param w not null */ - private void writeParameterList( MojoDescriptor mojoDescriptor, String title, List parameterList, XMLWriter w ) + private void writeParameterList( MojoDescriptor mojoDescriptor, String title, List parameterList, + XMLWriter w ) { w.startElement( "subsection" ); w.addAttribute( "name", title ); @@ -722,9 +728,8 @@ public class PluginXdocGenerator String description; if ( StringUtils.isNotEmpty( parameter.getDeprecated() ) ) { - description = - format( "pluginxdoc.mojodescriptor.parameter.deprecated", - PluginUtils.makeHtmlValid( parameter.getDeprecated() ) ); + description = format( "pluginxdoc.mojodescriptor.parameter.deprecated", + PluginUtils.makeHtmlValid( parameter.getDeprecated() ) ); } else if ( StringUtils.isNotEmpty( parameter.getDescription() ) ) { @@ -750,7 +755,7 @@ public class PluginXdocGenerator } /** - * @param required true for required parameters, false otherwise. + * @param required true for required parameters, false otherwise. * @param parameterList not null * @return list of parameters depending the value of required */ @@ -792,21 +797,21 @@ public class PluginXdocGenerator /** * Convenience method. * - * @param key not null + * @param key not null * @param arg1 not null * @return Localized, formatted text identified by key. * @see #format(String, Object[]) */ private String format( String key, Object arg1 ) { - return format( key, new Object[] { arg1 } ); + return format( key, new Object[]{ arg1 } ); } /** * Looks up the value for key in the ResourceBundle, * then formats that value for the specified Locale using args. * - * @param key not null + * @param key not null * @param args not null * @return Localized, formatted text identified by key. */ diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java index 1d5d8a2..05a2b1c 100644 --- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java +++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java @@ -19,11 +19,6 @@ package org.apache.maven.tools.plugin.scanner; * under the License. */ -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor; @@ -36,6 +31,11 @@ import org.codehaus.plexus.logging.AbstractLogEnabled; import org.codehaus.plexus.logging.Logger; import org.codehaus.plexus.logging.console.ConsoleLogger; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * @author jdcasey */ @@ -71,14 +71,18 @@ public class DefaultMojoScanner // nop } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public void populatePluginDescriptor( MavenProject project, PluginDescriptor pluginDescriptor ) throws ExtractionException, InvalidPluginDescriptorException { populatePluginDescriptor( new DefaultPluginToolsRequest( project, pluginDescriptor ) ); } - - /** {@inheritDoc} */ + + /** + * {@inheritDoc} + */ public void populatePluginDescriptor( PluginToolsRequest request ) throws ExtractionException, InvalidPluginDescriptorException { @@ -103,7 +107,7 @@ public class DefaultMojoScanner List extractorDescriptors = extractor.execute( request ); logger.info( "Mojo extractor for language: " + language + " found " + extractorDescriptors.size() - + " mojo descriptors." ); + + " mojo descriptors." ); numMojoDescriptors += extractorDescriptors.size(); for ( MojoDescriptor descriptor : extractorDescriptors ) @@ -116,10 +120,11 @@ public class DefaultMojoScanner } } - if ( numMojoDescriptors == 0 ) + if ( numMojoDescriptors == 0 && !request.isSkipErrorNoDescriptorsFound() ) { - throw new InvalidPluginDescriptorException( "No mojo definitions were found for plugin: " - + request.getPluginDescriptor().getPluginLookupKey() + "." ); + throw new InvalidPluginDescriptorException( + "No mojo definitions were found for plugin: " + request.getPluginDescriptor().getPluginLookupKey() + + "." ); } } diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java index 94f2ada..462832d 100644 --- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java +++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java @@ -715,7 +715,7 @@ public final class PluginUtils String text; if ( preformatted > 0 ) { - text = data.replace( ' ', '\u00A0' ); + text = data; } else { diff --git a/maven-plugin-tools-api/src/main/resources/help-class-source.vm b/maven-plugin-tools-api/src/main/resources/help-class-source.vm new file mode 100644 index 0000000..1a65a62 --- /dev/null +++ b/maven-plugin-tools-api/src/main/resources/help-class-source.vm @@ -0,0 +1,340 @@ +#if ($helpPackageName.length()>0) +package ${helpPackageName}; +#end + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.codehaus.plexus.util.xml.Xpp3DomBuilder; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Display help information on maven-plugin-plugin.
Call
 mvn plugin:help -Ddetail=true -Dgoal=<goal-name>
to display parameter details. + * @author + * @version + * @goal help + * @requiresProject false + * @threadSafe + */ +public class HelpMojo + extends AbstractMojo +{ + /** + * If true, display all settable properties for each goal. + * + */ + //@Parameter( expression = "${detail}", defaultValue = "false" ) + //private boolean detail; + + /** + * The name of the goal for which to show help. If unspecified, all goals will be displayed. + * + */ + //@Parameter( expression = "${goal}" ) + //private java.lang.String goal; + + /** + * The maximum length of a display line, should be positive. + * + */ + //@Parameter( expression = "${lineLength}", defaultValue = "80" ) + //private int lineLength; + + /** + * The number of spaces per indentation level, should be positive. + * + */ + //@Parameter( expression = "${indentSize}", defaultValue = "2" ) + //private int indentSize; + +/** + * If true, display all settable properties for each goal. + * + * @parameter expression="${detail}" default-value="false" + */ +private boolean detail; + +/** + * The name of the goal for which to show help. If unspecified, all goals will be displayed. + * + * @parameter expression="${goal}" + */ +private java.lang.String goal; + +/** + * The maximum length of a display line, should be positive. + * + * @parameter expression="${lineLength}" default-value="80" + */ +private int lineLength; + +/** + * The number of spaces per indentation level, should be positive. + * + * @parameter expression="${indentSize}" default-value="2" + */ +private int indentSize; + + // groupId/artifactId/version + private String pluginDescriptorPath = "/${propertiesFilePath}"; + + private Xpp3Dom build() + throws MojoExecutionException + { + // olamy more than one pluginDescriptor in the classloader possible ? + getLog().debug("load pluginDescriptorPath: " + pluginDescriptorPath); + InputStream is = getClass().getResourceAsStream( pluginDescriptorPath ); + try + { + return Xpp3DomBuilder.build( is, "ISO-8859-1" ); + } + catch ( XmlPullParserException e ) + { + throw new MojoExecutionException( e.getMessage(), e ); + } + catch ( IOException e ) + { + throw new MojoExecutionException( e.getMessage(), e ); + } + } + + /** + * {@inheritDoc} + */ + public void execute() + throws MojoExecutionException + { + if ( lineLength <= 0 ) + { + getLog().warn( "The parameter 'lineLength' should be positive, using '80' as default." ); + lineLength = 80; + } + if ( indentSize <= 0 ) + { + getLog().warn( "The parameter 'indentSize' should be positive, using '2' as default." ); + indentSize = 2; + } + + // FIXME encoding as parameter + Xpp3Dom pluginElement = build(); + + StringBuffer sb = new StringBuffer(); + /** + * org.apache.maven.plugins + * maven-plugin-plugin + * 3.0-SNAPSHOT + */ + //append( sb, "org.apache.maven.plugins:maven-plugin-plugin:3.0-SNAPSHOT", 0 ); + append( sb, + pluginElement.getChild( "groupId" ).getValue() + ":" + pluginElement.getChild( "artifactId" ).getValue() + + ":" + pluginElement.getChild( "version" ).getValue(), 0 ); + append( sb, "", 0 ); + + //append( sb, "Maven Plugin Plugin", 0 ); + append( sb, pluginElement.getChild( "name" ).getValue(), 0 ); + //append( sb, + // "The Plugin Plugin is used to create a Maven plugin descriptor for any Mojo\'s found in the source tree, to include in the JAR. It is also used to generate Xdoc files for the Mojos as well as for updating the plugin registry, the artifact metadata and a generic help goal.", + // 1 ); + append( sb, pluginElement.getChild( "description" ).getValue(), 1 ); + append( sb, "", 0 ); + + //plugin + String goalPrefix = pluginElement.getChild( "goalPrefix" ).getValue(); + + Xpp3Dom[] mojos = pluginElement.getChild( "mojos" ).getChildren( "mojo" ); + + if ( goal == null || goal.length() <= 0 ) + { + + append( sb, "This plugin has " + mojos.length + " goals:", 0 ); + append( sb, "", 0 ); + } + + for ( Xpp3Dom mojo : mojos ) + { + String mojoGoal = mojo.getChild( "goal" ).getValue(); + Xpp3Dom configurationElement = mojo.getChild( "configuration" ); + if ( goal == null || goal.length() <= 0 || mojoGoal.equals( goal ) ) + { + append( sb, goalPrefix + ":" + mojoGoal, 0 ); + append( sb, mojo.getChild( "description" ).getValue(), 1 ); + append( sb, "", 0 ); + if ( detail ) + { + Xpp3Dom[] parameters = mojo.getChild( "parameters" ).getChildren( "parameter" ); + append( sb, "Available parameters:", 1 ); + append( sb, "", 0 ); + + append( sb, "goalPrefix", 2 ); + append( sb, "The prefix for the plugin goal.", 3 ); + append( sb, "", 0 ); + + for ( Xpp3Dom parameter : parameters ) + { + Xpp3Dom name = parameter.getChild( "name" ); + Xpp3Dom fieldConfigurationElement = configurationElement.getChild( name.getValue() ); + if ( fieldConfigurationElement != null && fieldConfigurationElement.getValue() != null ) + { + append( sb, name.getValue() + "(Default: " + configurationElement.getChild( + name.getValue() ).getAttribute( "default-value" ) + ")", 2 ); + } + + append( sb, parameter.getChild( "description" ).getValue(), 3 ); + if ( fieldConfigurationElement != null && fieldConfigurationElement.getValue() != null ) + { + append( sb, fieldConfigurationElement.getValue(), 3 ); + } + append( sb, "", 0 ); + } + } + } + } + + if ( getLog().isInfoEnabled() ) + { + getLog().info( sb.toString() ); + } + } + + /** + *

Repeat a String n times to form a new string.

+ * + * @param str String to repeat + * @param repeat number of times to repeat str + * @return String with repeated String + * @throws NegativeArraySizeException if repeat < 0 + * @throws NullPointerException if str is null + */ + private static String repeat( String str, int repeat ) + { + StringBuffer buffer = new StringBuffer( repeat * str.length() ); + + for ( int i = 0; i < repeat; i++ ) + { + buffer.append( str ); + } + + return buffer.toString(); + } + + /** + * Append a description to the buffer by respecting the indentSize and lineLength parameters. + * Note: The last character is always a new line. + * + * @param sb The buffer to append the description, not null. + * @param description The description, not null. + * @param indent The base indentation level of each line, must not be negative. + */ + private void append( StringBuffer sb, String description, int indent ) + { + for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); ) + { + sb.append( it.next().toString() ).append( '\n' ); + } + } + + /** + * Splits the specified text into lines of convenient display length. + * + * @param text The text to split into lines, must not be null. + * @param indent The base indentation level of each line, must not be negative. + * @param indentSize The size of each indentation, must not be negative. + * @param lineLength The length of the line, must not be negative. + * @return The sequence of display lines, never null. + * @throws NegativeArraySizeException if indent < 0 + */ + private static List toLines( String text, int indent, int indentSize, int lineLength ) + { + List lines = new ArrayList(); + + String ind = repeat( "\t", indent ); + String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" ); + for ( int i = 0; i < plainLines.length; i++ ) + { + toLines( lines, ind + plainLines[i], indentSize, lineLength ); + } + + return lines; + } + + /** + * Adds the specified line to the output sequence, performing line wrapping if necessary. + * + * @param lines The sequence of display lines, must not be null. + * @param line The line to add, must not be null. + * @param indentSize The size of each indentation, must not be negative. + * @param lineLength The length of the line, must not be negative. + */ + private static void toLines( List lines, String line, int indentSize, int lineLength ) + { + int lineIndent = getIndentLevel( line ); + StringBuffer buf = new StringBuffer( 256 ); + String[] tokens = line.split( " +" ); + for ( int i = 0; i < tokens.length; i++ ) + { + String token = tokens[i]; + if ( i > 0 ) + { + if ( buf.length() + token.length() >= lineLength ) + { + lines.add( buf.toString() ); + buf.setLength( 0 ); + buf.append( repeat( " ", lineIndent * indentSize ) ); + } + else + { + buf.append( ' ' ); + } + } + for ( int j = 0; j < token.length(); j++ ) + { + char c = token.charAt( j ); + if ( c == '\t' ) + { + buf.append( repeat( " ", indentSize - buf.length() % indentSize ) ); + } + else if ( c == '\u00A0' ) + { + buf.append( ' ' ); + } + else + { + buf.append( c ); + } + } + } + lines.add( buf.toString() ); + } + + /** + * Gets the indentation level of the specified line. + * + * @param line The line whose indentation level should be retrieved, must not be null. + * @return The indentation level of the line. + */ + private static int getIndentLevel( String line ) + { + int level = 0; + for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ ) + { + level++; + } + for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ ) + { + if ( line.charAt( i ) == '\t' ) + { + level++; + break; + } + } + return level; + } + + +} diff --git a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java index e987068..0087e1c 100644 --- a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java +++ b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java @@ -19,11 +19,13 @@ package org.apache.maven.tools.plugin.generator; * under the License. */ -import junit.framework.TestCase; +import org.apache.maven.model.Build; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.Parameter; import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; +import org.codehaus.plexus.PlexusTestCase; import org.codehaus.plexus.component.repository.ComponentDependency; import org.codehaus.plexus.util.FileUtils; @@ -38,7 +40,7 @@ import java.util.List; * jdcasey Exp $ */ public abstract class AbstractGeneratorTestCase - extends TestCase + extends PlexusTestCase { protected Generator generator; @@ -47,6 +49,7 @@ public abstract class AbstractGeneratorTestCase protected void setUp() throws Exception { + super.setUp(); basedir = System.getProperty( "basedir" ); } @@ -93,7 +96,25 @@ public abstract class AbstractGeneratorTestCase FileUtils.deleteDirectory( destinationDirectory ); destinationDirectory.mkdir(); - generator.execute( destinationDirectory, new DefaultPluginToolsRequest( null, pluginDescriptor ) ); + MavenProject mavenProject = new MavenProject(); + mavenProject.setGroupId( "foo" ); + mavenProject.setArtifactId( "bar" ); + mavenProject.setBuild( new Build() + { + @Override + public String getDirectory() + { + return basedir + "/target"; + } + + @Override + public String getOutputDirectory() + { + return basedir + "/target"; + } + } ); + + generator.execute( destinationDirectory, new DefaultPluginToolsRequest( mavenProject, pluginDescriptor ) ); validate( destinationDirectory ); @@ -120,8 +141,8 @@ public abstract class AbstractGeneratorTestCase catch ( Exception e ) { throw new Exception( "Cannot find " + generatorClassName + - "! Make sure your test case is named in the form ${generatorClassName}Test " + - "or override the setupPlugin() method to instantiate the mojo yourself." ); + "! Make sure your test case is named in the form ${generatorClassName}Test " + + "or override the setupPlugin() method to instantiate the mojo yourself." ); } } diff --git a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java index 78565f2..725967b 100644 --- a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java +++ b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java @@ -19,6 +19,8 @@ package org.apache.maven.tools.plugin.generator; * under the License. */ +import org.codehaus.plexus.velocity.VelocityComponent; + /** * @author Vincent Siveton * @version $Id$ @@ -27,4 +29,12 @@ public class PluginHelpGeneratorTest extends AbstractGeneratorTestCase { // inherits tests from base class + protected void setupGenerator() + throws Exception + { + + generator = + new PluginHelpGenerator().setVelocityComponent( (VelocityComponent) lookup( VelocityComponent.ROLE ) ); + + } } diff --git a/maven-plugin-tools-beanshell/pom.xml b/maven-plugin-tools-beanshell/pom.xml index 27e3e0e..ebb2863 100644 --- a/maven-plugin-tools-beanshell/pom.xml +++ b/maven-plugin-tools-beanshell/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.plugin-tools maven-plugin-tools - 2.10-SNAPSHOT + 3.0-SNAPSHOT maven-plugin-tools-beanshell diff --git a/maven-plugin-tools-java/pom.xml b/maven-plugin-tools-java/pom.xml index 1afba00..e662e87 100644 --- a/maven-plugin-tools-java/pom.xml +++ b/maven-plugin-tools-java/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.plugin-tools maven-plugin-tools - 2.10-SNAPSHOT + 3.0-SNAPSHOT maven-plugin-tools-java @@ -66,7 +66,6 @@ com.thoughtworks.qdox qdox - 1.11 @@ -77,4 +76,18 @@ + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.build.directory} + + + + + + diff --git a/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/java/JavaMojoDescriptorExtractorTest.java b/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/java/JavaMojoDescriptorExtractorTest.java index c6e18b5..77b2359 100644 --- a/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/java/JavaMojoDescriptorExtractorTest.java +++ b/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/java/JavaMojoDescriptorExtractorTest.java @@ -20,6 +20,7 @@ package org.apache.maven.tools.plugin.extractor.java; */ import junit.framework.TestCase; +import org.apache.maven.model.Build; import org.apache.maven.model.Model; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.Parameter; @@ -77,6 +78,13 @@ public class JavaMojoDescriptorExtractorTest model.setArtifactId( "maven-unitTesting-plugin" ); MavenProject project = new MavenProject( model ); + project.setBuild( new Build(){ + @Override + public String getOutputDirectory() + { + return System.getProperty( "filePath" ); + } + }); project.setFile( new File( root, "pom.xml" ) ); project.addCompileSourceRoot( new File( root, directory ).getPath() ); diff --git a/maven-plugin-tools-javadoc/pom.xml b/maven-plugin-tools-javadoc/pom.xml index 5609dca..80413ba 100644 --- a/maven-plugin-tools-javadoc/pom.xml +++ b/maven-plugin-tools-javadoc/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.plugin-tools maven-plugin-tools - 2.10-SNAPSHOT + 3.0-SNAPSHOT maven-plugin-tools-javadoc diff --git a/maven-plugin-tools-model/pom.xml b/maven-plugin-tools-model/pom.xml index e42e38e..641ccdf 100644 --- a/maven-plugin-tools-model/pom.xml +++ b/maven-plugin-tools-model/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.plugin-tools maven-plugin-tools - 2.10-SNAPSHOT + 3.0-SNAPSHOT maven-plugin-tools-model diff --git a/pom.xml b/pom.xml index 79b6cd0..f9531f2 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,4 @@ - - + - 4.0.0 @@ -31,7 +29,7 @@ org.apache.maven.plugin-tools maven-plugin-tools - 2.10-SNAPSHOT + 3.0-SNAPSHOT pom Maven Plugin Tools @@ -132,6 +130,8 @@ maven-plugin-plugin maven-plugin-tools-model maven-plugin-tools-javadoc + maven-plugin-tools-annotations + maven-plugin-annotations @@ -145,7 +145,7 @@ Jenkins - https://builds.apache.org/hudson/job/maven-plugin-tools/ + https://builds.apache.org/job/maven-plugin-tools/ @@ -155,7 +155,6 @@ - 2.10-SNAPSHOT 1.2 @@ -165,22 +164,32 @@ org.apache.maven.plugin-tools maven-plugin-tools-api - ${pluginToolsVersion} + ${project.version} org.apache.maven.plugin-tools maven-plugin-tools-model - ${pluginToolsVersion} + ${project.version} org.apache.maven.plugin-tools maven-plugin-tools-java - ${pluginToolsVersion} + ${project.version} + + + org.apache.maven.plugin-tools + maven-plugin-tools-annotations + ${project.version} + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${project.version} org.apache.maven.plugin-tools maven-plugin-tools-beanshell - ${pluginToolsVersion} + ${project.version} org.apache.maven @@ -212,13 +221,53 @@ org.codehaus.plexus plexus-utils - 2.0.5 + 3.0 org.codehaus.plexus plexus-container-default 1.0-alpha-9-stable-1 + + org.codehaus.plexus + plexus-archiver + 2.1.1 + + + org.codehaus.plexus + plexus-velocity + 1.1.8 + + + velocity + velocity + + + + + + + org.apache.velocity + velocity + 1.7 + + + + com.thoughtworks.qdox + qdox + 1.11 + + + + asm + asm + 3.3.1 + + + asm + asm-commons + 3.3.1 + org.apache.maven.plugin-testing @@ -236,6 +285,12 @@ 3.8.2 test + + org.easytesting + fest-assert + 1.4 + test +