1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.util;
20
21 import static org.junit.Assert.assertTrue;
22 import static org.junit.Assert.fail;
23
24 import java.io.BufferedWriter;
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.FileOutputStream;
28 import java.io.FileWriter;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.jar.JarEntry;
32 import java.util.jar.JarOutputStream;
33 import java.util.jar.Manifest;
34
35 import javax.tools.JavaCompiler;
36 import javax.tools.JavaFileObject;
37 import javax.tools.StandardJavaFileManager;
38 import javax.tools.ToolProvider;
39
40 import org.apache.commons.logging.Log;
41 import org.apache.commons.logging.LogFactory;
42 import org.apache.hadoop.conf.Configuration;
43 import org.apache.hadoop.fs.Path;
44 import org.apache.hadoop.hbase.HBaseConfiguration;
45 import org.apache.hadoop.hbase.HBaseTestingUtility;
46 import org.apache.hadoop.hbase.SmallTests;
47 import org.junit.Test;
48 import org.junit.experimental.categories.Category;
49
50
51
52
53 @Category(SmallTests.class)
54 public class TestDynamicClassLoader {
55 private static final Log LOG = LogFactory.getLog(TestDynamicClassLoader.class);
56
57 private static final Configuration conf = HBaseConfiguration.create();
58
59 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
60
61 static {
62 conf.set("hbase.dynamic.jars.dir", TEST_UTIL.getDataTestDir().toString());
63 }
64
65
66 private boolean createJarArchive(File archiveFile, File[] tobeJared) {
67 try {
68 byte buffer[] = new byte[4096];
69
70 FileOutputStream stream = new FileOutputStream(archiveFile);
71 JarOutputStream out = new JarOutputStream(stream, new Manifest());
72
73 for (int i = 0; i < tobeJared.length; i++) {
74 if (tobeJared[i] == null || !tobeJared[i].exists()
75 || tobeJared[i].isDirectory()) {
76 continue;
77 }
78
79
80 JarEntry jarAdd = new JarEntry(tobeJared[i].getName());
81 jarAdd.setTime(tobeJared[i].lastModified());
82 out.putNextEntry(jarAdd);
83
84
85 FileInputStream in = new FileInputStream(tobeJared[i]);
86 while (true) {
87 int nRead = in.read(buffer, 0, buffer.length);
88 if (nRead <= 0)
89 break;
90 out.write(buffer, 0, nRead);
91 }
92 in.close();
93 }
94 out.close();
95 stream.close();
96 LOG.info("Adding classes to jar file completed");
97 return true;
98 } catch (Exception ex) {
99 LOG.error("Error: " + ex.getMessage());
100 return false;
101 }
102 }
103
104 private File buildJar(
105 String className, String folder) throws Exception {
106 String javaCode = "public class " + className + " {}";
107 Path srcDir = new Path(TEST_UTIL.getDataTestDir(), "src");
108 File srcDirPath = new File(srcDir.toString());
109 srcDirPath.mkdirs();
110 File sourceCodeFile = new File(srcDir.toString(), className + ".java");
111 BufferedWriter bw = new BufferedWriter(new FileWriter(sourceCodeFile));
112 bw.write(javaCode);
113 bw.close();
114
115
116 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
117 ArrayList<String> srcFileNames = new ArrayList<String>();
118 srcFileNames.add(sourceCodeFile.toString());
119 StandardJavaFileManager fm = compiler.getStandardFileManager(null, null,
120 null);
121 Iterable<? extends JavaFileObject> cu =
122 fm.getJavaFileObjects(sourceCodeFile);
123 List<String> options = new ArrayList<String>();
124 options.add("-classpath");
125
126
127 String currentDir = new File(".").getAbsolutePath();
128 String classpath =
129 currentDir + File.separator + "target"+ File.separator + "classes" +
130 System.getProperty("path.separator") + System.getProperty("java.class.path");
131 options.add(classpath);
132 LOG.debug("Setting classpath to: "+classpath);
133
134 JavaCompiler.CompilationTask task = compiler.getTask(null, fm, null,
135 options, null, cu);
136 assertTrue("Compile file " + sourceCodeFile + " failed.", task.call());
137
138
139 String jarFileName = className + ".jar";
140 File jarFile = new File(folder, jarFileName);
141 if (!createJarArchive(jarFile,
142 new File[]{new File(srcDir.toString(), className + ".class")})){
143 assertTrue("Build jar file failed.", false);
144 }
145 return jarFile;
146 }
147
148 @Test
149 public void testLoadClassFromLocalPath() throws Exception {
150 ClassLoader parent = TestDynamicClassLoader.class.getClassLoader();
151 DynamicClassLoader classLoader = new DynamicClassLoader(conf, parent);
152
153 String className = "TestLoadClassFromLocalPath";
154 try {
155 classLoader.loadClass(className);
156 fail("Should not be able to load class " + className);
157 } catch (ClassNotFoundException cnfe) {
158
159 }
160
161 try {
162 buildJar(className, localDirPath());
163 classLoader.loadClass(className);
164 } catch (ClassNotFoundException cnfe) {
165 LOG.error("Should be able to load class " + className, cnfe);
166 fail(cnfe.getMessage());
167 } finally {
168 deleteClass(className);
169 }
170 }
171
172 @Test
173 public void testLoadClassFromAnotherPath() throws Exception {
174 ClassLoader parent = TestDynamicClassLoader.class.getClassLoader();
175 DynamicClassLoader classLoader = new DynamicClassLoader(conf, parent);
176
177 String className = "TestLoadClassFromAnotherPath";
178 try {
179 classLoader.loadClass(className);
180 fail("Should not be able to load class " + className);
181 } catch (ClassNotFoundException cnfe) {
182
183 }
184
185 try {
186 buildJar(className, TEST_UTIL.getDataTestDir().toString());
187 classLoader.loadClass(className);
188 } catch (ClassNotFoundException cnfe) {
189 LOG.error("Should be able to load class " + className, cnfe);
190 fail(cnfe.getMessage());
191 } finally {
192 deleteClass(className);
193 }
194 }
195
196 private String localDirPath() {
197 return conf.get("hbase.local.dir") + File.separator
198 + "dynamic" + File.separator + "jars" + File.separator;
199 }
200
201 private void deleteClass(String className) throws Exception {
202 String jarFileName = className + ".jar";
203 File file = new File(TEST_UTIL.getDataTestDir().toString(), jarFileName);
204 file.deleteOnExit();
205
206 file = new File(conf.get("hbase.dynamic.jars.dir"), jarFileName);
207 file.deleteOnExit();
208
209 file = new File(localDirPath(), jarFileName);
210 file.deleteOnExit();
211 }
212
213 @org.junit.Rule
214 public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
215 new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
216 }