You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by hy...@apache.org on 2014/04/21 13:13:01 UTC
[7/9] git commit: TAJO-737: Change version message when daemon starts
up. (hyunsik)
TAJO-737: Change version message when daemon starts up. (hyunsik)
Project: http://git-wip-us.apache.org/repos/asf/tajo/repo
Commit: http://git-wip-us.apache.org/repos/asf/tajo/commit/bbf2461a
Tree: http://git-wip-us.apache.org/repos/asf/tajo/tree/bbf2461a
Diff: http://git-wip-us.apache.org/repos/asf/tajo/diff/bbf2461a
Branch: refs/heads/window_function
Commit: bbf2461a5bddc77b3597030976158e00ee88fe0d
Parents: c367377
Author: Hyunsik Choi <hy...@apache.org>
Authored: Mon Apr 21 16:38:48 2014 +0900
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Mon Apr 21 16:39:15 2014 +0900
----------------------------------------------------------------------
CHANGES.txt | 2 +
pom.xml | 1 +
tajo-common/pom.xml | 45 +++
.../java/org/apache/tajo/util/StringUtils.java | 68 ++++
.../java/org/apache/tajo/util/VersionInfo.java | 177 ++++++++++
.../main/resources/tajo-version-info.properties | 26 ++
.../java/org/apache/tajo/master/TajoMaster.java | 2 +-
.../java/org/apache/tajo/worker/TajoWorker.java | 2 +-
tajo-maven-plugins/pom.xml | 88 +++++
.../tajo/maven/plugin/protoc/ProtocMojo.java | 114 ++++++
.../org/apache/tajo/maven/plugin/util/Exec.java | 117 +++++++
.../tajo/maven/plugin/util/FileSetUtils.java | 61 ++++
.../plugin/versioninfo/VersionInfoMojo.java | 344 +++++++++++++++++++
13 files changed, 1045 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 7f22b06..7f1b175 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -153,6 +153,8 @@ Release 0.8.0 - unreleased
IMPROVEMENTS
+ TAJO-737: Change version message when daemon starts up. (hyunsik)
+
TAJO-768: Improve the log4j configuration. (hyoungjunkim via jinho)
TAJO-755: ALTER TABLESPACE LOCATION support. (hyunsilk)
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 964d984..6eea5c8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -78,6 +78,7 @@
</properties>
<modules>
+ <module>tajo-maven-plugins</module>
<module>tajo-project</module>
<module>tajo-common</module>
<module>tajo-algebra</module>
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/tajo-common/pom.xml
----------------------------------------------------------------------
diff --git a/tajo-common/pom.xml b/tajo-common/pom.xml
index 35ac3e5..f334380 100644
--- a/tajo-common/pom.xml
+++ b/tajo-common/pom.xml
@@ -46,8 +46,53 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
</repositories>
<build>
+ <!--
+ Include all files in src/main/resources. By default, do not apply property
+ substitution (filtering=false), but do apply property substitution to
+ tajo-version-info.properties (filtering=true). This will substitute the
+ version information correctly, but prevent Maven from altering other files
+ like tajo-default.xml.
+ -->
+ <resources>
+ <resource>
+ <directory>${basedir}/src/main/resources</directory>
+ <excludes>
+ <exclude>tajo-version-info.properties</exclude>
+ </excludes>
+ <filtering>false</filtering>
+ </resource>
+ <resource>
+ <directory>${basedir}/src/main/resources</directory>
+ <includes>
+ <include>tajo-version-info.properties</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
<plugins>
<plugin>
+ <groupId>org.apache.tajo</groupId>
+ <artifactId>tajo-maven-plugins</artifactId>
+ <executions>
+ <execution>
+ <id>version-info</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>version-info</goal>
+ </goals>
+ <configuration>
+ <source>
+ <directory>${basedir}/src/main</directory>
+ <includes>
+ <include>java/**/*.java</include>
+ <include>proto/**/*.proto</include>
+ </includes>
+ </source>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/tajo-common/src/main/java/org/apache/tajo/util/StringUtils.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/StringUtils.java b/tajo-common/src/main/java/org/apache/tajo/util/StringUtils.java
index 32edc31..ed9014d 100644
--- a/tajo-common/src/main/java/org/apache/tajo/util/StringUtils.java
+++ b/tajo-common/src/main/java/org/apache/tajo/util/StringUtils.java
@@ -18,9 +18,20 @@
package org.apache.tajo.util;
+import org.apache.commons.lang.SystemUtils;
+import org.apache.hadoop.util.ShutdownHookManager;
+import org.apache.hadoop.util.SignalLogger;
+
+import java.util.Arrays;
+
public class StringUtils {
/**
+ * Priority of the StringUtils shutdown hook.
+ */
+ public static final int SHUTDOWN_HOOK_PRIORITY = 0;
+
+ /**
*
* Given the time in long milliseconds, returns a
* String in the format X hrs, Y mins, S sec, M msecs
@@ -97,4 +108,61 @@ public class StringUtils {
public static String escapeLike(String literal) {
return literal.replaceAll(LIKE_SPECIAL_CHARACTERS, "\\\\$1");
}
+
+ /**
+ * Return a message for logging.
+ * @param prefix prefix keyword for the message
+ * @param msg content of the message
+ * @return a message for logging
+ */
+ private static String toStartupShutdownString(String prefix, String [] msg) {
+ StringBuilder b = new StringBuilder(prefix);
+ b.append("\n/************************************************************");
+ for(String s : msg)
+ b.append("\n" + prefix + s);
+ b.append("\n************************************************************/");
+ return b.toString();
+ }
+
+ /**
+ * Print a log message for starting up and shutting down
+ * @param clazz the class of the server
+ * @param args arguments
+ * @param LOG the target log object
+ */
+ public static void startupShutdownMessage(Class<?> clazz, String[] args,
+ final org.apache.commons.logging.Log LOG) {
+ final String hostname = org.apache.hadoop.net.NetUtils.getHostname();
+ final String classname = clazz.getSimpleName();
+ LOG.info(
+ toStartupShutdownString("STARTUP_MSG: ", new String[] {
+ "Starting " + classname,
+ " host = " + hostname,
+ " args = " + Arrays.asList(args),
+ " version = " + org.apache.tajo.util.VersionInfo.getVersion(),
+ " classpath = " + System.getProperty("java.class.path"),
+ " build = " + org.apache.tajo.util.VersionInfo.getUrl() + " -r "
+ + org.apache.tajo.util.VersionInfo.getRevision()
+ + "; compiled by '" + org.apache.tajo.util.VersionInfo.getUser()
+ + "' on " + org.apache.tajo.util.VersionInfo.getDate(),
+ " java = " + System.getProperty("java.version") }
+ )
+ );
+
+ if (SystemUtils.IS_OS_UNIX) {
+ try {
+ SignalLogger.INSTANCE.register(LOG);
+ } catch (Throwable t) {
+ LOG.warn("failed to register any UNIX signal loggers: ", t);
+ }
+ }
+ ShutdownHookManager.get().addShutdownHook(
+ new Runnable() {
+ @Override
+ public void run() {
+ LOG.info(toStartupShutdownString("SHUTDOWN_MSG: ", new String[]{
+ "Shutting down " + classname + " at " + hostname}));
+ }
+ }, SHUTDOWN_HOOK_PRIORITY);
+ }
}
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/tajo-common/src/main/java/org/apache/tajo/util/VersionInfo.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/VersionInfo.java b/tajo-common/src/main/java/org/apache/tajo/util/VersionInfo.java
new file mode 100644
index 0000000..39e0f54
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/util/VersionInfo.java
@@ -0,0 +1,177 @@
+package org.apache.tajo.util;
+
+/*
+ * 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.
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.util.ClassUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * This class returns build information about Hadoop components.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class VersionInfo {
+ private static final Log LOG = LogFactory.getLog(VersionInfo.class);
+
+ private Properties info;
+
+ protected VersionInfo(String component) {
+ info = new Properties();
+ String versionInfoFile = component + "-version-info.properties";
+ try {
+ InputStream is = Thread.currentThread().getContextClassLoader()
+ .getResourceAsStream(versionInfoFile);
+ if (is == null) {
+ throw new IOException("Resource not found");
+ }
+ info.load(is);
+ } catch (IOException ex) {
+ LogFactory.getLog(getClass()).warn("Could not read '" +
+ versionInfoFile + "', " + ex.toString(), ex);
+ }
+ }
+
+ protected String _getVersion() {
+ return info.getProperty("version", "Unknown");
+ }
+
+ protected String _getRevision() {
+ return info.getProperty("revision", "Unknown");
+ }
+
+ protected String _getBranch() {
+ return info.getProperty("branch", "Unknown");
+ }
+
+ protected String _getDate() {
+ return info.getProperty("date", "Unknown");
+ }
+
+ protected String _getUser() {
+ return info.getProperty("user", "Unknown");
+ }
+
+ protected String _getUrl() {
+ return info.getProperty("url", "Unknown");
+ }
+
+ protected String _getSrcChecksum() {
+ return info.getProperty("srcChecksum", "Unknown");
+ }
+
+ protected String _getBuildVersion(){
+ return getVersion() +
+ " from " + _getRevision() +
+ " by " + _getUser() +
+ " source checksum " + _getSrcChecksum();
+ }
+
+ protected String _getProtocVersion() {
+ return info.getProperty("protocVersion", "Unknown");
+ }
+
+ private static VersionInfo TAJO_VERSION_INFO = new VersionInfo("tajo");
+ /**
+ * Get the Hadoop version.
+ * @return the Hadoop version string, eg. "0.6.3-dev"
+ */
+ public static String getVersion() {
+ return TAJO_VERSION_INFO._getVersion();
+ }
+
+ /**
+ * Get the subversion revision number for the root directory
+ * @return the revision number, eg. "451451"
+ */
+ public static String getRevision() {
+ return TAJO_VERSION_INFO._getRevision();
+ }
+
+ /**
+ * Get the branch on which this originated.
+ * @return The branch name, e.g. "trunk" or "branches/branch-0.20"
+ */
+ public static String getBranch() {
+ return TAJO_VERSION_INFO._getBranch();
+ }
+
+ /**
+ * The date that Hadoop was compiled.
+ * @return the compilation date in unix date format
+ */
+ public static String getDate() {
+ return TAJO_VERSION_INFO._getDate();
+ }
+
+ /**
+ * The user that compiled Hadoop.
+ * @return the username of the user
+ */
+ public static String getUser() {
+ return TAJO_VERSION_INFO._getUser();
+ }
+
+ /**
+ * Get the subversion URL for the root Hadoop directory.
+ */
+ public static String getUrl() {
+ return TAJO_VERSION_INFO._getUrl();
+ }
+
+ /**
+ * Get the checksum of the source files from which Hadoop was
+ * built.
+ **/
+ public static String getSrcChecksum() {
+ return TAJO_VERSION_INFO._getSrcChecksum();
+ }
+
+ /**
+ * Returns the buildVersion which includes version,
+ * revision, user and date.
+ */
+ public static String getBuildVersion(){
+ return TAJO_VERSION_INFO._getBuildVersion();
+ }
+
+ /**
+ * Returns the protoc version used for the build.
+ */
+ public static String getProtocVersion(){
+ return TAJO_VERSION_INFO._getProtocVersion();
+ }
+
+ public static void main(String[] args) {
+ LOG.debug("version: "+ getVersion());
+ System.out.println("Tajo " + getVersion());
+ System.out.println("Git " + getUrl() + " -r " + getRevision());
+ System.out.println("Compiled by " + getUser() + " on " + getDate());
+ System.out.println("Compiled with protoc " + getProtocVersion());
+ System.out.println("From source with checksum " + getSrcChecksum());
+ System.out.println("This command was run using " + ClassUtil.findContainingJar(VersionInfo.class));
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/tajo-common/src/main/resources/tajo-version-info.properties
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/resources/tajo-version-info.properties b/tajo-common/src/main/resources/tajo-version-info.properties
new file mode 100644
index 0000000..ad9a24d
--- /dev/null
+++ b/tajo-common/src/main/resources/tajo-version-info.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+version=${pom.version}
+revision=${version-info.scm.commit}
+branch=${version-info.scm.branch}
+user=${user.name}
+date=${version-info.build.time}
+url=${version-info.scm.uri}
+srcChecksum=${version-info.source.md5}
+protocVersion=${protobuf.version}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/tajo-core/src/main/java/org/apache/tajo/master/TajoMaster.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/master/TajoMaster.java b/tajo-core/src/main/java/org/apache/tajo/master/TajoMaster.java
index 9d54bb5..dfae300 100644
--- a/tajo-core/src/main/java/org/apache/tajo/master/TajoMaster.java
+++ b/tajo-core/src/main/java/org/apache/tajo/master/TajoMaster.java
@@ -30,7 +30,6 @@ import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.service.CompositeService;
import org.apache.hadoop.util.ShutdownHookManager;
-import org.apache.hadoop.util.StringUtils;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.event.AsyncDispatcher;
import org.apache.hadoop.yarn.event.EventHandler;
@@ -58,6 +57,7 @@ import org.apache.tajo.storage.StorageManagerFactory;
import org.apache.tajo.util.ClassUtil;
import org.apache.tajo.util.CommonTestingUtil;
import org.apache.tajo.util.NetUtils;
+import org.apache.tajo.util.StringUtils;
import org.apache.tajo.util.metrics.TajoSystemMetrics;
import org.apache.tajo.webapp.QueryExecutorServlet;
import org.apache.tajo.webapp.StaticHttpServer;
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/tajo-core/src/main/java/org/apache/tajo/worker/TajoWorker.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/worker/TajoWorker.java b/tajo-core/src/main/java/org/apache/tajo/worker/TajoWorker.java
index 0b8d6c2..3768edf 100644
--- a/tajo-core/src/main/java/org/apache/tajo/worker/TajoWorker.java
+++ b/tajo-core/src/main/java/org/apache/tajo/worker/TajoWorker.java
@@ -27,7 +27,6 @@ import org.apache.hadoop.fs.LocalDirAllocator;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.shell.PathData;
import org.apache.hadoop.service.CompositeService;
-import org.apache.hadoop.util.StringUtils;
import org.apache.hadoop.yarn.util.RackResolver;
import org.apache.tajo.QueryId;
import org.apache.tajo.TajoConstants;
@@ -45,6 +44,7 @@ import org.apache.tajo.rpc.RpcConnectionPool;
import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos;
import org.apache.tajo.util.CommonTestingUtil;
import org.apache.tajo.util.NetUtils;
+import org.apache.tajo.util.StringUtils;
import org.apache.tajo.util.TajoIdUtils;
import org.apache.tajo.util.metrics.TajoSystemMetrics;
import org.apache.tajo.webapp.StaticHttpServer;
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/tajo-maven-plugins/pom.xml
----------------------------------------------------------------------
diff --git a/tajo-maven-plugins/pom.xml b/tajo-maven-plugins/pom.xml
new file mode 100644
index 0000000..7de67ef
--- /dev/null
+++ b/tajo-maven-plugins/pom.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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. See accompanying LICENSE file.
+-->
+<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.apache.tajo</groupId>
+ <artifactId>tajo-project</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ <relativePath>../tajo-project</relativePath>
+ </parent>
+ <groupId>org.apache.tajo</groupId>
+ <artifactId>tajo-maven-plugins</artifactId>
+ <packaging>maven-plugin</packaging>
+ <name>Tajo Maven Plugins</name>
+ <properties>
+ <maven.dependency.version>3.0</maven.dependency.version>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>${maven.dependency.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>${maven.dependency.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.plugin-tools</groupId>
+ <artifactId>maven-plugin-annotations</artifactId>
+ <version>${maven.dependency.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>${maven.dependency.version}</version>
+ <configuration>
+ <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
+ </configuration>
+ <executions>
+ <execution>
+ <id>mojo-descriptor</id>
+ <goals>
+ <goal>descriptor</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <!--
+ Skip Clover instrumentation for this module to prevent error finding Clover
+ classes during plugin execution when running a build with Clover enabled.
+ -->
+ <plugin>
+ <groupId>com.atlassian.maven.plugins</groupId>
+ <artifactId>maven-clover2-plugin</artifactId>
+ <version>3.0.5</version>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/protoc/ProtocMojo.java
----------------------------------------------------------------------
diff --git a/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/protoc/ProtocMojo.java b/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/protoc/ProtocMojo.java
new file mode 100644
index 0000000..498f85d
--- /dev/null
+++ b/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/protoc/ProtocMojo.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2012 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.
+ */
+package org.apache.tajo.maven.plugin.protoc;
+
+import org.apache.tajo.maven.plugin.util.Exec;
+import org.apache.tajo.maven.plugin.util.FileSetUtils;
+import org.apache.maven.model.FileSet;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.apache.tajo.maven.plugin.util.Exec;
+import org.apache.tajo.maven.plugin.util.FileSetUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+
+@Mojo(name="protoc", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
+public class ProtocMojo extends AbstractMojo {
+
+ @Parameter(defaultValue="${project}")
+ private MavenProject project;
+
+ @Parameter
+ private File[] imports;
+
+ @Parameter(defaultValue="${project.build.directory}/generated-sources/java")
+ private File output;
+
+ @Parameter(required=true)
+ private FileSet source;
+
+ @Parameter
+ private String protocCommand;
+
+ @Parameter(required=true)
+ private String protocVersion;
+
+ public void execute() throws MojoExecutionException {
+ try {
+ if (protocCommand == null || protocCommand.trim().isEmpty()) {
+ protocCommand = "protoc";
+ }
+ List<String> command = new ArrayList<String>();
+ command.add(protocCommand);
+ command.add("--version");
+ Exec exec = new Exec(this);
+ List<String> out = new ArrayList<String>();
+ if (exec.run(command, out) == 127) {
+ getLog().error("protoc, not found at: " + protocCommand);
+ throw new MojoExecutionException("protoc failure");
+ } else {
+ if (out.isEmpty()) {
+ getLog().error("stdout: " + out);
+ throw new MojoExecutionException(
+ "'protoc --version' did not return a version");
+ } else {
+ if (!out.get(0).endsWith(protocVersion)) {
+ throw new MojoExecutionException(
+ "protoc version is '" + out.get(0) + "', expected version is '"
+ + protocVersion + "'");
+ }
+ }
+ }
+ if (!output.mkdirs()) {
+ if (!output.exists()) {
+ throw new MojoExecutionException("Could not create directory: " +
+ output);
+ }
+ }
+ command = new ArrayList<String>();
+ command.add(protocCommand);
+ command.add("--java_out=" + output.getCanonicalPath());
+ if (imports != null) {
+ for (File i : imports) {
+ command.add("-I" + i.getCanonicalPath());
+ }
+ }
+ for (File f : FileSetUtils.convertFileSetToFiles(source)) {
+ command.add(f.getCanonicalPath());
+ }
+ exec = new Exec(this);
+ out = new ArrayList<String>();
+ if (exec.run(command, out) != 0) {
+ getLog().error("protoc compiler error");
+ for (String s : out) {
+ getLog().error(s);
+ }
+ throw new MojoExecutionException("protoc failure");
+ }
+ } catch (Throwable ex) {
+ throw new MojoExecutionException(ex.toString(), ex);
+ }
+ project.addCompileSourceRoot(output.getAbsolutePath());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/util/Exec.java
----------------------------------------------------------------------
diff --git a/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/util/Exec.java b/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/util/Exec.java
new file mode 100644
index 0000000..89ba6fb
--- /dev/null
+++ b/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/util/Exec.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012 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.
+ */
+package org.apache.tajo.maven.plugin.util;
+
+import org.apache.maven.plugin.Mojo;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Exec is a helper class for executing an external process from a mojo.
+ */
+public class Exec {
+ private Mojo mojo;
+
+ /**
+ * Creates a new Exec instance for executing an external process from the given
+ * mojo.
+ *
+ * @param mojo Mojo executing external process
+ */
+ public Exec(Mojo mojo) {
+ this.mojo = mojo;
+ }
+
+ /**
+ * Runs the specified command and saves each line of the command's output to
+ * the given list.
+ *
+ * @param command List<String> containing command and all arguments
+ * @param output List<String> in/out parameter to receive command output
+ * @return int exit code of command
+ */
+ public int run(List<String> command, List<String> output) {
+ int retCode = 1;
+ ProcessBuilder pb = new ProcessBuilder(command);
+ try {
+ Process p = pb.start();
+ OutputBufferThread stdOut = new OutputBufferThread(p.getInputStream());
+ OutputBufferThread stdErr = new OutputBufferThread(p.getErrorStream());
+ stdOut.start();
+ stdErr.start();
+ retCode = p.waitFor();
+ if (retCode != 0) {
+ mojo.getLog().warn(command + " failed with error code " + retCode);
+ for (String s : stdErr.getOutput()) {
+ mojo.getLog().debug(s);
+ }
+ }
+ stdOut.join();
+ stdErr.join();
+ output.addAll(stdOut.getOutput());
+ } catch (Exception ex) {
+ mojo.getLog().warn(command + " failed: " + ex.toString());
+ }
+ return retCode;
+ }
+
+ /**
+ * OutputBufferThread is a background thread for consuming and storing output
+ * of the external process.
+ */
+ private static class OutputBufferThread extends Thread {
+ private List<String> output;
+ private BufferedReader reader;
+
+ /**
+ * Creates a new OutputBufferThread to consume the given InputStream.
+ *
+ * @param is InputStream to consume
+ */
+ public OutputBufferThread(InputStream is) {
+ this.setDaemon(true);
+ output = new ArrayList<String>();
+ reader = new BufferedReader(new InputStreamReader(is));
+ }
+
+ @Override
+ public void run() {
+ try {
+ String line = reader.readLine();
+ while (line != null) {
+ output.add(line);
+ line = reader.readLine();
+ }
+ } catch (IOException ex) {
+ throw new RuntimeException("make failed with error code " + ex.toString());
+ }
+ }
+
+ /**
+ * Returns every line consumed from the input.
+ *
+ * @return List<String> every line consumed from the input
+ */
+ public List<String> getOutput() {
+ return output;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/util/FileSetUtils.java
----------------------------------------------------------------------
diff --git a/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/util/FileSetUtils.java b/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/util/FileSetUtils.java
new file mode 100644
index 0000000..f034f44
--- /dev/null
+++ b/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/util/FileSetUtils.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012 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.
+ */
+package org.apache.tajo.maven.plugin.util;
+
+import org.apache.maven.model.FileSet;
+import org.codehaus.plexus.util.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * FileSetUtils contains helper methods for mojo implementations that need to
+ * work with a Maven FileSet.
+ */
+public class FileSetUtils {
+
+ /**
+ * Returns a string containing every element of the given list, with each
+ * element separated by a comma.
+ *
+ * @param list List of all elements
+ * @return String containing every element, comma-separated
+ */
+ private static String getCommaSeparatedList(List list) {
+ StringBuilder buffer = new StringBuilder();
+ String separator = "";
+ for (Object e : list) {
+ buffer.append(separator).append(e);
+ separator = ",";
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Converts a Maven FileSet to a list of File objects.
+ *
+ * @param source FileSet to convert
+ * @return List<File> containing every element of the FileSet as a File
+ * @throws IOException if an I/O error occurs while trying to find the files
+ */
+ @SuppressWarnings("unchecked")
+ public static List<File> convertFileSetToFiles(FileSet source) throws IOException {
+ String includes = getCommaSeparatedList(source.getIncludes());
+ String excludes = getCommaSeparatedList(source.getExcludes());
+ return FileUtils.getFiles(new File(source.getDirectory()), includes, excludes);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/bbf2461a/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/versioninfo/VersionInfoMojo.java
----------------------------------------------------------------------
diff --git a/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/versioninfo/VersionInfoMojo.java b/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/versioninfo/VersionInfoMojo.java
new file mode 100644
index 0000000..5347f40
--- /dev/null
+++ b/tajo-maven-plugins/src/main/java/org/apache/tajo/maven/plugin/versioninfo/VersionInfoMojo.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2012 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.
+ */
+package org.apache.tajo.maven.plugin.versioninfo;
+
+import org.apache.tajo.maven.plugin.util.Exec;
+import org.apache.tajo.maven.plugin.util.FileSetUtils;
+import org.apache.maven.model.FileSet;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.apache.tajo.maven.plugin.util.Exec;
+import org.apache.tajo.maven.plugin.util.FileSetUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+
+/**
+ * VersionInfoMojo calculates information about the current version of the
+ * codebase and exports the information as properties for further use in a Maven
+ * build. The version information includes build time, SCM URI, SCM branch, SCM
+ * commit, and an MD5 checksum of the contents of the files in the codebase.
+ */
+@Mojo(name="version-info")
+public class VersionInfoMojo extends AbstractMojo {
+
+ @Parameter(defaultValue="${project}")
+ private MavenProject project;
+
+ @Parameter(required=true)
+ private FileSet source;
+
+ @Parameter(defaultValue="version-info.build.time")
+ private String buildTimeProperty;
+
+ @Parameter(defaultValue="version-info.source.md5")
+ private String md5Property;
+
+ @Parameter(defaultValue="version-info.scm.uri")
+ private String scmUriProperty;
+
+ @Parameter(defaultValue="version-info.scm.branch")
+ private String scmBranchProperty;
+
+ @Parameter(defaultValue="version-info.scm.commit")
+ private String scmCommitProperty;
+
+ @Parameter(defaultValue="git")
+ private String gitCommand;
+
+ @Parameter(defaultValue="svn")
+ private String svnCommand;
+
+ private enum SCM {NONE, SVN, GIT}
+
+ @Override
+ public void execute() throws MojoExecutionException {
+ try {
+ SCM scm = determineSCM();
+ project.getProperties().setProperty(buildTimeProperty, getBuildTime());
+ project.getProperties().setProperty(scmUriProperty, getSCMUri(scm));
+ project.getProperties().setProperty(scmBranchProperty, getSCMBranch(scm));
+ project.getProperties().setProperty(scmCommitProperty, getSCMCommit(scm));
+ project.getProperties().setProperty(md5Property, computeMD5());
+ } catch (Throwable ex) {
+ throw new MojoExecutionException(ex.toString(), ex);
+ }
+ }
+
+ /**
+ * Returns a string representing current build time.
+ *
+ * @return String representing current build time
+ */
+ private String getBuildTime() {
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ return dateFormat.format(new Date());
+ }
+ private List<String> scmOut;
+
+ /**
+ * Determines which SCM is in use (Subversion, git, or none) and captures
+ * output of the SCM command for later parsing.
+ *
+ * @return SCM in use for this build
+ * @throws Exception if any error occurs attempting to determine SCM
+ */
+ private SCM determineSCM() throws Exception {
+ Exec exec = new Exec(this);
+ SCM scm = SCM.NONE;
+ scmOut = new ArrayList<String>();
+ int ret = exec.run(Arrays.asList(svnCommand, "info"), scmOut);
+ if (ret == 0) {
+ scm = SCM.SVN;
+ } else {
+ ret = exec.run(Arrays.asList(gitCommand, "branch"), scmOut);
+ if (ret == 0) {
+ ret = exec.run(Arrays.asList(gitCommand, "remote", "-v"), scmOut);
+ if (ret != 0) {
+ scm = SCM.NONE;
+ scmOut = null;
+ } else {
+ ret = exec.run(Arrays.asList(gitCommand, "log", "-n", "1"), scmOut);
+ if (ret != 0) {
+ scm = SCM.NONE;
+ scmOut = null;
+ } else {
+ scm = SCM.GIT;
+ }
+ }
+ }
+ }
+ if (scmOut != null) {
+ getLog().debug(scmOut.toString());
+ }
+ getLog().info("SCM: " + scm);
+ return scm;
+ }
+
+ /**
+ * Return URI and branch of Subversion repository.
+ *
+ * @param str String Subversion info output containing URI and branch
+ * @return String[] containing URI and branch
+ */
+ private String[] getSvnUriInfo(String str) {
+ String[] res = new String[]{"Unknown", "Unknown"};
+ try {
+ String path = str;
+ int index = path.indexOf("trunk");
+ if (index > -1) {
+ res[0] = path.substring(0, index - 1);
+ res[1] = "trunk";
+ } else {
+ index = path.indexOf("branches");
+ if (index > -1) {
+ res[0] = path.substring(0, index - 1);
+ int branchIndex = index + "branches".length() + 1;
+ index = path.indexOf("/", branchIndex);
+ if (index > -1) {
+ res[1] = path.substring(branchIndex, index);
+ } else {
+ res[1] = path.substring(branchIndex);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ getLog().warn("Could not determine URI & branch from SVN URI: " + str);
+ }
+ return res;
+ }
+
+ /**
+ * Parses SCM output and returns URI of SCM.
+ *
+ * @param scm SCM in use for this build
+ * @return String URI of SCM
+ */
+ private String getSCMUri(SCM scm) {
+ String uri = "Unknown";
+ switch (scm) {
+ case SVN:
+ for (String s : scmOut) {
+ if (s.startsWith("URL:")) {
+ uri = s.substring(4).trim();
+ uri = getSvnUriInfo(uri)[0];
+ break;
+ }
+ }
+ break;
+ case GIT:
+ for (String s : scmOut) {
+ if (s.startsWith("origin") && s.endsWith("(fetch)")) {
+ uri = s.substring("origin".length());
+ uri = uri.substring(0, uri.length() - "(fetch)".length());
+ break;
+ }
+ }
+ break;
+ }
+ return uri.trim();
+ }
+
+ /**
+ * Parses SCM output and returns commit of SCM.
+ *
+ * @param scm SCM in use for this build
+ * @return String commit of SCM
+ */
+ private String getSCMCommit(SCM scm) {
+ String commit = "Unknown";
+ switch (scm) {
+ case SVN:
+ for (String s : scmOut) {
+ if (s.startsWith("Revision:")) {
+ commit = s.substring("Revision:".length());
+ break;
+ }
+ }
+ break;
+ case GIT:
+ for (String s : scmOut) {
+ if (s.startsWith("commit")) {
+ commit = s.substring("commit".length());
+ break;
+ }
+ }
+ break;
+ }
+ return commit.trim();
+ }
+
+ /**
+ * Parses SCM output and returns branch of SCM.
+ *
+ * @param scm SCM in use for this build
+ * @return String branch of SCM
+ */
+ private String getSCMBranch(SCM scm) {
+ String branch = "Unknown";
+ switch (scm) {
+ case SVN:
+ for (String s : scmOut) {
+ if (s.startsWith("URL:")) {
+ branch = s.substring(4).trim();
+ branch = getSvnUriInfo(branch)[1];
+ break;
+ }
+ }
+ break;
+ case GIT:
+ for (String s : scmOut) {
+ if (s.startsWith("*")) {
+ branch = s.substring("*".length());
+ break;
+ }
+ }
+ break;
+ }
+ return branch.trim();
+ }
+
+ /**
+ * Reads and returns the full contents of the specified file.
+ *
+ * @param file File to read
+ * @return byte[] containing full contents of file
+ * @throws IOException if there is an I/O error while reading the file
+ */
+ private byte[] readFile(File file) throws IOException {
+ RandomAccessFile raf = new RandomAccessFile(file, "r");
+ byte[] buffer = new byte[(int) raf.length()];
+ raf.readFully(buffer);
+ raf.close();
+ return buffer;
+ }
+
+ /**
+ * Given a list of files, computes and returns an MD5 checksum of the full
+ * contents of all files.
+ *
+ * @param files List<File> containing every file to input into the MD5 checksum
+ * @return byte[] calculated MD5 checksum
+ * @throws IOException if there is an I/O error while reading a file
+ * @throws NoSuchAlgorithmException if the MD5 algorithm is not supported
+ */
+ private byte[] computeMD5(List<File> files) throws IOException, NoSuchAlgorithmException {
+ MessageDigest md5 = MessageDigest.getInstance("MD5");
+ for (File file : files) {
+ getLog().debug("Computing MD5 for: " + file);
+ md5.update(readFile(file));
+ }
+ return md5.digest();
+ }
+
+ /**
+ * Converts bytes to a hexadecimal string representation and returns it.
+ *
+ * @param array byte[] to convert
+ * @return String containing hexadecimal representation of bytes
+ */
+ private String byteArrayToString(byte[] array) {
+ StringBuilder sb = new StringBuilder();
+ for (byte b : array) {
+ sb.append(Integer.toHexString(0xff & b));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Computes and returns an MD5 checksum of the contents of all files in the
+ * input Maven FileSet.
+ *
+ * @return String containing hexadecimal representation of MD5 checksum
+ * @throws Exception if there is any error while computing the MD5 checksum
+ */
+ private String computeMD5() throws Exception {
+ List<File> files = FileSetUtils.convertFileSetToFiles(source);
+ // File order of MD5 calculation is significant. Sorting is done on
+ // unix-format names, case-folded, in order to get a platform-independent
+ // sort and calculate the same MD5 on all platforms.
+ Collections.sort(files, new Comparator<File>() {
+ @Override
+ public int compare(File lhs, File rhs) {
+ return normalizePath(lhs).compareTo(normalizePath(rhs));
+ }
+
+ private String normalizePath(File file) {
+ return file.getPath().toUpperCase().replaceAll("\\\\", "/");
+ }
+ });
+ byte[] md5 = computeMD5(files);
+ String md5str = byteArrayToString(md5);
+ getLog().info("Computed MD5: " + md5str);
+ return md5str;
+ }
+}