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.jupiter.api.Assertions.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertFalse; 022import static org.junit.jupiter.api.Assertions.assertNotNull; 023import static org.junit.jupiter.api.Assertions.assertTrue; 024import static org.junit.jupiter.api.Assertions.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.HBaseCommonTestingUtil; 032import org.apache.hadoop.hbase.testclassification.MiscTests; 033import org.apache.hadoop.hbase.testclassification.SmallTests; 034import org.apache.hadoop.io.IOUtils; 035import org.junit.jupiter.api.Tag; 036import org.junit.jupiter.api.Test; 037 038/** 039 * Test TestCoprocessorClassLoader. More tests are in TestClassLoading 040 */ 041@Tag(MiscTests.TAG) 042@Tag(SmallTests.TAG) 043public class TestCoprocessorClassLoader { 044 private static final HBaseCommonTestingUtil TEST_UTIL = new HBaseCommonTestingUtil(); 045 private static final Configuration conf = TEST_UTIL.getConfiguration(); 046 static { 047 TEST_UTIL.getDataTestDir(); // prepare data test dir and hbase local dir 048 } 049 050 @Test 051 public void testCleanupOldJars() throws Exception { 052 String className = "TestCleanupOldJars"; 053 String folder = TEST_UTIL.getDataTestDir().toString(); 054 File jarFile = ClassLoaderTestHelper.buildJar(folder, className, null, 055 ClassLoaderTestHelper.localDirPath(conf)); 056 File tmpJarFile = new File(jarFile.getParent(), "/tmp/" + className + ".test.jar"); 057 058 if (tmpJarFile.exists()) { 059 tmpJarFile.delete(); 060 } 061 062 assertFalse(tmpJarFile.exists(), "tmp jar file should not exist"); 063 ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader(); 064 CoprocessorClassLoader.getClassLoader(new Path(jarFile.getParent()), parent, "112", conf); 065 IOUtils.copyBytes(new FileInputStream(jarFile), new FileOutputStream(tmpJarFile), conf, true); 066 assertTrue(tmpJarFile.exists(), "tmp jar file should be created"); 067 Path path = new Path(jarFile.getAbsolutePath()); 068 CoprocessorClassLoader.parentDirLockSet.clear(); // So that clean up can be triggered 069 ClassLoader classLoader = CoprocessorClassLoader.getClassLoader(path, parent, "111", conf); 070 assertNotNull(classLoader, "Classloader should be created"); 071 assertFalse(tmpJarFile.exists(), "tmp jar file should be removed"); 072 } 073 074 @Test 075 public void testLibJarName() throws Exception { 076 checkingLibJarName("TestLibJarName.jar", "/lib/"); 077 } 078 079 @Test 080 public void testRelativeLibJarName() throws Exception { 081 checkingLibJarName("TestRelativeLibJarName.jar", "lib/"); 082 } 083 084 /** 085 * Test to make sure the lib jar file extracted from a coprocessor jar have the right name. 086 * Otherwise, some existing jar could be override if there are naming conflicts. 087 */ 088 private void checkingLibJarName(String jarName, String libPrefix) throws Exception { 089 File tmpFolder = new File(ClassLoaderTestHelper.localDirPath(conf), "tmp"); 090 if (tmpFolder.exists()) { // Clean up the tmp folder 091 File[] files = tmpFolder.listFiles(); 092 if (files != null) { 093 for (File f : files) { 094 f.delete(); 095 } 096 } 097 } 098 String className = "CheckingLibJarName"; 099 String folder = TEST_UTIL.getDataTestDir().toString(); 100 File innerJarFile = ClassLoaderTestHelper.buildJar(folder, className, null, 101 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, "Classloader should be created"); 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 String localDirContainingJar = ClassLoaderTestHelper.localDirPath(conf); 127 ClassLoaderTestHelper.buildJar(dataTestDir, testClassName, null, localDirContainingJar); 128 ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader(); 129 CoprocessorClassLoader.parentDirLockSet.clear(); // So that clean up can be triggered 130 131 // Directory 132 Path testPath = new Path(localDirContainingJar); 133 CoprocessorClassLoader coprocessorClassLoader = 134 CoprocessorClassLoader.getClassLoader(testPath, parent, "113_1", conf); 135 verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName); 136 137 // Wildcard - *.jar 138 testPath = new Path(localDirContainingJar, "*.jar"); 139 coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath, parent, "113_2", conf); 140 verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName); 141 142 // Wildcard - *.j* 143 testPath = new Path(localDirContainingJar, "*.j*"); 144 coprocessorClassLoader = CoprocessorClassLoader.getClassLoader(testPath, parent, "113_3", conf); 145 verifyCoprocessorClassLoader(coprocessorClassLoader, testClassName); 146 } 147 148 /** 149 * Verify the coprocessorClassLoader is not null and the expected class can be loaded successfully 150 * @param coprocessorClassLoader the CoprocessorClassLoader to verify 151 * @param className the expected class to be loaded by the coprocessorClassLoader 152 * @throws ClassNotFoundException if the class, which should be loaded via the 153 * coprocessorClassLoader, does not exist 154 */ 155 private void verifyCoprocessorClassLoader(CoprocessorClassLoader coprocessorClassLoader, 156 String className) throws ClassNotFoundException { 157 assertNotNull(coprocessorClassLoader, "Classloader should be created and not null"); 158 assertEquals(className, coprocessorClassLoader.loadClass(className).getName()); 159 } 160}