Moving from govendor to dep.

Vendor folder has been deleted. Use dep to regenerate vendor folder.
This commit is contained in:
Renan DelValle 2018-01-02 16:39:22 -08:00
parent 9631aa3aab
commit 03278a882b
No known key found for this signature in database
GPG key ID: C240AD6D6F443EC9
2181 changed files with 400398 additions and 346 deletions

View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<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.apache.thrift</groupId>
<artifactId>thrift-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<name>thrift-maven-plugin</name>
<version>0.10.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.14.1</version>
<configuration>
<systemPropertyVariables>
<thriftExecutable>${thrift.compiler}</thriftExecutable>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>14.0.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.0.14</version>
</dependency>
</dependencies>
<properties>
<thrift.root>${basedir}/../..</thrift.root>
<thrift.compiler>${thrift.root}/compiler/cpp/thrift</thrift.compiler>
<thrift.test.home>${thrift.root}/test</thrift.test.home>
</properties>
</project>

View file

@ -0,0 +1,377 @@
/*
* 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.
*/
package org.apache.thrift.maven;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
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.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.codehaus.plexus.util.cli.CommandLineException;
import org.codehaus.plexus.util.io.RawInputStreamFacade;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Sets.newHashSet;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.Collections.list;
import static org.codehaus.plexus.util.FileUtils.cleanDirectory;
import static org.codehaus.plexus.util.FileUtils.copyStreamToFile;
import static org.codehaus.plexus.util.FileUtils.getFiles;
/**
* Abstract Mojo implementation.
* <p/>
* This class is extended by {@link org.apache.thrift.maven.ThriftCompileMojo} and
* {@link org.apache.thrift.maven.ThriftTestCompileMojo} in order to override the specific configuration for
* compiling the main or test classes respectively.
*/
abstract class AbstractThriftMojo extends AbstractMojo {
private static final String THRIFT_FILE_SUFFIX = ".thrift";
private static final String DEFAULT_INCLUDES = "**/*" + THRIFT_FILE_SUFFIX;
/**
* The current Maven project.
*
* @parameter default-value="${project}"
* @readonly
* @required
*/
protected MavenProject project;
/**
* A helper used to add resources to the project.
*
* @component
* @required
*/
protected MavenProjectHelper projectHelper;
/**
* This is the path to the {@code thrift} executable. By default it will search the {@code $PATH}.
*
* @parameter default-value="thrift"
* @required
*/
private String thriftExecutable;
/**
* This string is passed to the {@code --gen} option of the {@code thrift} parameter. By default
* it will generate Java output. The main reason for this option is to be able to add options
* to the Java generator - if you generate something else, you're on your own.
*
* @parameter default-value="java"
*/
private String generator;
/**
* @parameter
*/
private File[] additionalThriftPathElements = new File[]{};
/**
* Since {@code thrift} cannot access jars, thrift files in dependencies are extracted to this location
* and deleted on exit. This directory is always cleaned during execution.
*
* @parameter default-value="${project.build.directory}/thrift-dependencies"
* @required
*/
private File temporaryThriftFileDirectory;
/**
* This is the path to the local maven {@code repository}.
*
* @parameter default-value="${localRepository}"
* @required
*/
private ArtifactRepository localRepository;
/**
* Set this to {@code false} to disable hashing of dependent jar paths.
* <p/>
* This plugin expands jars on the classpath looking for embedded .thrift files.
* Normally these paths are hashed (MD5) to avoid issues with long file names on windows.
* However if this property is set to {@code false} longer paths will be used.
*
* @parameter default-value="true"
* @required
*/
private boolean hashDependentPaths;
/**
* @parameter
*/
private Set<String> includes = ImmutableSet.of(DEFAULT_INCLUDES);
/**
* @parameter
*/
private Set<String> excludes = ImmutableSet.of();
/**
* @parameter
*/
private long staleMillis = 0;
/**
* @parameter
*/
private boolean checkStaleness = false;
/**
* Executes the mojo.
*/
public void execute() throws MojoExecutionException, MojoFailureException {
checkParameters();
final File thriftSourceRoot = getThriftSourceRoot();
if (thriftSourceRoot.exists()) {
try {
ImmutableSet<File> thriftFiles = findThriftFilesInDirectory(thriftSourceRoot);
final File outputDirectory = getOutputDirectory();
ImmutableSet<File> outputFiles = findGeneratedFilesInDirectory(getOutputDirectory());
if (thriftFiles.isEmpty()) {
getLog().info("No thrift files to compile.");
} else if (checkStaleness && ((lastModified(thriftFiles) + staleMillis) < lastModified(outputFiles))) {
getLog().info("Skipping compilation because target directory newer than sources.");
attachFiles();
} else {
ImmutableSet<File> derivedThriftPathElements =
makeThriftPathFromJars(temporaryThriftFileDirectory, getDependencyArtifactFiles());
outputDirectory.mkdirs();
// Quick fix to fix issues with two mvn installs in a row (ie no clean)
// cleanDirectory(outputDirectory);
Thrift thrift = new Thrift.Builder(thriftExecutable, outputDirectory)
.setGenerator(generator)
.addThriftPathElement(thriftSourceRoot)
.addThriftPathElements(derivedThriftPathElements)
.addThriftPathElements(asList(additionalThriftPathElements))
.addThriftFiles(thriftFiles)
.build();
final int exitStatus = thrift.compile();
if (exitStatus != 0) {
getLog().error("thrift failed output: " + thrift.getOutput());
getLog().error("thrift failed error: " + thrift.getError());
throw new MojoFailureException(
"thrift did not exit cleanly. Review output for more information.");
}
attachFiles();
}
} catch (IOException e) {
throw new MojoExecutionException("An IO error occurred", e);
} catch (IllegalArgumentException e) {
throw new MojoFailureException("thrift failed to execute because: " + e.getMessage(), e);
} catch (CommandLineException e) {
throw new MojoExecutionException("An error occurred while invoking thrift.", e);
}
} else {
getLog().info(format("%s does not exist. Review the configuration or consider disabling the plugin.",
thriftSourceRoot));
}
}
ImmutableSet<File> findGeneratedFilesInDirectory(File directory) throws IOException {
if (directory == null || !directory.isDirectory())
return ImmutableSet.of();
List<File> javaFilesInDirectory = getFiles(directory, "**/*.java", null);
return ImmutableSet.copyOf(javaFilesInDirectory);
}
private long lastModified(ImmutableSet<File> files) {
long result = 0;
for (File file : files) {
if (file.lastModified() > result)
result = file.lastModified();
}
return result;
}
private void checkParameters() {
checkNotNull(project, "project");
checkNotNull(projectHelper, "projectHelper");
checkNotNull(thriftExecutable, "thriftExecutable");
checkNotNull(generator, "generator");
final File thriftSourceRoot = getThriftSourceRoot();
checkNotNull(thriftSourceRoot);
checkArgument(!thriftSourceRoot.isFile(), "thriftSourceRoot is a file, not a diretory");
checkNotNull(temporaryThriftFileDirectory, "temporaryThriftFileDirectory");
checkState(!temporaryThriftFileDirectory.isFile(), "temporaryThriftFileDirectory is a file, not a directory");
final File outputDirectory = getOutputDirectory();
checkNotNull(outputDirectory);
checkState(!outputDirectory.isFile(), "the outputDirectory is a file, not a directory");
}
protected abstract File getThriftSourceRoot();
protected abstract List<Artifact> getDependencyArtifacts();
protected abstract File getOutputDirectory();
protected abstract void attachFiles();
/**
* Gets the {@link File} for each dependency artifact.
*
* @return A set of all dependency artifacts.
*/
private ImmutableSet<File> getDependencyArtifactFiles() {
Set<File> dependencyArtifactFiles = newHashSet();
for (Artifact artifact : getDependencyArtifacts()) {
dependencyArtifactFiles.add(artifact.getFile());
}
return ImmutableSet.copyOf(dependencyArtifactFiles);
}
/**
* @throws IOException
*/
ImmutableSet<File> makeThriftPathFromJars(File temporaryThriftFileDirectory, Iterable<File> classpathElementFiles)
throws IOException, MojoExecutionException {
checkNotNull(classpathElementFiles, "classpathElementFiles");
// clean the temporary directory to ensure that stale files aren't used
if (temporaryThriftFileDirectory.exists()) {
cleanDirectory(temporaryThriftFileDirectory);
}
Set<File> thriftDirectories = newHashSet();
for (File classpathElementFile : classpathElementFiles) {
// for some reason under IAM, we receive poms as dependent files
// I am excluding .xml rather than including .jar as there may be other extensions in use (sar, har, zip)
if (classpathElementFile.isFile() && classpathElementFile.canRead() &&
!classpathElementFile.getName().endsWith(".xml")) {
// create the jar file. the constructor validates.
JarFile classpathJar;
try {
classpathJar = new JarFile(classpathElementFile);
} catch (IOException e) {
throw new IllegalArgumentException(format(
"%s was not a readable artifact", classpathElementFile));
}
for (JarEntry jarEntry : list(classpathJar.entries())) {
final String jarEntryName = jarEntry.getName();
if (jarEntry.getName().endsWith(THRIFT_FILE_SUFFIX)) {
final File uncompressedCopy =
new File(new File(temporaryThriftFileDirectory,
truncatePath(classpathJar.getName())), jarEntryName);
uncompressedCopy.getParentFile().mkdirs();
copyStreamToFile(new RawInputStreamFacade(classpathJar
.getInputStream(jarEntry)), uncompressedCopy);
thriftDirectories.add(uncompressedCopy.getParentFile());
}
}
} else if (classpathElementFile.isDirectory()) {
File[] thriftFiles = classpathElementFile.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(THRIFT_FILE_SUFFIX);
}
});
if (thriftFiles.length > 0) {
thriftDirectories.add(classpathElementFile);
}
}
}
return ImmutableSet.copyOf(thriftDirectories);
}
ImmutableSet<File> findThriftFilesInDirectory(File directory) throws IOException {
checkNotNull(directory);
checkArgument(directory.isDirectory(), "%s is not a directory", directory);
List<File> thriftFilesInDirectory = getFiles(directory,
Joiner.on(",").join(includes),
Joiner.on(",").join(excludes));
return ImmutableSet.copyOf(thriftFilesInDirectory);
}
ImmutableSet<File> findThriftFilesInDirectories(Iterable<File> directories) throws IOException {
checkNotNull(directories);
Set<File> thriftFiles = newHashSet();
for (File directory : directories) {
thriftFiles.addAll(findThriftFilesInDirectory(directory));
}
return ImmutableSet.copyOf(thriftFiles);
}
/**
* Truncates the path of jar files so that they are relative to the local repository.
*
* @param jarPath the full path of a jar file.
* @return the truncated path relative to the local repository or root of the drive.
*/
String truncatePath(final String jarPath) throws MojoExecutionException {
if (hashDependentPaths) {
try {
return toHexString(MessageDigest.getInstance("MD5").digest(jarPath.getBytes()));
} catch (NoSuchAlgorithmException e) {
throw new MojoExecutionException("Failed to expand dependent jar", e);
}
}
String repository = localRepository.getBasedir().replace('\\', '/');
if (!repository.endsWith("/")) {
repository += "/";
}
String path = jarPath.replace('\\', '/');
int repositoryIndex = path.indexOf(repository);
if (repositoryIndex != -1) {
path = path.substring(repositoryIndex + repository.length());
}
// By now the path should be good, but do a final check to fix windows machines.
int colonIndex = path.indexOf(':');
if (colonIndex != -1) {
// 2 = :\ in C:\
path = path.substring(colonIndex + 2);
}
return path;
}
private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();
public static String toHexString(byte[] byteArray) {
final StringBuilder hexString = new StringBuilder(2 * byteArray.length);
for (final byte b : byteArray) {
hexString.append(HEX_CHARS[(b & 0xF0) >> 4]).append(HEX_CHARS[b & 0x0F]);
}
return hexString.toString();
}
}

View file

@ -0,0 +1,262 @@
/*
* 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.
*/
package org.apache.thrift.maven;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.codehaus.plexus.util.cli.CommandLineException;
import org.codehaus.plexus.util.cli.CommandLineUtils;
import org.codehaus.plexus.util.cli.Commandline;
import java.io.File;
import java.util.List;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Lists.newLinkedList;
import static com.google.common.collect.Sets.newHashSet;
/**
* This class represents an invokable configuration of the {@code thrift}
* compiler. The actual executable is invoked using the plexus
* {@link Commandline}.
* <p/>
* This class currently only supports generating java source files.
*/
final class Thrift {
final static String GENERATED_JAVA = "gen-java";
private final String executable;
private final String generator;
private final ImmutableSet<File> thriftPathElements;
private final ImmutableSet<File> thriftFiles;
private final File javaOutputDirectory;
private final CommandLineUtils.StringStreamConsumer output;
private final CommandLineUtils.StringStreamConsumer error;
/**
* Constructs a new instance. This should only be used by the {@link Builder}.
*
* @param executable The path to the {@code thrift} executable.
* @param generator The value for the {@code --gen} option.
* @param thriftPath The directories in which to search for imports.
* @param thriftFiles The thrift source files to compile.
* @param javaOutputDirectory The directory into which the java source files
* will be generated.
*/
private Thrift(String executable, String generator, ImmutableSet<File> thriftPath,
ImmutableSet<File> thriftFiles, File javaOutputDirectory) {
this.executable = checkNotNull(executable, "executable");
this.generator = checkNotNull(generator, "generator");
this.thriftPathElements = checkNotNull(thriftPath, "thriftPath");
this.thriftFiles = checkNotNull(thriftFiles, "thriftFiles");
this.javaOutputDirectory = checkNotNull(javaOutputDirectory, "javaOutputDirectory");
this.error = new CommandLineUtils.StringStreamConsumer();
this.output = new CommandLineUtils.StringStreamConsumer();
}
/**
* Invokes the {@code thrift} compiler using the configuration specified at
* construction.
*
* @return The exit status of {@code thrift}.
* @throws CommandLineException
*/
public int compile() throws CommandLineException {
for (File thriftFile : thriftFiles) {
Commandline cl = new Commandline();
cl.setExecutable(executable);
cl.addArguments(buildThriftCommand(thriftFile).toArray(new String[]{}));
final int result = CommandLineUtils.executeCommandLine(cl, null, output, error);
if (result != 0) {
return result;
}
}
// result will always be 0 here.
return 0;
}
/**
* Creates the command line arguments.
* <p/>
* This method has been made visible for testing only.
*
* @param thriftFile
* @return A list consisting of the executable followed by any arguments.
*/
ImmutableList<String> buildThriftCommand(final File thriftFile) {
final List<String> command = newLinkedList();
// add the executable
for (File thriftPathElement : thriftPathElements) {
command.add("-I");
command.add(thriftPathElement.toString());
}
command.add("-out");
command.add(javaOutputDirectory.toString());
command.add("--gen");
command.add(generator);
command.add(thriftFile.toString());
return ImmutableList.copyOf(command);
}
/**
* @return the output
*/
public String getOutput() {
return output.getOutput();
}
/**
* @return the error
*/
public String getError() {
return error.getOutput();
}
/**
* This class builds {@link Thrift} instances.
*/
static final class Builder {
private final String executable;
private final File javaOutputDirectory;
private Set<File> thriftPathElements;
private Set<File> thriftFiles;
private String generator;
/**
* Constructs a new builder. The two parameters are present as they are
* required for all {@link Thrift} instances.
*
* @param executable The path to the {@code thrift} executable.
* @param javaOutputDirectory The directory into which the java source files
* will be generated.
* @throws NullPointerException If either of the arguments are {@code null}.
* @throws IllegalArgumentException If the {@code javaOutputDirectory} is
* not a directory.
*/
public Builder(String executable, File javaOutputDirectory) {
this.executable = checkNotNull(executable, "executable");
this.javaOutputDirectory = checkNotNull(javaOutputDirectory);
checkArgument(javaOutputDirectory.isDirectory());
this.thriftFiles = newHashSet();
this.thriftPathElements = newHashSet();
}
/**
* Adds a thrift file to be compiled. Thrift files must be on the thriftpath
* and this method will fail if a thrift file is added without first adding a
* parent directory to the thriftpath.
*
* @param thriftFile
* @return The builder.
* @throws IllegalStateException If a thrift file is added without first
* adding a parent directory to the thriftpath.
* @throws NullPointerException If {@code thriftFile} is {@code null}.
*/
public Builder addThriftFile(File thriftFile) {
checkNotNull(thriftFile);
checkArgument(thriftFile.isFile());
checkArgument(thriftFile.getName().endsWith(".thrift"));
checkThriftFileIsInThriftPath(thriftFile);
thriftFiles.add(thriftFile);
return this;
}
/**
* Adds the option string for the Thrift executable's {@code --gen} parameter.
*
* @param generator
* @return The builder
* @throws NullPointerException If {@code generator} is {@code null}.
*/
public Builder setGenerator(String generator) {
checkNotNull(generator);
this.generator = generator;
return this;
}
private void checkThriftFileIsInThriftPath(File thriftFile) {
assert thriftFile.isFile();
checkState(checkThriftFileIsInThriftPathHelper(thriftFile.getParentFile()));
}
private boolean checkThriftFileIsInThriftPathHelper(File directory) {
assert directory.isDirectory();
if (thriftPathElements.contains(directory)) {
return true;
} else {
final File parentDirectory = directory.getParentFile();
return (parentDirectory == null) ? false
: checkThriftFileIsInThriftPathHelper(parentDirectory);
}
}
/**
* @see #addThriftFile(File)
*/
public Builder addThriftFiles(Iterable<File> thriftFiles) {
for (File thriftFile : thriftFiles) {
addThriftFile(thriftFile);
}
return this;
}
/**
* Adds the {@code thriftPathElement} to the thriftPath.
*
* @param thriftPathElement A directory to be searched for imported thrift message
* buffer definitions.
* @return The builder.
* @throws NullPointerException If {@code thriftPathElement} is {@code null}.
* @throws IllegalArgumentException If {@code thriftPathElement} is not a
* directory.
*/
public Builder addThriftPathElement(File thriftPathElement) {
checkNotNull(thriftPathElement);
checkArgument(thriftPathElement.isDirectory());
thriftPathElements.add(thriftPathElement);
return this;
}
/**
* @see #addThriftPathElement(File)
*/
public Builder addThriftPathElements(Iterable<File> thriftPathElements) {
for (File thriftPathElement : thriftPathElements) {
addThriftPathElement(thriftPathElement);
}
return this;
}
/**
* @return A configured {@link Thrift} instance.
* @throws IllegalStateException If no thrift files have been added.
*/
public Thrift build() {
checkState(!thriftFiles.isEmpty());
return new Thrift(executable, generator, ImmutableSet.copyOf(thriftPathElements),
ImmutableSet.copyOf(thriftFiles), javaOutputDirectory);
}
}
}

View file

@ -0,0 +1,78 @@
/*
* 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.
*/
package org.apache.thrift.maven;
import java.io.File;
import java.util.List;
import org.apache.maven.artifact.Artifact;
import com.google.common.collect.ImmutableList;
/**
* This mojo executes the {@code thrift} compiler for generating java sources
* from thrift definitions. It also searches dependency artifacts for
* thrift files and includes them in the thriftPath so that they can be
* referenced. Finally, it adds the thrift files to the project as resources so
* that they are included in the final artifact.
*
* @phase generate-sources
* @goal compile
* @requiresDependencyResolution compile
*/
public final class ThriftCompileMojo extends AbstractThriftMojo {
/**
* The source directories containing the sources to be compiled.
*
* @parameter default-value="${basedir}/src/main/thrift"
* @required
*/
private File thriftSourceRoot;
/**
* This is the directory into which the {@code .java} will be created.
*
* @parameter default-value="${project.build.directory}/generated-sources/thrift"
* @required
*/
private File outputDirectory;
@Override
protected List<Artifact> getDependencyArtifacts() {
List<Artifact> compileArtifacts = project.getCompileArtifacts();
return compileArtifacts;
}
@Override
protected File getOutputDirectory() {
return outputDirectory;
}
@Override
protected File getThriftSourceRoot() {
return thriftSourceRoot;
}
@Override
protected void attachFiles() {
project.addCompileSourceRoot(outputDirectory.getAbsolutePath());
projectHelper.addResource(project, thriftSourceRoot.getAbsolutePath(),
ImmutableList.of("**/*.thrift"), null);
}
}

View file

@ -0,0 +1,74 @@
/*
* 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.
*/
package org.apache.thrift.maven;
import java.io.File;
import java.util.List;
import org.apache.maven.artifact.Artifact;
import com.google.common.collect.ImmutableList;
/**
* @phase generate-test-sources
* @goal testCompile
* @requiresDependencyResolution test
*/
public final class ThriftTestCompileMojo extends AbstractThriftMojo {
/**
* The source directories containing the sources to be compiled.
*
* @parameter default-value="${basedir}/src/test/thrift"
* @required
*/
private File thriftTestSourceRoot;
/**
* This is the directory into which the {@code .java} will be created.
*
* @parameter default-value="${project.build.directory}/generated-test-sources/thrift"
* @required
*/
private File outputDirectory;
@Override
protected void attachFiles() {
project.addTestCompileSourceRoot(outputDirectory.getAbsolutePath());
projectHelper.addTestResource(project, thriftTestSourceRoot.getAbsolutePath(),
ImmutableList.of("**/*.thrift"), null);
}
@Override
protected List<Artifact> getDependencyArtifacts() {
// TODO(gak): maven-project needs generics
@SuppressWarnings("unchecked")
List<Artifact> testArtifacts = project.getTestArtifacts();
return testArtifacts;
}
@Override
protected File getOutputDirectory() {
return outputDirectory;
}
@Override
protected File getThriftSourceRoot() {
return thriftTestSourceRoot;
}
}

View file

@ -0,0 +1,163 @@
/*
* 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.
*/
package org.apache.thrift.maven;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.cli.CommandLineException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class TestThrift {
private File testRootDir;
private File idlDir;
private File genJavaDir;
private Thrift.Builder builder;
@Before
public void setup() throws Exception {
final File tmpDir = new File(System.getProperty("java.io.tmpdir"));
testRootDir = new File(tmpDir, "thrift-test");
if (testRootDir.exists()) {
FileUtils.cleanDirectory(testRootDir);
} else {
assertTrue("Failed to create output directory for test: " + testRootDir.getPath(), testRootDir.mkdir());
}
File testResourceDir = new File("src/test/resources");
assertTrue("Unable to find test resources", testRootDir.exists());
String thriftExecutable = System.getProperty("thriftExecutable", "thrift");
if (!(new File(thriftExecutable).exists())) {
thriftExecutable = "thrift";
}
System.out.println("Thrift compiler: " + thriftExecutable);
idlDir = new File(testResourceDir, "idl");
genJavaDir = new File(testRootDir, Thrift.GENERATED_JAVA);
builder = new Thrift.Builder(thriftExecutable, testRootDir);
builder
.setGenerator("java")
.addThriftPathElement(idlDir);
}
@Test
public void testThriftCompile() throws Exception {
executeThriftCompile();
}
@Test
public void testThriftCompileWithGeneratorOption() throws Exception {
builder.setGenerator("java:private-members");
executeThriftCompile();
}
private void executeThriftCompile() throws CommandLineException {
final File thriftFile = new File(idlDir, "shared.thrift");
builder.addThriftFile(thriftFile);
final Thrift thrift = builder.build();
assertTrue("File not found: shared.thrift", thriftFile.exists());
assertFalse("gen-java directory should not exist", genJavaDir.exists());
// execute the compile
final int result = thrift.compile();
assertEquals(0, result);
assertFalse("gen-java directory was not removed", genJavaDir.exists());
assertTrue("generated java code doesn't exist",
new File(testRootDir, "shared/SharedService.java").exists());
}
@Test
public void testThriftMultipleFileCompile() throws Exception {
final File sharedThrift = new File(idlDir, "shared.thrift");
final File tutorialThrift = new File(idlDir, "tutorial.thrift");
builder.addThriftFile(sharedThrift);
builder.addThriftFile(tutorialThrift);
final Thrift thrift = builder.build();
assertTrue("File not found: shared.thrift", sharedThrift.exists());
assertFalse("gen-java directory should not exist", genJavaDir.exists());
// execute the compile
final int result = thrift.compile();
assertEquals(0, result);
assertFalse("gen-java directory was not removed", genJavaDir.exists());
assertTrue("generated java code doesn't exist",
new File(testRootDir, "shared/SharedService.java").exists());
assertTrue("generated java code doesn't exist",
new File(testRootDir, "tutorial/InvalidOperation.java").exists());
}
@Test
public void testBadCompile() throws Exception {
final File thriftFile = new File(testRootDir, "missing.thrift");
builder.addThriftPathElement(testRootDir);
// Hacking around checks in addThrift file.
assertTrue(thriftFile.createNewFile());
builder.addThriftFile(thriftFile);
assertTrue(thriftFile.delete());
final Thrift thrift = builder.build();
assertTrue(!thriftFile.exists());
assertFalse("gen-java directory should not exist", genJavaDir.exists());
// execute the compile
final int result = thrift.compile();
assertEquals(1, result);
}
@Test
public void testFileInPathPreCondition() throws Exception {
final File thriftFile = new File(testRootDir, "missing.thrift");
// Hacking around checks in addThrift file.
assertTrue(thriftFile.createNewFile());
try {
builder.addThriftFile(thriftFile);
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
}
}
@After
public void cleanup() throws Exception {
if (testRootDir.exists()) {
FileUtils.cleanDirectory(testRootDir);
assertTrue("Failed to delete output directory for test: " + testRootDir.getPath(), testRootDir.delete());
}
}
}

View file

@ -0,0 +1,36 @@
/*
* 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.
*/
/**
* This Thrift file can be included by other Thrift files that want to share
* these definitions.
*/
namespace cpp shared
namespace java shared
namespace perl shared
struct SharedStruct {
1: i32 key
2: string value
}
service SharedService {
SharedStruct getStruct(1: i32 key)
}

View file

@ -0,0 +1,152 @@
/*
* 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.
*/
# Thrift Tutorial
# Mark Slee (mcslee@facebook.com)
#
# This file aims to teach you how to use Thrift, in a .thrift file. Neato. The
# first thing to notice is that .thrift files support standard shell comments.
# This lets you make your thrift file executable and include your Thrift build
# step on the top line. And you can place comments like this anywhere you like.
#
# Before running this file, you will need to have installed the thrift compiler
# into /usr/local/bin.
/**
* The first thing to know about are types. The available types in Thrift are:
*
* bool Boolean, one byte
* byte Signed byte
* i16 Signed 16-bit integer
* i32 Signed 32-bit integer
* i64 Signed 64-bit integer
* double 64-bit floating point value
* string String
* binary Blob (byte array)
* map<t1,t2> Map from one type to another
* list<t1> Ordered list of one type
* set<t1> Set of unique elements of one type
*
* Did you also notice that Thrift supports C style comments?
*/
// Just in case you were wondering... yes. We support simple C comments too.
/**
* Thrift files can reference other Thrift files to include common struct
* and service definitions. These are found using the current path, or by
* searching relative to any paths specified with the -I compiler flag.
*
* Included objects are accessed using the name of the .thrift file as a
* prefix. i.e. shared.SharedObject
*/
include "shared.thrift"
/**
* Thrift files can namespace, package, or prefix their output in various
* target languages.
*/
namespace cpp tutorial
namespace java tutorial
namespace php tutorial
namespace perl tutorial
namespace smalltalk.category Thrift.Tutorial
/**
* Thrift lets you do typedefs to get pretty names for your types. Standard
* C style here.
*/
typedef i32 MyInteger
/**
* Thrift also lets you define constants for use across languages. Complex
* types and structs are specified using JSON notation.
*/
const i32 INT32CONSTANT = 9853
const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}
/**
* You can define enums, which are just 32 bit integers. Values are optional
* and start at 1 if not supplied, C style again.
*/
enum Operation {
ADD = 1,
SUBTRACT = 2,
MULTIPLY = 3,
DIVIDE = 4
}
/**
* Structs are the basic complex data structures. They are comprised of fields
* which each have an integer identifier, a type, a symbolic name, and an
* optional default value.
*
* Fields can be declared "optional", which ensures they will not be included
* in the serialized output if they aren't set. Note that this requires some
* manual management in some languages.
*/
struct Work {
1: i32 num1 = 0,
2: i32 num2,
3: Operation op,
4: optional string comment,
}
/**
* Structs can also be exceptions, if they are nasty.
*/
exception InvalidOperation {
1: i32 what,
2: string why
}
/**
* Ahh, now onto the cool part, defining a service. Services just need a name
* and can optionally inherit from another service using the extends keyword.
*/
service Calculator extends shared.SharedService {
/**
* A method definition looks like C code. It has a return type, arguments,
* and optionally a list of exceptions that it may throw. Note that argument
* lists and exception lists are specified using the exact same syntax as
* field lists in struct or exception definitions.
*/
void ping(),
i32 add(1:i32 num1, 2:i32 num2),
i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),
/**
* This method has a oneway modifier. That means the client only makes
* a request and does not listen for any response at all. Oneway methods
* must be void.
*/
oneway void zip()
}
/**
* That just about covers the basics. Take a look in the test/ folder for more
* detailed examples. After you run this file, your generated code shows up
* in folders with names gen-<language>. The generated code isn't too scary
* to look at. It even has pretty indentation.
*/