Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
igor-petruk committed Feb 7, 2012
0 parents commit bf404f8
Show file tree
Hide file tree
Showing 5 changed files with 376 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
@@ -0,0 +1,6 @@
*.ipr
*.iws
*.iml
target
*.releaseBackup
release.properties
9 changes: 9 additions & 0 deletions README
@@ -0,0 +1,9 @@
Hello.

There are a couple of plugins out there to compile
Google Protobuf files, but most of them end up
giving NPEs, so you have to fallback to Exec Plugin.

That's why I wanted to create a quite simple plugin
that just does the job. Plus the source code is very
small and simple to fix any possible issue.
121 changes: 121 additions & 0 deletions pom.xml
@@ -0,0 +1,121 @@
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>7</version>
</parent>

<groupId>com.petruk.protobuf</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>0.1-SNAPSHOT</version>
<name>Once Again Maven Protobuf Plugin</name>
<url>http://github.com/igor-petruk/protobuf-maven-plugin</url>
<properties>
<mavenVersion>2.0.9</mavenVersion>
</properties>

<developers>
<developer>
<id>igor-petruk</id>
<name>Igor Petruk</name>
<email>igor.petrouk@gmail.com</email>
</developer>
</developers>

<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>

<scm>
<connection>scm:git:git://github.com/igor-petruk/protobuf-maven-plugin.git</connection>
<developerConnection>scm:git:ssh://git@github.com/igor-petruk/protobuf-maven-plugin.git</developerConnection>
<url>https://github.com/igor-petruk/protobuf-maven-plugin</url>
</scm>

<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact-manager</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-repository-metadata</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-dependency-tree</artifactId>
<version>1.2</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<profiles>
<profile>
<id>release-sign-artifacts</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
218 changes: 218 additions & 0 deletions src/main/java/com/petruk/protobuf/MyMojo.java
@@ -0,0 +1,218 @@
package com.petruk.protobuf;

/*
* Copyright 2001-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactCollector;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.dependency.tree.DependencyNode;
import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map;
import java.util.Scanner;

/**
* @goal run
* @phase generate-sources
* @requiresDependencyResolution
*/
public class MyMojo extends AbstractMojo {

private static final String PROTOBUF_GROUPID="com.google.protobuf";
private static final String PROTOBUF_ARTIFACTID="protobuf-java";
private static final String PROTOC="protoc";
private static final String VERSION_KEY="--version";
private static final ProtoFileFilter PROTO_FILTER =
new ProtoFileFilter(".proto");

/**
* The Maven project.
*
* @parameter expression="${project}"
* @required
* @readonly
*/
private MavenProject project;

/**
* The artifact repository to use.
*
* @parameter expression="${localRepository}"
* @required
* @readonly
*/
private ArtifactRepository localRepository;

/**
* The artifact factory to use.
*
* @component
* @required
* @readonly
*/
private ArtifactFactory artifactFactory;

/**
* The artifact metadata source to use.
*
* @component
* @required
* @readonly
*/
private ArtifactMetadataSource artifactMetadataSource;

/**
* The artifact collector to use.
*
* @component
* @required
* @readonly
*/
private ArtifactCollector artifactCollector;

/**
* The dependency tree builder to use.
*
* @component
* @required
* @readonly
*/
private DependencyTreeBuilder dependencyTreeBuilder;

/**
* Location of the file.
* @parameter expression="${run.inputDirectories}"
* @required
*/
private File[] inputDirectories;

/**
* Location of the file.
* @parameter expression="${run.outputDirectory}"
* @required
*/
private File outputDirectory;

public void execute() throws MojoExecutionException
{
String dependencyVersion = getProtobufVersion();
getLog().info("Protobuf dependency version " + dependencyVersion);
String executableVersion = detectProtobufVersion();
if (executableVersion==null){
throw new MojoExecutionException("Unable to find '"+PROTOC+"'");
}
getLog().info("'protoc' executable version "+executableVersion);
if (!dependencyVersion.startsWith(executableVersion)){
throw new MojoExecutionException("Protobuf installation version does not match Protobuf library version");
}
performProtoCompilation();
}

private void performProtoCompilation() throws MojoExecutionException{
File f = outputDirectory;
if ( !f.exists() )
{
f.mkdirs();
}
for (File input: inputDirectories){
getLog().info("Directory "+input);
File[] files = input.listFiles(PROTO_FILTER);
for (File file: files){
processFile(file, outputDirectory);
}
}
}

private void processFile(File file, File outputDir) throws MojoExecutionException{
getLog().info(" Processing "+file.getName());
Runtime runtime = Runtime.getRuntime();
try {
Process process = runtime.exec(new String[]{
PROTOC,
"--proto_path="+file.getParentFile().getAbsolutePath(),
"--java_out="+outputDir,
file.toString()
});
int result = process.waitFor();
if (result!=0){
Scanner scanner = new Scanner(process.getErrorStream());
while (scanner.hasNextLine()){
getLog().info(" " + scanner.nextLine());
}
throw new MojoExecutionException("'protoc' failed for "+file+". Exit code "+result);
}
}catch (InterruptedException e){
throw new MojoExecutionException("Interrupted",e);
} catch (IOException e) {
throw new MojoExecutionException("Unable to execute protoc for "+file, e);
}
}

private String getProtobufVersion() throws MojoExecutionException{
try {
ArtifactFilter artifactFilter = null;
DependencyNode node = dependencyTreeBuilder.buildDependencyTree(project,localRepository,
artifactFactory,
artifactMetadataSource,
null,
artifactCollector
);
return traverseNode(node);

} catch (DependencyTreeBuilderException e) {
throw new MojoExecutionException("Unable to traverse dependency tree", e);
}
}

private String detectProtobufVersion() throws MojoExecutionException{
Runtime runtime = Runtime.getRuntime();
try {
Process process = runtime.exec(new String[]{
PROTOC,VERSION_KEY});
Scanner scanner = new Scanner(process.getInputStream());
String[] version = scanner.nextLine().split(" ");
return version[1];
} catch (IOException e) {
return null;
}
}

private String traverseNode(DependencyNode node) {
Artifact artifact = node.getArtifact();
if ((PROTOBUF_GROUPID.equals(artifact.getGroupId())
&& (PROTOBUF_ARTIFACTID.equals(artifact.getArtifactId())))){
return artifact.getVersion();
}
for (Object o: node.getChildren()){
DependencyNode child = (DependencyNode)o;
String result = traverseNode(child);
if (result!=null)
return result;
}
return null;
}
}
22 changes: 22 additions & 0 deletions src/main/java/com/petruk/protobuf/ProtoFileFilter.java
@@ -0,0 +1,22 @@
package com.petruk.protobuf;

import java.io.File;
import java.io.FilenameFilter;

/**
* User: Igor Petruk
* Date: 07.02.12
* Time: 17:01
*/
public class ProtoFileFilter implements FilenameFilter{
String extension;

public ProtoFileFilter(String extension) {
this.extension = extension;
}

@Override
public boolean accept(File dir, String name) {
return name.endsWith(extension);
}
}

0 comments on commit bf404f8

Please sign in to comment.