001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.util; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertFalse; 022import static org.junit.Assert.assertNotNull; 023import static org.junit.Assert.assertTrue; 024import static org.junit.Assert.fail; 025 026import java.io.File; 027import java.io.FileInputStream; 028import java.io.FileOutputStream; 029import org.apache.hadoop.conf.Configuration; 030import org.apache.hadoop.fs.Path; 031import org.apache.hadoop.hbase.HBaseClassTestRule; 032import org.apache.hadoop.hbase.HBaseCommonTestingUtility; 033import org.apache.hadoop.hbase.testclassification.MiscTests; 034import org.apache.hadoop.hbase.testclassification.SmallTests; 035import org.apache.hadoop.io.IOUtils; 036import org.junit.ClassRule; 037import org.junit.Test; 038import org.junit.experimental.categories.Category; 039 040/** 041 * Test TestCoprocessorClassLoader. More tests are in TestClassLoading 042 */ 043@Category({MiscTests.class, SmallTests.class}) 044public class TestCoprocessorClassLoader { 045 @ClassRule 046 public static final HBaseClassTestRule CLASS_RULE = 047 HBaseClassTestRule.forClass(TestCoprocessorClassLoader.class); 048 049 private static final HBaseCommonTestingUtility TEST_UTIL = new HBaseCommonTestingUtility(); 050 private static final Configuration conf = TEST_UTIL.getConfiguration(); 051 static { 052 TEST_UTIL.getDataTestDir(); // prepare data test dir and hbase local dir 053 } 054 055 @Test 056 public void testCleanupOldJars() throws Exception { 057 String className = "TestCleanupOldJars"; 058 String folder = TEST_UTIL.getDataTestDir().toString(); 059 File jarFile = ClassLoaderTestHelper.buildJar( 060 folder, className, null, ClassLoaderTestHelper.localDirPath(conf)); 061 File tmpJarFile = new File(jarFile.getParent(), "/tmp/" + className + ".test.jar"); 062 063 if (tmpJarFile.exists()) { 064 tmpJarFile.delete(); 065 } 066 067 assertFalse("tmp jar file should not exist", tmpJarFile.exists()); 068 ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader(); 069 CoprocessorClassLoader.getClassLoader(new Path(jarFile.getParent()), parent, "112", conf); 070 IOUtils.copyBytes(new FileInputStream(jarFile), 071 new FileOutputStream(tmpJarFile), conf, true); 072 assertTrue("tmp jar file should be created", tmpJarFile.exists()); 073 Path path = new Path(jarFile.getAbsolutePath()); 074 CoprocessorClassLoader.parentDirLockSet.clear(); // So that clean up can be triggered 075 ClassLoader classLoader = CoprocessorClassLoader.getClassLoader(path, parent, "111", conf); 076 assertNotNull("Classloader should be created", classLoader); 077 assertFalse("tmp jar file should be removed", tmpJarFile.exists()); 078 } 079 080 @Test 081 public void testLibJarName() throws Exception { 082 checkingLibJarName("TestLibJarName.jar", "/lib/"); 083 } 084 085 @Test 086 public void testRelativeLibJarName() throws Exception { 087 checkingLibJarName("TestRelativeLibJarName.jar", "lib/"); 088 } 089 090 /** 091 * Test to make sure the lib jar file extracted from a coprocessor jar have 092 * the right name. Otherwise, some existing jar could be override if there are 093 * naming conflicts. 094 */ 095 private void checkingLibJarName(String jarName, String libPrefix) throws Exception { 096 File tmpFolder = new File(ClassLoaderTestHelper.localDirPath(conf), "tmp"); 097 if (tmpFolder.exists()) { // Clean up the tmp folder 098 File[] files = tmpFolder.listFiles(); 099 if (files != null) { 100 for (File f: files) { 101 f.delete(); 102 } 103 } 104 } 105 String className = "CheckingLibJarName"; 106 String folder = TEST_UTIL.getDataTestDir().toString(); 107 File innerJarFile = ClassLoaderTestHelper.buildJar( 108 folder, className, null, ClassLoaderTestHelper.localDirPath(conf)); 109 File targetJarFile = new File(innerJarFile.getParent(), jarName); 110 ClassLoaderTestHelper.addJarFilesToJar(targetJarFile, libPrefix, innerJarFile); 111 Path path = new Path(targetJarFile.getAbsolutePath()); 112 ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader(); 113 ClassLoader classLoader = CoprocessorClassLoader.getClassLoader(path, parent, "112", conf); 114 assertNotNull("Classloader should be created", classLoader); 115 String fileToLookFor = "." + className + ".jar"; 116 String[] files = tmpFolder.list(); 117 if (files != null) { 118 for (String f: files) { 119 if (f.endsWith(fileToLookFor) && f.contains(jarName)) { 120 // Cool, found it; 121 return; 122 } 123 } 124 } 125 fail("Could not find the expected lib jar file"); 126 } 127 128 // HBASE-14548 129 @Test 130 public void testDirectoryAndWildcard() throws Exception { 131 String testClassName = "TestClass"; 132 String dataTestDir = TEST_UTIL.getDataTestDir().toString(); 133 System.out.println(dataTestDir); 134 String localDirContainingJar = ClassLoaderTestHelper.localDirPath(conf); 135 ClassLoaderTestHelper.buildJar(dataTestDir, testClassName, null, localDirContainingJar); 136 ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader(); 137 CoprocessorClassLoader.parentDirLockSet.clear(); // So that clean up can be triggered 138 139 // Directory 140 Path testPath = new Path(localDirContainingJar); 141 CoprocessorClassLoader coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath, 142 parent, "113_1", conf); 143 verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName); 144 145 // Wildcard - *.jar 146 testPath = new Path(localDirContainingJar, "*.jar"); 147 coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath, parent, "113_2", conf); 148 verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName); 149 150 // Wildcard - *.j* 151 testPath = new Path(localDirContainingJar, "*.j*"); 152 coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath, parent, "113_3", conf); 153 verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName); 154 } 155 156 /** 157 * Verify the coprocessorClassLoader is not null and the expected class can be loaded successfully 158 * @param coprocessorClassLoader the CoprocessorClassLoader to verify 159 * @param className the expected class to be loaded by the coprocessorClassLoader 160 * @throws ClassNotFoundException if the class, which should be loaded via the 161 * coprocessorClassLoader, does not exist 162 */ 163 private void verifyCoprocessorClassLoader(CoprocessorClassLoader coprocessorClassLoader, 164 String className) throws ClassNotFoundException { 165 assertNotNull("Classloader should be created and not null", coprocessorClassLoader); 166 assertEquals(className, coprocessorClassLoader.loadClass(className).getName()); 167 } 168}