/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseCommonTestingUtility;
import org.apache.hadoop.hbase.testclassification.MiscTests;
import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.apache.hadoop.io.IOUtils;
import org.junit.Test;
import org.junit.experimental.categories.Category;
/**
* Test TestCoprocessorClassLoader. More tests are in TestClassLoading
*/
@Category({MiscTests.class, SmallTests.class})
public class TestCoprocessorClassLoader {
private static final HBaseCommonTestingUtility TEST_UTIL = new HBaseCommonTestingUtility();
private static final Configuration conf = TEST_UTIL.getConfiguration();
static {
TEST_UTIL.getDataTestDir(); // prepare data test dir and hbase local dir
}
@Test
public void testCleanupOldJars() throws Exception {
String className = "TestCleanupOldJars";
String folder = TEST_UTIL.getDataTestDir().toString();
File jarFile = ClassLoaderTestHelper.buildJar(
folder, className, null, ClassLoaderTestHelper.localDirPath(conf));
File tmpJarFile = new File(jarFile.getParent(), "/tmp/" + className + ".test.jar");
if (tmpJarFile.exists()) tmpJarFile.delete();
assertFalse("tmp jar file should not exist", tmpJarFile.exists());
IOUtils.copyBytes(new FileInputStream(jarFile),
new FileOutputStream(tmpJarFile), conf, true);
assertTrue("tmp jar file should be created", tmpJarFile.exists());
Path path = new Path(jarFile.getAbsolutePath());
ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader();
CoprocessorClassLoader.parentDirLockSet.clear(); // So that clean up can be triggered
ClassLoader classLoader = CoprocessorClassLoader.getClassLoader(path, parent, "111", conf);
assertNotNull("Classloader should be created", classLoader);
assertFalse("tmp jar file should be removed", tmpJarFile.exists());
}
@Test
public void testLibJarName() throws Exception {
checkingLibJarName("TestLibJarName.jar", "/lib/");
}
@Test
public void testRelativeLibJarName() throws Exception {
checkingLibJarName("TestRelativeLibJarName.jar", "lib/");
}
/**
* Test to make sure the lib jar file extracted from a coprocessor jar have
* the right name. Otherwise, some existing jar could be override if there are
* naming conflicts.
*/
private void checkingLibJarName(String jarName, String libPrefix) throws Exception {
File tmpFolder = new File(ClassLoaderTestHelper.localDirPath(conf), "tmp");
if (tmpFolder.exists()) { // Clean up the tmp folder
for (File f: tmpFolder.listFiles()) {
f.delete();
}
}
String className = "CheckingLibJarName";
String folder = TEST_UTIL.getDataTestDir().toString();
File innerJarFile = ClassLoaderTestHelper.buildJar(
folder, className, null, ClassLoaderTestHelper.localDirPath(conf));
File targetJarFile = new File(innerJarFile.getParent(), jarName);
ClassLoaderTestHelper.addJarFilesToJar(targetJarFile, libPrefix, innerJarFile);
Path path = new Path(targetJarFile.getAbsolutePath());
ClassLoader parent = TestCoprocessorClassLoader.class.getClassLoader();
ClassLoader classLoader = CoprocessorClassLoader.getClassLoader(path, parent, "112", conf);
assertNotNull("Classloader should be created", classLoader);
String fileToLookFor = "." + className + ".jar";
for (String f: tmpFolder.list()) {
if (f.endsWith(fileToLookFor) && f.contains(jarName)) {
// Cool, found it;
return;
}
}
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());
}
}