Skip to content

Commit

Permalink
Merge pull request #130 from joh-ivu/main
Browse files Browse the repository at this point in the history
fixes issue #129 by using File in the configuration
  • Loading branch information
ascopes authored Mar 19, 2024
2 parents 41a4175 + 68dd163 commit bef4895
Show file tree
Hide file tree
Showing 6 changed files with 290 additions and 43 deletions.
17 changes: 17 additions & 0 deletions src/it/java-paths/invoker.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#
# Copyright (C) 2023 - 2024, Ashley Scopes.
#
# Licensed 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.
#

invoker.goals = clean package
90 changes: 90 additions & 0 deletions src/it/java-paths/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2023 - 2024, Ashley Scopes.
Licensed 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>example</artifactId>
<version>0.0.1-SNAPSHOT</version>

<properties>
<junit.version>5.10.1</junit.version>
<protobuf.version>4.26.0</protobuf.version>

<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<maven-surefire-plugin.version>3.2.2</maven-surefire-plugin.version>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>

<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>

<configuration>
<protocVersion>${protobuf.version}</protocVersion>
<sourceDirectories>
<sourceDirectory>${project.basedir}/src/main/other-protobuf-dir</sourceDirectory>
</sourceDirectories>
</configuration>

<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
27 changes: 27 additions & 0 deletions src/it/java-paths/src/main/other-protobuf-dir/helloworld.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// Copyright (C) 2023 - 2024, Ashley Scopes.
//
// Licensed 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.
//

syntax = "proto3";

option java_multiple_files = true;
option java_package = "org.example.helloworld";

package org.example.helloworld;

message GreetingRequest {
string name = 1;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2023 - 2024, Ashley Scopes.
*
* Licensed 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.
*/
package org.example.helloworld;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class ProtobufTest {
@Test
void generatedProtobufSourcesAreFullMessages() throws Throwable {
// When
var superClasses = new ArrayList<String>();
Class<?> superClass = GreetingRequest.class;

do {
superClasses.add(superClass.getName());
superClass = superClass.getSuperclass();
} while (superClass != null);

// Then
// GeneratedMessageV3 for protobuf-java 3.25.3 and older.
// GeneratedMessage for protobuf-java 4.26.0 and newer.
assertTrue(superClasses.contains("com.google.protobuf.GeneratedMessage"));
}

@Test
void generatedProtobufSourcesAreValid() throws Throwable {
// Given
var expectedGreetingRequest = GreetingRequest
.newBuilder()
.setName("Ashley")
.build();

// When
var baos = new ByteArrayOutputStream();
expectedGreetingRequest.writeTo(baos);
var actualGreetingRequest = GreetingRequest.parseFrom(baos.toByteArray());

assertNotEquals(0, baos.toByteArray().length);

// Then
assertEquals(expectedGreetingRequest.getName(), actualGreetingRequest.getName());
}
}
41 changes: 41 additions & 0 deletions src/it/java-paths/test.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2023 - 2024, Ashley Scopes.
*
* Licensed 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.nio.file.Path

import static org.assertj.core.api.Assertions.assertThat

Path baseDirectory = basedir.toPath().toAbsolutePath()
def generatedSourcesDir = baseDirectory.resolve("target/generated-sources/protobuf")
def classesDir = baseDirectory.resolve("target/classes")
def expectedGeneratedFiles = [
"org/example/helloworld/Helloworld",
"org/example/helloworld/GreetingRequest",
"org/example/helloworld/GreetingRequestOrBuilder",
]

assertThat(generatedSourcesDir).isDirectory()

assertThat(classesDir).isDirectory()

expectedGeneratedFiles.forEach {
assertThat(generatedSourcesDir.resolve("${it}.java"))
.exists()
.isNotEmptyFile()
assertThat(classesDir.resolve("${it}.class"))
.exists()
.isNotEmptyFile()

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@
import io.github.ascopes.protobufmavenplugin.generate.SourceCodeGenerator;
import io.github.ascopes.protobufmavenplugin.generate.SourceRootRegistrar;
import io.github.ascopes.protobufmavenplugin.platform.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
Expand Down Expand Up @@ -97,7 +100,7 @@ public abstract class AbstractGenerateMojo extends AbstractMojo {
* @since 0.0.1
*/
@Parameter
private @Nullable List<Path> sourceDirectories;
private @Nullable List<File> sourceDirectories;

/**
* Specify additional paths to import protobuf sources from on the local file system.
Expand All @@ -112,7 +115,7 @@ public abstract class AbstractGenerateMojo extends AbstractMojo {
* @since 0.1.0
*/
@Parameter
private @Nullable List<Path> additionalImportPaths;
private @Nullable List<File> additionalImportPaths;

/**
* Binary plugins to use with the protobuf compiler, sourced from a Maven repository.
Expand Down Expand Up @@ -228,7 +231,7 @@ public abstract class AbstractGenerateMojo extends AbstractMojo {
* @since 0.1.0
*/
@Parameter
private @Nullable Path outputDirectory;
private @Nullable File outputDirectory;

/**
* Whether to fail on missing sources.
Expand Down Expand Up @@ -389,37 +392,33 @@ public void execute() throws MojoExecutionException, MojoFailureException {
throw new MojoExecutionException(ex.getMessage(), ex);
}

var request = ImmutableGenerationRequest.builder()
.additionalImportPaths(nonNullList(additionalImportPaths))
.allowedDependencyScopes(allowedScopes())
.binaryMavenPlugins(nonNullList(binaryMavenPlugins))
.binaryPathPlugins(nonNullList(binaryPathPlugins))
.binaryUrlPlugins(nonNullList(binaryUrlPlugins))
.jvmMavenPlugins(nonNullList(jvmMavenPlugins))
.isCppEnabled(cppEnabled)
.isCsharpEnabled(csharpEnabled)
.isFailOnMissingSources(failOnMissingSources)
.isFatalWarnings(fatalWarnings)
.isJavaEnabled(javaEnabled)
.isKotlinEnabled(kotlinEnabled)
.isLiteEnabled(liteOnly)
.isObjcEnabled(objcEnabled)
.isPhpEnabled(phpEnabled)
.isPythonEnabled(pythonEnabled)
.isPythonStubsEnabled(pythonStubsEnabled)
.isRegisterAsCompilationRoot(registerAsCompilationRoot)
.isRubyEnabled(rubyEnabled)
.isRustEnabled(rustEnabled)
.mavenSession(session)
.outputDirectory(requireNonNullElseGet(
outputDirectory, () -> defaultOutputDirectory(session)
))
.protocVersion(protocVersion())
.sourceRootRegistrar(sourceRootRegistrar())
.sourceRoots(requireNonNullElseGet(
sourceDirectories, () -> List.of(defaultSourceDirectory(session))
))
.build();
var request = ImmutableGenerationRequest.builder()
.additionalImportPaths(nonNullList(additionalImportPaths).stream().map(File::toPath).collect(Collectors.toList()))
.allowedDependencyScopes(allowedScopes())
.binaryMavenPlugins(nonNullList(binaryMavenPlugins))
.binaryPathPlugins(nonNullList(binaryPathPlugins))
.binaryUrlPlugins(nonNullList(binaryUrlPlugins))
.jvmMavenPlugins(nonNullList(jvmMavenPlugins))
.isCppEnabled(cppEnabled)
.isCsharpEnabled(csharpEnabled)
.isFailOnMissingSources(failOnMissingSources)
.isFatalWarnings(fatalWarnings)
.isJavaEnabled(javaEnabled)
.isKotlinEnabled(kotlinEnabled)
.isLiteEnabled(liteOnly)
.isObjcEnabled(objcEnabled)
.isPhpEnabled(phpEnabled)
.isPythonEnabled(pythonEnabled)
.isPythonStubsEnabled(pythonStubsEnabled)
.isRegisterAsCompilationRoot(registerAsCompilationRoot)
.isRubyEnabled(rubyEnabled)
.isRustEnabled(rustEnabled)
.mavenSession(session)
.outputDirectory(outputDirectory())
.protocVersion(protocVersion())
.sourceRootRegistrar(sourceRootRegistrar())
.sourceRoots(sourceDirectories())
.build();

try {
if (!sourceCodeGenerator.generate(request)) {
Expand All @@ -432,7 +431,19 @@ public void execute() throws MojoExecutionException, MojoFailureException {
}
}

/**
private Path outputDirectory() {
return Optional.ofNullable(outputDirectory).map(File::toPath).orElseGet(() -> defaultOutputDirectory(session));
}

private Collection<Path> sourceDirectories() {
if(sourceDirectories != null){
return sourceDirectories.stream().map(File::toPath).collect(Collectors.toList());
}else{
return List.of(defaultSourceDirectory(session));
}
}

/**
* Provides the source root registrar for this Mojo.
*
* <p>This specifies where to attach generated sources to in order for it
Expand Down Expand Up @@ -490,18 +501,17 @@ protected void validate() {
}

// Having .jar on the output directory makes protoc generate a JAR with a
// Manifest. This will break our logic because generated7 sources will be
// Manifest. This will break our logic because generated sources will be
// inaccessible for the compilation phase later. For now, just prevent this
// edge case entirely.
// TODO: move this logic into the source generator class.
Optional.ofNullable(outputDirectory)
.flatMap(FileUtils::getFileExtension)
.filter(".jar"::equalsIgnoreCase)
.ifPresent(ext -> {
throw new IllegalArgumentException(
"The output directory cannot be a path with a JAR file extension"
);
});
.map(File::toPath)
.flatMap(FileUtils::getFileExtension)
.filter(".jar"::equalsIgnoreCase)
.ifPresent(ext -> {
throw new IllegalArgumentException("The output directory cannot be a path with a JAR file extension");
});
}

private String protocVersion() {
Expand Down

0 comments on commit bef4895

Please sign in to comment.