summaryrefslogtreecommitdiffstats
path: root/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/AbstractThriftMojo.java380
-rw-r--r--src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/Thrift.java262
-rw-r--r--src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/ThriftCompileMojo.java78
-rw-r--r--src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/ThriftTestCompileMojo.java93
4 files changed, 813 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/AbstractThriftMojo.java b/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/AbstractThriftMojo.java
new file mode 100644
index 000000000..869be95e4
--- /dev/null
+++ b/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/AbstractThriftMojo.java
@@ -0,0 +1,380 @@
+/*
+ * 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
+ */
+ protected 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
+ */
+ protected 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 directory");
+ 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));
+ }
+
+ /**
+ * Copy each .thrift file found in the JAR into a temporary directory, preserving the
+ * directory path it had relative to its containing JAR. Add the resulting root directory
+ * (unique for each JAR processed) to the set of thrift include directories to use when
+ * compiling.
+ */
+ for (JarEntry jarEntry : list(classpathJar.entries())) {
+ final String jarEntryName = jarEntry.getName();
+ if (jarEntry.getName().endsWith(THRIFT_FILE_SUFFIX)) {
+ final String truncatedJarPath = truncatePath(classpathJar.getName());
+ final File thriftRootDirectory = new File(temporaryThriftFileDirectory, truncatedJarPath);
+ final File uncompressedCopy =
+ new File(thriftRootDirectory, jarEntryName);
+ uncompressedCopy.getParentFile().mkdirs();
+ copyStreamToFile(new RawInputStreamFacade(classpathJar
+ .getInputStream(jarEntry)), uncompressedCopy);
+ thriftDirectories.add(thriftRootDirectory);
+ }
+ }
+
+ } 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);
+ }
+
+ /**
+ * 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();
+ }
+}
diff --git a/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/Thrift.java b/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/Thrift.java
new file mode 100644
index 000000000..6eea95448
--- /dev/null
+++ b/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/Thrift.java
@@ -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);
+ }
+ }
+}
diff --git a/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/ThriftCompileMojo.java b/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/ThriftCompileMojo.java
new file mode 100644
index 000000000..b4f75714b
--- /dev/null
+++ b/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/ThriftCompileMojo.java
@@ -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);
+ }
+}
diff --git a/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/ThriftTestCompileMojo.java b/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/ThriftTestCompileMojo.java
new file mode 100644
index 000000000..1b1d99e0d
--- /dev/null
+++ b/src/jaegertracing/thrift/contrib/thrift-maven-plugin/src/main/java/org/apache/thrift/maven/ThriftTestCompileMojo.java
@@ -0,0 +1,93 @@
+/*
+ * 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;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+
+/**
+ * @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;
+ }
+
+ /**
+ * Set the local maven ArtifactRepository. Exposed only to allow testing outside of Maven itself.
+ *
+ * @param localRepository local ArtifactRepository
+ */
+ public void setLocalMavenRepository(final ArtifactRepository localRepository) {
+ this.localRepository = localRepository;
+ }
+
+ /**
+ * Set the option to hash dependent JAR paths. Exposed only to allow testing outside of Maven itself.
+ *
+ * @param hashDependentPaths whether or not to hash paths to dependent JARs
+ */
+ public void setHashDependentPaths(final boolean hashDependentPaths) {
+ this.hashDependentPaths = hashDependentPaths;
+ }
+}