return new CloseableClassLoader(new DirectoryClassLoader(unpackDir, parentClassLoader, "lib"), new Closeable() { @Override public void close() throws IOException {
private static URL[] getClassPathURLs(File dir, @Nullable String extraClassPath, Set<String> libDirs) { try { List<URL> urls = Lists.newArrayList(dir.toURI().toURL()); addJarURLs(dir, urls); for (String libDir : libDirs) { addJarURLs(new File(dir, libDir), urls); } if (extraClassPath != null) { for (String path : Splitter.on(File.pathSeparatorChar).omitEmptyStrings().split(extraClassPath)) { String wildcardSuffix = File.separator + "*"; if (path.endsWith(wildcardSuffix)) { addJarURLs(new File(path.substring(0, path.length() - wildcardSuffix.length())), urls); } else { urls.add(new File(path).toURI().toURL()); } } } return urls.toArray(new URL[urls.size()]); } catch (MalformedURLException e) { // Should never happen LOG.error("Error in adding jar URLs to classPathUrls", e); throw Throwables.propagate(e); } }
public DirectoryClassLoader(File dir, @Nullable String extraClassPath, ClassLoader parent, Iterable<String> libDirs) { super(getClassPathURLs(dir, extraClassPath, ImmutableSet.copyOf(libDirs)), parent); // Try to load the Manifest from the unpacked directory Manifest manifest = null; try { try ( InputStream input = new FileInputStream(new File(dir, JarFile.MANIFEST_NAME.replace('/', File.separatorChar))) ) { manifest = new Manifest(input); } } catch (IOException e) { // Ignore, since it's possible that there is no MANIFEST LOG.trace("No Manifest file under {}", dir, e); } this.manifest = manifest; }
return new CloseableClassLoader(new DirectoryClassLoader(unpackDir, parentClassLoader, "lib"), new Closeable() { @Override public void close() throws IOException {
public DirectoryClassLoader(File dir, @Nullable String extraClassPath, ClassLoader parent, Iterable<String> libDirs) { super(getClassPathURLs(dir, extraClassPath, ImmutableSet.copyOf(libDirs)), parent); // Try to load the Manifest from the unpacked directory Manifest manifest = null; try { try ( InputStream input = new FileInputStream(new File(dir, JarFile.MANIFEST_NAME.replace('/', File.separatorChar))) ) { manifest = new Manifest(input); } } catch (IOException e) { // Ignore, since it's possible that there is no MANIFEST LOG.trace("No Manifest file under {}", dir, e); } this.manifest = manifest; }
private static URL[] getClassPathURLs(File dir, @Nullable String extraClassPath, Set<String> libDirs) { try { List<URL> urls = Lists.newArrayList(dir.toURI().toURL()); addJarURLs(dir, urls); for (String libDir : libDirs) { addJarURLs(new File(dir, libDir), urls); } if (extraClassPath != null) { for (String path : Splitter.on(File.pathSeparatorChar).omitEmptyStrings().split(extraClassPath)) { String wildcardSuffix = File.separator + "*"; if (path.endsWith(wildcardSuffix)) { addJarURLs(new File(path.substring(0, path.length() - wildcardSuffix.length())), urls); } else { urls.add(new File(path).toURI().toURL()); } } } return urls.toArray(new URL[urls.size()]); } catch (MalformedURLException e) { // Should never happen LOG.error("Error in adding jar URLs to classPathUrls", e); throw Throwables.propagate(e); } }
@Override public CloseableClassLoader createClassLoader(@Nullable String namespace, ArtifactInfo artifactInfo, @Nullable ClassLoader parentClassLoader) throws IOException { File unpackedDir = DirUtils.createTempDir(tmpDir); BundleJarUtil.unJar(getArtifactLocation(artifactInfo, namespace), unpackedDir); DirectoryClassLoader directoryClassLoader = new DirectoryClassLoader(unpackedDir, parentClassLoader == null ? bootstrapClassLoader : parentClassLoader, "lib"); return new CloseableClassLoader(directoryClassLoader, new ClassLoaderCleanup(directoryClassLoader, unpackedDir)); }
/** * Create a class loader with artifact jar unpacked contents and parent for this classloader is the supplied * parentClassLoader, if that parent classloader is null, bootstrap classloader is used as parent. * This is a closeable classloader, caller should call close when he is done using it, during close directory * cleanup will be performed. * * @param artifactInfo artifact info whose artifact will be unpacked to create classloader * @param parentClassLoader optional parent classloader, if null bootstrap classloader will be used * @return CloseableClassLoader call close on this CloseableClassLoader for cleanup * @throws IOException if artifact is not found or there were any error while getting artifact */ @Override public CloseableClassLoader createClassLoader(ArtifactInfo artifactInfo, @Nullable ClassLoader parentClassLoader) throws IOException { File unpackedDir = DirUtils.createTempDir(tmpDir); BundleJarUtil.unJar(getArtifactLocation(artifactInfo), unpackedDir); DirectoryClassLoader directoryClassLoader = new DirectoryClassLoader(unpackedDir, parentClassLoader == null ? bootstrapClassLoader : parentClassLoader, "lib"); return new CloseableClassLoader(directoryClassLoader, new ClassLoaderCleanup(directoryClassLoader, unpackedDir)); }
cl = new DirectoryClassLoader(unpackedLocation, cConf.get(Constants.AppFabric.PROGRAM_EXTRA_CLASSPATH), FilterClassLoader.create(getClass().getClassLoader()), "lib");
cl = new DirectoryClassLoader(unpackedLocation, cConf.get(Constants.AppFabric.PROGRAM_EXTRA_CLASSPATH), FilterClassLoader.create(getClass().getClassLoader()), "lib");
@Test public void testExtraClassPath() throws IOException, ClassNotFoundException { File tmpDir = TMP_FOLDER.newFolder(); // Create two jars, one with guava, one with gson ApplicationBundler bundler = new ApplicationBundler(new ClassAcceptor()); Location guavaJar = Locations.toLocation(new File(tmpDir, "guava.jar")); bundler.createBundle(guavaJar, ImmutableList.class); Location gsonJar = Locations.toLocation(new File(tmpDir, "gson.jar")); bundler.createBundle(gsonJar, Gson.class); // Unpack them File guavaDir = BundleJarUtil.unJar(guavaJar, TMP_FOLDER.newFolder()); File gsonDir = BundleJarUtil.unJar(gsonJar, TMP_FOLDER.newFolder()); // Create a DirectoryClassLoader using guava dir as the main directory, with the gson dir in the extra classpath String extraClassPath = gsonDir.getAbsolutePath() + File.pathSeparatorChar + gsonDir.getAbsolutePath() + "/lib/*"; ClassLoader cl = new DirectoryClassLoader(guavaDir, extraClassPath, null, Arrays.asList("lib")); // Should be able to load both guava and gson class from the class loader cl.loadClass(ImmutableList.class.getName()); cl.loadClass(Gson.class.getName()); }
@Test public void testWeakReferenceClassLoader() throws Exception { // Creates a jar that has Application class in it. Location jar = AppJarHelper.createDeploymentJar(new LocalLocationFactory(TMP_FOLDER.newFolder()), ClassLoaderTest.class); // Create a class loader that load from that jar. File unpackDir = TMP_FOLDER.newFolder(); BundleJarUtil.unJar(jar, unpackDir); ClassLoader cl = new DirectoryClassLoader(unpackDir, null, "lib"); // Wrap it with the WeakReference ClassLoader ClassLoader classLoader = new WeakReferenceDelegatorClassLoader(cl); // Load class from the wrapped ClassLoader, should succeed and should be loaded by the delegating ClassLoader. Class<?> cls = classLoader.loadClass(ClassLoaderTest.class.getName()); Assert.assertSame(cl, cls.getClassLoader()); Assert.assertSame(cl, Delegators.getDelegate(classLoader, ClassLoader.class)); // There is no good way to test the GC of the weak reference referent since it depends on GC. }