View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.util;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertFalse;
22  import static org.junit.Assert.assertNotNull;
23  import static org.junit.Assert.assertTrue;
24  import static org.junit.Assert.fail;
25  
26  import java.io.File;
27  import java.io.FileInputStream;
28  import java.io.FileOutputStream;
29  
30  import org.apache.hadoop.conf.Configuration;
31  import org.apache.hadoop.fs.Path;
32  import org.apache.hadoop.hbase.HBaseCommonTestingUtility;
33  import org.apache.hadoop.hbase.testclassification.SmallTests;
34  import org.apache.hadoop.io.IOUtils;
35  import org.junit.Test;
36  import org.junit.experimental.categories.Category;
37  
38  /**
39   * Test TestCoprocessorClassLoader. More tests are in TestClassLoading
40   */
41  @Category(SmallTests.class)
42  public class TestCoprocessorClassLoader {
43    private static final HBaseCommonTestingUtility TEST_UTIL = new HBaseCommonTestingUtility();
44    private static final Configuration conf = TEST_UTIL.getConfiguration();
45    static {
46      TEST_UTIL.getDataTestDir(); // prepare data test dir and hbase local dir
47    }
48  
49    @Test
50    public void testCleanupOldJars() throws Exception {
51      String className = "TestCleanupOldJars";
52      String folder = TEST_UTIL.getDataTestDir().toString();
53      File jarFile = ClassLoaderTestHelper.buildJar(
54        folder, className, null, ClassLoaderTestHelper.localDirPath(conf));
55      File tmpJarFile = new File(jarFile.getParent(), "/tmp/" + className + ".test.jar");
56  
57      if (tmpJarFile.exists()) {
58        tmpJarFile.delete();
59      }
60  
61      assertFalse("tmp jar file should not exist", tmpJarFile.exists());
62      IOUtils.copyBytes(new FileInputStream(jarFile),
63        new FileOutputStream(tmpJarFile), conf, true);
64      assertTrue("tmp jar file should be created", tmpJarFile.exists());
65      Path path = new Path(jarFile.getAbsolutePath());
66      ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader();
67      CoprocessorClassLoader.parentDirLockSet.clear(); // So that clean up can be triggered
68      ClassLoader classLoader = CoprocessorClassLoader.getClassLoader(path, parent, "111", conf);
69      assertNotNull("Classloader should be created", classLoader);
70      assertFalse("tmp jar file should be removed", tmpJarFile.exists());
71    }
72  
73    @Test
74    public void testLibJarName() throws Exception {
75      checkingLibJarName("TestLibJarName.jar", "/lib/");
76    }
77  
78    @Test
79    public void testRelativeLibJarName() throws Exception {
80      checkingLibJarName("TestRelativeLibJarName.jar", "lib/");
81    }
82  
83    /**
84     * Test to make sure the lib jar file extracted from a coprocessor jar have
85     * the right name.  Otherwise, some existing jar could be override if there are
86     * naming conflicts.
87     */
88    private void checkingLibJarName(String jarName, String libPrefix) throws Exception {
89      File tmpFolder = new File(ClassLoaderTestHelper.localDirPath(conf), "tmp");
90      if (tmpFolder.exists()) { // Clean up the tmp folder
91        File[] files = tmpFolder.listFiles();
92        if (files != null) {
93          for (File f: files) {
94            f.delete();
95          }
96        }
97      }
98      String className = "CheckingLibJarName";
99      String folder = TEST_UTIL.getDataTestDir().toString();
100     File innerJarFile = ClassLoaderTestHelper.buildJar(
101       folder, className, null, ClassLoaderTestHelper.localDirPath(conf));
102     File targetJarFile = new File(innerJarFile.getParent(), jarName);
103     ClassLoaderTestHelper.addJarFilesToJar(targetJarFile, libPrefix, innerJarFile);
104     Path path = new Path(targetJarFile.getAbsolutePath());
105     ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader();
106     ClassLoader classLoader = CoprocessorClassLoader.getClassLoader(path, parent, "112", conf);
107     assertNotNull("Classloader should be created", classLoader);
108     String fileToLookFor = "." + className + ".jar";
109     String[] files = tmpFolder.list();
110     if (files != null) {
111       for (String f: files) {
112         if (f.endsWith(fileToLookFor) && f.contains(jarName)) {
113           // Cool, found it;
114           return;
115         }
116       }
117     }
118     fail("Could not find the expected lib jar file");
119   }
120 
121   // HBASE-14548
122   @Test
123   public void testDirectoryAndWildcard() throws Exception {
124     String testClassName = "TestClass";
125     String dataTestDir = TEST_UTIL.getDataTestDir().toString();
126     System.out.println(dataTestDir);
127     String localDirContainingJar = ClassLoaderTestHelper.localDirPath(conf);
128     ClassLoaderTestHelper.buildJar(dataTestDir, testClassName, null, localDirContainingJar);
129     ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader();
130     CoprocessorClassLoader.parentDirLockSet.clear(); // So that clean up can be triggered
131 
132     // Directory
133     Path testPath = new Path(localDirContainingJar);
134     CoprocessorClassLoader coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath,
135       parent, "113_1", conf);
136     verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName);
137 
138     // Wildcard - *.jar
139     testPath = new Path(localDirContainingJar, "*.jar");
140     coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath, parent, "113_2", conf);
141     verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName);
142 
143     // Wildcard - *.j*
144     testPath = new Path(localDirContainingJar, "*.j*");
145     coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath, parent, "113_3", conf);
146     verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName);
147   }
148 
149   /**
150    * Verify the coprocessorClassLoader is not null and the expected class can be loaded successfully
151    * @param coprocessorClassLoader the CoprocessorClassLoader to verify
152    * @param className the expected class to be loaded by the coprocessorClassLoader
153    * @throws ClassNotFoundException if the class, which should be loaded via the
154    *    coprocessorClassLoader, does not exist
155    */
156   private void verifyCoprocessorClassLoader(CoprocessorClassLoader coprocessorClassLoader,
157       String className) throws ClassNotFoundException {
158     assertNotNull("Classloader should be created and not null", coprocessorClassLoader);
159     assertEquals(className, coprocessorClassLoader.loadClass(className).getName());
160   }
161 }