Moving from govendor to dep, updated dependencies (#48)

* Moving from govendor to dep.

* Making the pull request template more friendly.

* Fixing akward space in PR template.

* goimports run on whole project using ` goimports -w $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./gen-go/*")`

source of command: https://gist.github.com/bgentry/fd1ffef7dbde01857f66
This commit is contained in:
Renan DelValle 2018-01-07 13:13:47 -08:00 committed by GitHub
parent 9631aa3aab
commit 8d445c1c77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2186 changed files with 400410 additions and 352 deletions

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.
*/