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.HBaseCommonTestingUtil; 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 HBaseCommonTestingUtil TEST_UTIL = new HBaseCommonTestingUtil(); 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(folder, className, null, 060 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), new FileOutputStream(tmpJarFile), conf, true); 071 assertTrue("tmp jar file should be created", tmpJarFile.exists()); 072 Path path = new Path(jarFile.getAbsolutePath()); 073 CoprocessorClassLoader.parentDirLockSet.clear(); // So that clean up can be triggered 074 ClassLoader classLoader = CoprocessorClassLoader.getClassLoader(path, parent, "111", conf); 075 assertNotNull("Classloader should be created", classLoader); 076 assertFalse("tmp jar file should be removed", tmpJarFile.exists()); 077 } 078 079 @Test 080 public void testLibJarName() throws Exception { 081 checkingLibJarName("TestLibJarName.jar", "/lib/"); 082 } 083 084 @Test 085 public void testRelativeLibJarName() throws Exception { 086 checkingLibJarName("TestRelativeLibJarName.jar", "lib/"); 087 } 088 089 /** 090 * Test to make sure the lib jar file extracted from a coprocessor jar have the right name. 091 * Otherwise, some existing jar could be override if there are naming conflicts. 092 */ 093 private void checkingLibJarName(String jarName, String libPrefix) throws Exception { 094 File tmpFolder = new File(ClassLoaderTestHelper.localDirPath(conf), "tmp"); 095 if (tmpFolder.exists()) { // Clean up the tmp folder 096 File[] files = tmpFolder.listFiles(); 097 if (files != null) { 098 for (File f : files) { 099 f.delete(); 100 } 101 } 102 } 103 String className = "CheckingLibJarName"; 104 String folder = TEST_UTIL.getDataTestDir().toString(); 105 File innerJarFile = ClassLoaderTestHelper.buildJar(folder, className, null, 106 ClassLoaderTestHelper.localDirPath(conf)); 107 File targetJarFile = new File(innerJarFile.getParent(), jarName); 108 ClassLoaderTestHelper.addJarFilesToJar(targetJarFile, libPrefix, innerJarFile); 109 Path path = new Path(targetJarFile.getAbsolutePath()); 110 ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader(); 111 ClassLoader classLoader = CoprocessorClassLoader.getClassLoader(path, parent, "112", conf); 112 assertNotNull("Classloader should be created", classLoader); 113 String fileToLookFor = "." + className + ".jar"; 114 String[] files = tmpFolder.list(); 115 if (files != null) { 116 for (String f : files) { 117 if (f.endsWith(fileToLookFor) && f.contains(jarName)) { 118 // Cool, found it; 119 return; 120 } 121 } 122 } 123 fail("Could not find the expected lib jar file"); 124 } 125 126 // HBASE-14548 127 @Test 128 public void testDirectoryAndWildcard() throws Exception { 129 String testClassName = "TestClass"; 130 String dataTestDir = TEST_UTIL.getDataTestDir().toString(); 131 System.out.println(dataTestDir); 132 String localDirContainingJar = ClassLoaderTestHelper.localDirPath(conf); 133 ClassLoaderTestHelper.buildJar(dataTestDir, testClassName, null, localDirContainingJar); 134 ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader(); 135 CoprocessorClassLoader.parentDirLockSet.clear(); // So that clean up can be triggered 136 137 // Directory 138 Path testPath = new Path(localDirContainingJar); 139 CoprocessorClassLoader coprocessorClassLoader = 140 CoprocessorClassLoader.getClassLoader(testPath, parent, "113_1", conf); 141 verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName); 142 143 // Wildcard - *.jar 144 testPath = new Path(localDirContainingJar, "*.jar"); 145 coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath, parent, "113_2", conf); 146 verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName); 147 148 // Wildcard - *.j* 149 testPath = new Path(localDirContainingJar, "*.j*"); 150 coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath, parent, "113_3", conf); 151 verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName); 152 } 153 154 /** 155 * Verify the coprocessorClassLoader is not null and the expected class can be loaded successfully 156 * @param coprocessorClassLoader the CoprocessorClassLoader to verify 157 * @param className the expected class to be loaded by the coprocessorClassLoader 158 * @throws ClassNotFoundException if the class, which should be loaded via the 159 * coprocessorClassLoader, does not exist 160 */ 161 private void verifyCoprocessorClassLoader(CoprocessorClassLoader coprocessorClassLoader, 162 String className) throws ClassNotFoundException { 163 assertNotNull("Classloader should be created and not null", coprocessorClassLoader); 164 assertEquals(className, coprocessorClassLoader.loadClass(className).getName()); 165 } 166}