Repository: hbase
Updated Branches:
  refs/heads/0.98 27c583467 -> 6dfdc0d89


HBASE-14548 Expand how table coprocessor jar and dependency path can be 
specified (Xiang Li)

Amending-Author: Andrew Purtell <apurt...@apache.org>


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

Branch: refs/heads/0.98
Commit: f750acb751c5cc3b4a3292451c0504942b62bf39
Parents: 27c5834
Author: Jerry He <jerry...@apache.org>
Authored: Sat Jul 9 18:18:22 2016 -0700
Committer: Andrew Purtell <apurt...@apache.org>
Committed: Mon Aug 1 15:52:44 2016 -0700

----------------------------------------------------------------------
 .../hbase/util/CoprocessorClassLoader.java      | 74 +++++++++++++-------
 .../hbase/util/TestCoprocessorClassLoader.java  | 43 ++++++++++++
 2 files changed, 93 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/f750acb7/hbase-common/src/main/java/org/apache/hadoop/hbase/util/CoprocessorClassLoader.java
----------------------------------------------------------------------
diff --git 
a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/CoprocessorClassLoader.java
 
b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/CoprocessorClassLoader.java
index fb2a127..9b65807 100644
--- 
a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/CoprocessorClassLoader.java
+++ 
b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/CoprocessorClassLoader.java
@@ -18,6 +18,7 @@
 package org.apache.hadoop.hbase.util;
 
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.net.URL;
@@ -39,6 +40,9 @@ import 
org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.FileUtil;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.io.IOUtils;
 
 import com.google.common.base.Preconditions;
@@ -155,7 +159,7 @@ public class CoprocessorClassLoader extends ClassLoaderBase 
{
     super(parent);
   }
 
-  private void init(Path path, String pathPrefix,
+  private void init(Path pathPattern, String pathPrefix,
       Configuration conf) throws IOException {
     // Copy the jar to the local filesystem
     String parentDirStr =
@@ -173,31 +177,53 @@ public class CoprocessorClassLoader extends 
ClassLoaderBase {
       }
     }
 
-    FileSystem fs = path.getFileSystem(conf);
-    File dst = new File(parentDirStr, "." + pathPrefix + "."
-      + path.getName() + "." + System.currentTimeMillis() + ".jar");
-    fs.copyToLocalFile(path, new Path(dst.toString()));
-    dst.deleteOnExit();
-
-    addURL(dst.getCanonicalFile().toURI().toURL());
+    FileSystem fs = pathPattern.getFileSystem(conf);
+    Path pathPattern1 = fs.isDirectory(pathPattern) ?
+      new Path(pathPattern, "*.jar") : pathPattern;  // append "*.jar" if a 
directory is specified
+    FileStatus[] fileStatuses = fs.globStatus(pathPattern1);  // return all 
files that match the pattern
+    if (fileStatuses == null || fileStatuses.length == 0) {  // if no one 
matches
+      throw new FileNotFoundException(pathPattern1.toString());
+    } else {
+      boolean validFileEncountered = false;
+      for (Path path : FileUtil.stat2Paths(fileStatuses)) {  // for each file 
that match the pattern
+        if (fs.isFile(path)) {  // only process files, skip for directories
+          File dst = new File(parentDirStr, "." + pathPrefix + "."
+            + path.getName() + "." + System.currentTimeMillis() + ".jar");
+          fs.copyToLocalFile(path, new Path(dst.toString()));
+          dst.deleteOnExit();
+
+          addURL(dst.getCanonicalFile().toURI().toURL());
+
+          JarFile jarFile = new JarFile(dst.toString());
+          try {
+            Enumeration<JarEntry> entries = jarFile.entries();  // get entries 
inside a jar file
+            while (entries.hasMoreElements()) {
+              JarEntry entry = entries.nextElement();
+              Matcher m = libJarPattern.matcher(entry.getName());
+              if (m.matches()) {
+                File file = new File(parentDirStr, "." + pathPrefix + "."
+                  + path.getName() + "." + System.currentTimeMillis() + "." + 
m.group(1));
+                FileOutputStream outStream = new FileOutputStream(file);
+                try {
+                  IOUtils.copyBytes(jarFile.getInputStream(entry),
+                    outStream, conf, true);
+                } finally {
+                  outStream.close();
+                }
+                file.deleteOnExit();
+                addURL(file.toURI().toURL());
+              }
+            }
+          } finally {
+            jarFile.close();
+          }
 
-    JarFile jarFile = new JarFile(dst.toString());
-    try {
-      Enumeration<JarEntry> entries = jarFile.entries();
-      while (entries.hasMoreElements()) {
-        JarEntry entry = entries.nextElement();
-        Matcher m = libJarPattern.matcher(entry.getName());
-        if (m.matches()) {
-          File file = new File(parentDirStr, "." + pathPrefix + "."
-            + path.getName() + "." + System.currentTimeMillis() + "." + 
m.group(1));
-          IOUtils.copyBytes(jarFile.getInputStream(entry),
-            new FileOutputStream(file), conf, true);
-          file.deleteOnExit();
-          addURL(file.toURI().toURL());
+          validFileEncountered = true;  // Set to true when encountering a file
         }
       }
-    } finally {
-      jarFile.close();
+      if (validFileEncountered == false) {  // all items returned by 
globStatus() are directories
+        throw new FileNotFoundException("No file found matching " + 
pathPattern1.toString());
+      }
     }
   }
 
@@ -238,7 +264,7 @@ public class CoprocessorClassLoader extends ClassLoaderBase 
{
       return cl;
     }
 
-    if (!pathStr.endsWith(".jar")) {
+    if (path.getFileSystem(conf).isFile(path) && !pathStr.endsWith(".jar")) {
       throw new IOException(pathStr + ": not a jar file?");
     }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/f750acb7/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestCoprocessorClassLoader.java
----------------------------------------------------------------------
diff --git 
a/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestCoprocessorClassLoader.java
 
b/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestCoprocessorClassLoader.java
index f4b2002..e1048da 100644
--- 
a/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestCoprocessorClassLoader.java
+++ 
b/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestCoprocessorClassLoader.java
@@ -21,6 +21,7 @@ package org.apache.hadoop.hbase.util;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
 import java.io.File;
@@ -108,4 +109,46 @@ public class TestCoprocessorClassLoader {
     }
     fail("Could not find the expected lib jar file");
   }
+
+  // HBASE-14548
+  @Test
+  public void testDirectoryAndWildcard() throws Exception {
+    String testClassName = "TestClass";
+    String dataTestDir = TEST_UTIL.getDataTestDir().toString();
+    System.out.println(dataTestDir);
+    String localDirContainingJar = ClassLoaderTestHelper.localDirPath(conf);
+    ClassLoaderTestHelper.buildJar(dataTestDir, testClassName, null, 
localDirContainingJar);
+    ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader();
+    CoprocessorClassLoader.parentDirLockSet.clear(); // So that clean up can 
be triggered
+
+    CoprocessorClassLoader coprocessorClassLoader = null;
+    Path testPath = null;
+
+    // Directory
+    testPath = new Path(localDirContainingJar);
+    coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath, 
parent, "113_1", conf);
+    verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName);
+
+    // Wildcard - *.jar
+    testPath = new Path(localDirContainingJar, "*.jar");
+    coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath, 
parent, "113_2", conf);
+    verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName);
+
+    // Wildcard - *.j*
+    testPath = new Path(localDirContainingJar, "*.j*");
+    coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath, 
parent, "113_3", conf);
+    verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName);
+  }
+
+  /**
+   * Verify the coprocessorClassLoader is not null and the expected class can 
be loaded successfully
+   * @param coprocessorClassLoader the CoprocessorClassLoader to verify
+   * @param className the expected class to be loaded by the 
coprocessorClassLoader
+   * @throws ClassNotFoundException
+   */
+  private void verifyCoprocessorClassLoader(CoprocessorClassLoader 
coprocessorClassLoader, String className)
+    throws ClassNotFoundException{
+    assertNotNull("Classloader should be created and not null", 
coprocessorClassLoader);
+    assertEquals(className, 
coprocessorClassLoader.loadClass(className).getName());
+  }
 }

Reply via email to