accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From e..@apache.org
Subject [1/3] git commit: ACCUMULO-1494 Add support for accumulo jar command.
Date Tue, 24 Sep 2013 16:17:06 GMT
Updated Branches:
  refs/heads/master ed3c15737 -> d99626072


ACCUMULO-1494 Add support for accumulo jar command.

Signed-off-by: Eric Newton <eric.newton@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/ccc46b06
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/ccc46b06
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/ccc46b06

Branch: refs/heads/master
Commit: ccc46b06e2ff76ba5c2a40549ad6568299fdcf4f
Parents: 3de0c1e
Author: Bill Havanki <bhavanki@cloudera.com>
Authored: Thu Sep 19 16:18:49 2013 -0400
Committer: Eric Newton <eric.newton@gmail.com>
Committed: Tue Sep 24 12:13:08 2013 -0400

----------------------------------------------------------------------
 bin/accumulo                                    | 23 +++++-
 .../java/org/apache/accumulo/start/Main.java    | 77 +++++++++++++++---
 .../org/apache/accumulo/start/MainTest.java     | 84 ++++++++++++++++++++
 3 files changed, 170 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/ccc46b06/bin/accumulo
----------------------------------------------------------------------
diff --git a/bin/accumulo b/bin/accumulo
index ad42d05..8e1128a 100755
--- a/bin/accumulo
+++ b/bin/accumulo
@@ -33,7 +33,7 @@ START_JAR="${ACCUMULO_HOME}/lib/accumulo-start.jar"
 #
 # Resolve a program to its installation directory
 #
-locationByProgram() 
+locationByProgram()
 {
    RESULT=$( which "$1" )
    if [[ "$?" != 0 && -z "${RESULT}" ]]; then
@@ -59,6 +59,7 @@ DEFAULT_GENERAL_JAVA_OPTS=""
 
 #
 # ACCUMULO_XTRAJARS is where all of the commandline -add items go into for reading by accumulo.
+# It also holds the JAR run with the jar command and, if possible, any items in the JAR manifest's
Class-Path.
 #
 if [ "$1" = "-add" ] ; then
     export ACCUMULO_XTRAJARS="$2"
@@ -66,6 +67,26 @@ if [ "$1" = "-add" ] ; then
 else
     export ACCUMULO_XTRAJARS=""
 fi
+if [ "$1" = "jar" ] ; then
+    if [[ $2 =~ ^/ ]]; then
+      jardir="$(dirname "$2")"
+      jarfile="$2"
+    else
+      jardir="$(pwd)"
+      jarfile="${jardir}/${2}"
+    fi
+    if jar tf "$jarfile" | grep -q META-INF/MANIFEST.MF ; then
+      cp="$(unzip -p "$jarfile" META-INF/MANIFEST.MF | grep ^Class-Path: | sed 's/^Class-Path:
*//')"
+      if [ -n "$cp" ] ; then
+         for j in $cp; do
+            if [ "$j" != "Class-Path:" ]; then
+               ACCUMULO_XTRAJARS="${jardir}/${j},$ACCUMULO_XTRAJARS"
+            fi
+         done
+      fi
+    fi
+    ACCUMULO_XTRAJARS="${jarfile},$ACCUMULO_XTRAJARS"
+fi
 
 #
 # Add appropriate options for process type

http://git-wip-us.apache.org/repos/asf/accumulo/blob/ccc46b06/start/src/main/java/org/apache/accumulo/start/Main.java
----------------------------------------------------------------------
diff --git a/start/src/main/java/org/apache/accumulo/start/Main.java b/start/src/main/java/org/apache/accumulo/start/Main.java
index 0d1eeeb..7a9e76b 100644
--- a/start/src/main/java/org/apache/accumulo/start/Main.java
+++ b/start/src/main/java/org/apache/accumulo/start/Main.java
@@ -16,34 +16,36 @@
  */
 package org.apache.accumulo.start;
 
+import java.io.IOException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
 
 import org.apache.accumulo.start.classloader.AccumuloClassLoader;
 
 public class Main {
-  
+
   public static void main(String[] args) throws Exception {
     Runnable r = null;
-    
+
     try {
       if (args.length == 0) {
         printUsage();
         System.exit(1);
       }
-      final String argsToPass[] = new String[args.length - 1];
-      System.arraycopy(args, 1, argsToPass, 0, args.length - 1);
-      
+
       Thread.currentThread().setContextClassLoader(AccumuloClassLoader.getClassLoader());
-      
+
       Class<?> vfsClassLoader = AccumuloClassLoader.getClassLoader().loadClass("org.apache.accumulo.start.classloader.vfs.AccumuloVFSClassLoader");
-      
+
       ClassLoader cl = (ClassLoader) vfsClassLoader.getMethod("getClassLoader", new Class[]
{}).invoke(null, new Object[] {});
-      
+
       Class<?> runTMP = null;
-      
+
       Thread.currentThread().setContextClassLoader(cl);
-      
+
       if (args[0].equals("master")) {
         runTMP = cl.loadClass("org.apache.accumulo.server.master.Master");
       } else if (args[0].equals("tserver")) {
@@ -81,6 +83,22 @@ public class Main {
         runTMP = cl.loadClass("org.apache.accumulo.core.util.CreateToken");
       } else if (args[0].equals("info")) {
         runTMP = cl.loadClass("org.apache.accumulo.server.util.Info");
+      } else if (args[0].equals("jar")) {
+        if (args.length < 2) {
+          printUsage();
+          System.exit(1);
+        }
+        try {
+          JarFile f = new JarFile(args[1]);
+          runTMP = loadClassFromJar(args, f, cl);
+        } catch (IOException ioe) {
+          System.out.println("File " + args[1] + " could not be found or read.");
+          System.exit(1);
+        } catch (ClassNotFoundException cnfe) {
+          System.out.println("Classname " + (args.length > 2 ? args[2] : "in JAR manifest")
+
+                             " not found.  Please make sure you use the wholly qualified
package name.");
+          System.exit(1);
+        }
       } else {
         try {
           runTMP = cl.loadClass(args[0]);
@@ -99,6 +117,18 @@ public class Main {
         System.out.println(args[0] + " must implement a public static void main(String args[])
method");
         System.exit(1);
       }
+      int chopArgsCount;
+      if (args[0].equals("jar")) {
+        if (args.length > 2 && runTMP.getName().equals(args[2])) {
+          chopArgsCount = 3;
+        } else {
+          chopArgsCount = 2;
+        }
+      } else {
+        chopArgsCount = 1;
+      }
+      String argsToPass[] = new String[args.length - chopArgsCount];
+      System.arraycopy(args, chopArgsCount, argsToPass, 0, args.length - chopArgsCount);
       final Object thisIsJustOneArgument = argsToPass;
       final Method finalMain = main;
       r = new Runnable() {
@@ -112,7 +142,7 @@ public class Main {
           }
         }
       };
-      
+
       Thread t = new Thread(r, args[0]);
       t.setContextClassLoader(cl);
       t.start();
@@ -122,8 +152,29 @@ public class Main {
       System.exit(1);
     }
   }
-  
+
   private static void printUsage() {
-    System.out.println("accumulo init | master | tserver | monitor | shell | admin | gc |
classpath | rfile-info | login-info | tracer | minicluster | proxy | zookeeper | create-token
| info | version <accumulo class> args");
+    System.out.println("accumulo init | master | tserver | monitor | shell | admin | gc |
classpath | rfile-info | login-info | tracer | minicluster | proxy | zookeeper | create-token
| info | version | jar <jar> [<main class>] args | <accumulo class> args");
+  }
+
+  // feature: will work even if main class isn't in the JAR
+  static Class<?> loadClassFromJar(String[] args, JarFile f, ClassLoader cl) throws
IOException, ClassNotFoundException {
+    ClassNotFoundException explicitNotFound = null;
+    if (args.length >= 3) {
+      try {
+        return cl.loadClass(args[2]);  // jar jar-file main-class
+      } catch (ClassNotFoundException cnfe) {
+        // assume this is the first argument, look for main class in JAR manifest
+        explicitNotFound = cnfe;
+      }
+    }
+    String mainClass = f.getManifest().getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
+    if (mainClass == null) {
+      if (explicitNotFound != null) {
+        throw explicitNotFound;
+      }
+      throw new ClassNotFoundException("No main class was specified, and the JAR manifest
does not specify one");
+    }
+    return cl.loadClass(mainClass);
   }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/ccc46b06/start/src/test/java/org/apache/accumulo/start/MainTest.java
----------------------------------------------------------------------
diff --git a/start/src/test/java/org/apache/accumulo/start/MainTest.java b/start/src/test/java/org/apache/accumulo/start/MainTest.java
new file mode 100644
index 0000000..02dc46d
--- /dev/null
+++ b/start/src/test/java/org/apache/accumulo/start/MainTest.java
@@ -0,0 +1,84 @@
+package org.apache.accumulo.start;
+
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.easymock.Capture;
+import static org.easymock.EasyMock.*;
+
+public class MainTest {
+  private static final Class MAIN_CLASS = String.class;  // arbitrary
+  private static final String MAIN_CLASS_NAME = MAIN_CLASS.getName();
+
+  private JarFile f;
+  private ClassLoader cl;
+  @Before public void setUp() {
+    f = createMock(JarFile.class);
+    cl = createMock(ClassLoader.class);
+  }
+  @Test public void testLoadClassFromJar_ExplicitMainClass() throws Exception {
+    String[] args = { "jar", "the.jar", "main.class", "arg1", "arg2" };
+    expect(cl.loadClass("main.class")).andReturn(MAIN_CLASS);
+    replay(cl);
+    assertEquals(MAIN_CLASS, Main.loadClassFromJar(args, f, cl));
+  }
+  @Test public void testLoadClassFromJar_ManifestMainClass() throws Exception {
+    String[] args = { "jar", "the.jar", "arg1", "arg2" };
+    expect(cl.loadClass("arg1")).andThrow(new ClassNotFoundException());
+    expect(cl.loadClass(MAIN_CLASS_NAME)).andReturn(MAIN_CLASS);
+    replay(cl);
+    mockManifestMainClass(f, MAIN_CLASS.getName());
+    replay(f);
+    assertEquals(MAIN_CLASS, Main.loadClassFromJar(args, f, cl));
+  }
+  @Test(expected=ClassNotFoundException.class)
+  public void testLoadClassFromJar_NoMainClass() throws Exception {
+    String[] args = { "jar", "the.jar", "arg1", "arg2" };
+    expect(cl.loadClass("arg1")).andThrow(new ClassNotFoundException());
+    replay(cl);
+    mockManifestMainClass(f, null);
+    replay(f);
+    Main.loadClassFromJar(args, f, cl);
+  }
+  @Test(expected=ClassNotFoundException.class)
+  public void testLoadClassFromJar_NoMainClassNoArgs() throws Exception {
+    String[] args = { "jar", "the.jar" };
+    mockManifestMainClass(f, null);
+    replay(f);
+    Main.loadClassFromJar(args, f, cl);
+  }
+
+  @Test(expected=ClassNotFoundException.class)
+  public void testLoadClassFromJar_ExplicitMainClass_Fail() throws Exception {
+    String[] args = { "jar", "the.jar", "main.class", "arg1", "arg2" };
+    expect(cl.loadClass("main.class")).andThrow(new ClassNotFoundException());
+    replay(cl);
+    mockManifestMainClass(f, null);
+    replay(f);
+    Main.loadClassFromJar(args, f, cl);
+  }
+  @Test(expected=ClassNotFoundException.class)
+  public void testLoadClassFromJar_ManifestMainClass_Fail() throws Exception {
+    String[] args = { "jar", "the.jar", "arg1", "arg2" };
+    expect(cl.loadClass("arg1")).andThrow(new ClassNotFoundException());
+    expect(cl.loadClass(MAIN_CLASS_NAME)).andThrow(new ClassNotFoundException());
+    replay(cl);
+    mockManifestMainClass(f, MAIN_CLASS.getName());
+    replay(f);
+    Main.loadClassFromJar(args, f, cl);
+  }
+
+  private void mockManifestMainClass(JarFile f, String mainClassName)
+    throws Exception {
+    Manifest mf = createMock(Manifest.class);
+    expect(f.getManifest()).andReturn(mf);
+    Attributes attrs = createMock(Attributes.class);
+    expect(mf.getMainAttributes()).andReturn(attrs);
+    replay(mf);
+    expect(attrs.getValue(Attributes.Name.MAIN_CLASS)).andReturn(mainClassName);
+    replay(attrs);
+  }
+}


Mime
View raw message