diff --git a/src/it/TEST-26/invoker.properties b/src/it/TEST-26/invoker.properties new file mode 100644 index 00000000..9ff2b87f --- /dev/null +++ b/src/it/TEST-26/invoker.properties @@ -0,0 +1,6 @@ +# An optional description for this build job to be included in the build reports. +invoker.description = Verifies that javanano generation works + +# A comma or space separated list of goals/phases to execute, may +# specify an empty list to execute the default goal of the IT project +invoker.goals = clean generate-sources diff --git a/src/it/TEST-26/pom.xml b/src/it/TEST-26/pom.xml new file mode 100644 index 00000000..2d8106cb --- /dev/null +++ b/src/it/TEST-26/pom.xml @@ -0,0 +1,48 @@ + + + + + 4.0.0 + + + com.google.protobuf.tools.maven-protoc-plugin.its + it-parent + 0.0.1-SNAPSHOT + + + TEST-26 + 0.0.1-SNAPSHOT + + Integration Test 26 + + + + + kr.motd.maven + os-maven-plugin + 1.3.0.Final + + + + + + com.google.protobuf.tools + maven-protoc-plugin + @project.version@ + + + + compile-javanano + + + com.google.protobuf:protoc:2.6.1:exe:${os.detected.classifier} + + + + + + + + diff --git a/src/it/TEST-26/src/main/proto/test.proto b/src/it/TEST-26/src/main/proto/test.proto new file mode 100644 index 00000000..b4708ff8 --- /dev/null +++ b/src/it/TEST-26/src/main/proto/test.proto @@ -0,0 +1,8 @@ +package integration_test; + +option java_package = "test"; +option java_outer_classname = "TestProtos"; +option parcelable_messages = true; + +message TestMessage { +} diff --git a/src/it/TEST-26/verify.groovy b/src/it/TEST-26/verify.groovy new file mode 100644 index 00000000..216d4569 --- /dev/null +++ b/src/it/TEST-26/verify.groovy @@ -0,0 +1,14 @@ +outputDirectory = new File(basedir, 'target/generated-sources/protobuf/javanano'); +assert outputDirectory.exists(); +assert outputDirectory.isDirectory(); + +generatedJavaFile = new File(outputDirectory, 'test/TestProtos.java'); +assert generatedJavaFile.exists(); +assert generatedJavaFile.isFile(); + +content = generatedJavaFile.text; +assert content.contains('package test'); +assert content.contains('class Test'); +assert content.contains('class TestMessage'); + +return true; diff --git a/src/main/java/com/google/protobuf/maven/AbstractProtocMojo.java b/src/main/java/com/google/protobuf/maven/AbstractProtocMojo.java index c1db9471..112b4308 100644 --- a/src/main/java/com/google/protobuf/maven/AbstractProtocMojo.java +++ b/src/main/java/com/google/protobuf/maven/AbstractProtocMojo.java @@ -507,6 +507,10 @@ public void execute() throws MojoExecutionException, MojoFailureException { } if (exitStatus != 0) { getLog().error("PROTOC FAILED: " + protoc.getError()); + for( File pf : protoFiles ) { + buildContext.removeMessages( pf ); + buildContext.addMessage( pf, 0, 0, protoc.getError(), BuildContext.SEVERITY_ERROR, null); + } throw new MojoFailureException( "protoc did not exit cleanly. Review output for more information."); } else if (StringUtils.isNotBlank(protoc.getError())) { diff --git a/src/main/java/com/google/protobuf/maven/Protoc.java b/src/main/java/com/google/protobuf/maven/Protoc.java index 38013f48..53660ed9 100644 --- a/src/main/java/com/google/protobuf/maven/Protoc.java +++ b/src/main/java/com/google/protobuf/maven/Protoc.java @@ -52,6 +52,11 @@ final class Protoc { */ private final File javaOutputDirectory; + /** + * A directory into which JavaNano source files will be generated. + */ + private final File javaNanoOutputDirectory; + private final ImmutableSet plugins; private final File pluginDirectory; @@ -98,6 +103,7 @@ final class Protoc { * @param protoPath a set of directories in which to search for definition imports. * @param protoFiles a set of protobuf definitions to process. * @param javaOutputDirectory a directory into which Java source files will be generated. + * @param javaNanoOutputDirectory a directory into which JavaNano source files will be generated. * @param cppOutputDirectory a directory into which C++ source files will be generated. * @param pythonOutputDirectory a directory into which Python source files will be generated. * @param customOutputDirectory a directory into which a custom protoc plugin will generate files. @@ -115,6 +121,7 @@ private Protoc( final ImmutableSet protoPath, final ImmutableSet protoFiles, final File javaOutputDirectory, + final File javaNanoOutputDirectory, final File cppOutputDirectory, final File pythonOutputDirectory, final File customOutputDirectory, @@ -129,6 +136,7 @@ private Protoc( this.protoPathElements = checkNotNull(protoPath, "protoPath"); this.protoFiles = checkNotNull(protoFiles, "protoFiles"); this.javaOutputDirectory = javaOutputDirectory; + this.javaNanoOutputDirectory = javaNanoOutputDirectory; this.cppOutputDirectory = cppOutputDirectory; this.pythonOutputDirectory = pythonOutputDirectory; this.customOutputDirectory = customOutputDirectory; @@ -179,6 +187,9 @@ public ImmutableList buildProtocCommand() { command.add("--" + plugin.getId() + "_out=" + javaOutputDirectory); } } + if (javaNanoOutputDirectory != null) { + command.add("--javanano_out=" + javaNanoOutputDirectory); + } if (cppOutputDirectory != null) { command.add("--cpp_out=" + cppOutputDirectory); } @@ -244,6 +255,10 @@ public void logExecutionParameters(final Log log) { log.debug(LOG_PREFIX + ' ' + pluginDirectory); } + if (javaNanoOutputDirectory != null) { + log.debug(LOG_PREFIX + "Java Nano output directory:"); + log.debug(LOG_PREFIX + ' ' + javaNanoOutputDirectory); + } if (cppOutputDirectory != null) { log.debug(LOG_PREFIX + "C++ output directory:"); log.debug(LOG_PREFIX + ' ' + cppOutputDirectory); @@ -322,6 +337,11 @@ static final class Builder { */ private File javaOutputDirectory; + /** + * A directory into which Java Nano source files will be generated. + */ + private File javaNanoOutputDirectory; + /** * A directory into which C++ source files will be generated. */ @@ -370,6 +390,22 @@ public Builder setJavaOutputDirectory(final File javaOutputDirectory) { return this; } + /** + * Sets the directory into which JavaNano source files will be generated. + * + * @param javaNanoOutputDirectory a directory into which Java source files will be generated. + * @return this builder instance. + * @throws NullPointerException if {@code javaNanoOutputDirectory} is {@code null}. + * @throws IllegalArgumentException if {@code javaNanoOutputDirectory} is not a directory. + */ + public Builder setJavaNanoOutputDirectory(final File javaNanoOutputDirectory) { + this.javaNanoOutputDirectory = checkNotNull(javaNanoOutputDirectory, "'javaNanoOutputDirectory' is null"); + checkArgument( + javaNanoOutputDirectory.isDirectory(), + "'javaNanoOutputDirectory' is not a directory: " + javaNanoOutputDirectory); + return this; + } + /** * Sets the directory into which C++ source files will be generated. * @@ -461,6 +497,7 @@ public void setNativePluginId(final String nativePluginId) { checkArgument(!nativePluginId.isEmpty(), "'nativePluginId' is empty"); checkArgument( !(nativePluginId.equals("java") + || nativePluginId.equals("javanano") || nativePluginId.equals("python") || nativePluginId.equals("cpp") || nativePluginId.equals("descriptor_set")), @@ -552,11 +589,12 @@ public Builder addProtoPathElements(final Iterable protopathElements) { private void validateState() { checkState(!protoFiles.isEmpty()); checkState(javaOutputDirectory != null + || javaNanoOutputDirectory != null || cppOutputDirectory != null || pythonOutputDirectory != null || customOutputDirectory != null, "At least one of these properties must be set: " + - "'javaOutputDirectory', 'cppOutputDirectory', " + + "'javaOutputDirectory', 'javaNanoOutputDirectory', 'cppOutputDirectory', " + "'pythonOutputDirectory' or 'customOutputDirectory'"); } @@ -573,6 +611,7 @@ public Protoc build() { ImmutableSet.copyOf(protopathElements), ImmutableSet.copyOf(protoFiles), javaOutputDirectory, + javaNanoOutputDirectory, cppOutputDirectory, pythonOutputDirectory, customOutputDirectory, diff --git a/src/main/java/com/google/protobuf/maven/ProtocCompileJavaNanoMojo.java b/src/main/java/com/google/protobuf/maven/ProtocCompileJavaNanoMojo.java new file mode 100644 index 00000000..72848ecf --- /dev/null +++ b/src/main/java/com/google/protobuf/maven/ProtocCompileJavaNanoMojo.java @@ -0,0 +1,47 @@ +package com.google.protobuf.maven; + +import java.io.File; + +import org.apache.maven.plugin.MojoExecutionException; +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.annotations.ResolutionScope; + +/** + * This mojo executes the {@code protoc} compiler for generating main Java sources + * from protocol buffer definitions. It also searches dependency artifacts for + * {@code .proto} files and includes them in the {@code proto_path} so that they can be + * referenced. Finally, it adds the {@code .proto} files to the project as resources so + * that they are included in the final artifact. + * + * @since 0.4.3 + */ +@Mojo( + name = "compile-javanano", + defaultPhase = LifecyclePhase.GENERATE_SOURCES, + requiresDependencyResolution = ResolutionScope.COMPILE, + threadSafe = true +) +public final class ProtocCompileJavaNanoMojo extends AbstractProtocCompileMojo { + + /** + * This is the directory into which the {@code .java} will be created. + */ + @Parameter( + required = true, + defaultValue = "${project.build.directory}/generated-sources/protobuf/javanano" + ) + private File outputDirectory; + + @Override + protected void addProtocBuilderParameters(final Protoc.Builder protocBuilder) throws MojoExecutionException { + super.addProtocBuilderParameters(protocBuilder); + protocBuilder.setJavaNanoOutputDirectory(getOutputDirectory()); + } + + @Override + protected File getOutputDirectory() { + return outputDirectory; + } +} diff --git a/src/main/java/com/google/protobuf/maven/ProtocTestCompileJavaNanoMojo.java b/src/main/java/com/google/protobuf/maven/ProtocTestCompileJavaNanoMojo.java new file mode 100644 index 00000000..38aebf33 --- /dev/null +++ b/src/main/java/com/google/protobuf/maven/ProtocTestCompileJavaNanoMojo.java @@ -0,0 +1,53 @@ +package com.google.protobuf.maven; + +import java.io.File; + +import org.apache.maven.plugin.MojoExecutionException; +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.annotations.ResolutionScope; + +/** + * This mojo executes the {@code protoc} compiler for generating test Java sources + * from protocol buffer definitions. It also searches dependency artifacts in the test scope for + * {@code .proto} files and includes them in the {@code proto_path} so that they can be + * referenced. Finally, it adds the {@code .proto} files to the project as test resources so + * that they can be included in the test-jar artifact. + * + * @since 0.4.3 + */ +@Mojo( + name = "test-compile-javanano", + defaultPhase = LifecyclePhase.GENERATE_TEST_SOURCES, + requiresDependencyResolution = ResolutionScope.TEST, + threadSafe = true +) +public class ProtocTestCompileJavaNanoMojo extends AbstractProtocTestCompileMojo { + + /** + * This is the directory into which the {@code .java} test sources will be created. + */ + @Parameter( + required = true, + defaultValue = "${project.build.directory}/generated-test-sources/protobuf/javanano" + ) + private File outputDirectory; + + @Override + protected void addProtocBuilderParameters(final Protoc.Builder protocBuilder) throws MojoExecutionException { + super.addProtocBuilderParameters(protocBuilder); + protocBuilder.setJavaNanoOutputDirectory(getOutputDirectory()); + // We need to add project output directory to the protobuf import paths, + // in case test protobuf definitions extend or depend on production ones + final File buildOutputDirectory = new File(project.getBuild().getOutputDirectory()); + if (buildOutputDirectory.exists()) { + protocBuilder.addProtoPathElement(buildOutputDirectory); + } + } + + @Override + protected File getOutputDirectory() { + return outputDirectory; + } +} diff --git a/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml b/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml index 0d2ecaad..cee4f55b 100644 --- a/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml +++ b/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml @@ -11,6 +11,8 @@ compile-python test-compile-python testCompile + compile-javanano + test-compile-javanano