/** * Convenience class to construct a classloader for a program from an unpacked jar directory. * Adds <unpackedJarDir>/{.,*.jar,lib/*.jar} to the {@link java.net.URLClassLoader}. * * @param unpackedJarDir Directory of the unpacked jar to be used in the classpath. * @param parentDelegate Parent classloader. */ public ProgramClassLoader(File unpackedJarDir, ClassLoader parentDelegate) { super(getClassPathUrls(unpackedJarDir), parentDelegate); }
private synchronized void expandIfNeeded() { if (expanded) { return; } Preconditions.checkState(expandFolder != null, "Directory for jar expansion is not defined."); try { BundleJarUtil.unpackProgramJar(programJarLocation, expandFolder); expanded = true; } catch (IOException e) { throw Throwables.propagate(e); } } }
public static File unpackProgramJar(Location programJarLocation, File destinationFolder) throws IOException { Preconditions.checkArgument(programJarLocation != null); Preconditions.checkArgument(programJarLocation.exists()); Preconditions.checkArgument(destinationFolder != null); Preconditions.checkArgument(destinationFolder.canWrite()); destinationFolder.mkdirs(); Preconditions.checkState(destinationFolder.exists()); unJar(new ZipInputStream(programJarLocation.getInputStream()), destinationFolder); return destinationFolder; }
/** * Creates a program instance. * * @param programJarLocation Location of the program jar file. * @param expandFolder Local directory for expanding the jar file into. If it is {@code null}, * the {@link #getClassLoader()} methods would throw exception. */ DefaultProgram(Location programJarLocation, @Nullable File expandFolder) throws IOException { this.programJarLocation = programJarLocation; this.expandFolder = expandFolder; this.processorType = ProgramType.FLOW; Manifest manifest = BundleJarUtil.getManifest(programJarLocation); if (manifest == null) { throw new IOException("Failed to load manifest in program jar from " + programJarLocation.toURI()); } mainClassName = getAttribute(manifest, ManifestFields.MAIN_CLASS); // Load the app spec from the jar file if no expand folder is provided. Otherwise do lazy loading after the jar // is expanded. String specPath = getAttribute(manifest, ManifestFields.SPEC_FILE); if (expandFolder == null) { specification = FlowSpecificationAdapter.create().fromJson( CharStreams.newReaderSupplier(BundleJarUtil.getEntry(programJarLocation, specPath), Charsets.UTF_8)); specFile = null; } else { specFile = new File(expandFolder, specPath); } }
private static URL[] getClassPathUrls(File unpackedJarDir) { List<URL> classPathUrls = new LinkedList<URL>(); try { classPathUrls.add(unpackedJarDir.toURI().toURL()); } catch (MalformedURLException e) { LOG.error("Error in adding unpackedJarDir to classPathUrls", e); } try { classPathUrls.addAll(getJarURLs(unpackedJarDir)); } catch (MalformedURLException e) { LOG.error("Error in adding jar URLs to classPathUrls", e); } try { classPathUrls.addAll(getJarURLs(new File(unpackedJarDir, "lib"))); } catch (MalformedURLException e) { LOG.error("Error in adding jar URLs to classPathUrls", e); } return classPathUrls.toArray(new URL[classPathUrls.size()]); }
public static ProgramClassLoader newProgramClassLoader(File unpackedJarDir, Iterable<String> apiResourceList) throws IOException { Predicate<String> predicate = Predicates.in(Sets.newHashSet(apiResourceList)); ClassLoader filterParent = Objects.firstNonNull(Thread.currentThread().getContextClassLoader(), ClassLoaders.class.getClassLoader()); return new ProgramClassLoader(unpackedJarDir, new FilterClassLoader(predicate, filterParent)); }
public Program createProgram(File jarPath, String classToLoad, File jarUnpackDir) throws Exception { expandJar(jarPath, jarUnpackDir); ProgramClassLoader classLoader = ClassLoaders.newProgramClassLoader(jarUnpackDir, ApiResourceListHolder.getResourceList()); Class<?> clz = classLoader.loadClass(classToLoad); if (!(clz.newInstance() instanceof Flow)) { throw new Exception("Expected Flow class"); } ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(classLoader); Location deployJar = jarForTestBase(clz); LOG.info("Deploy Jar location : {}", deployJar.toURI()); try { return Programs.create(deployJar, classLoader); } finally { Thread.currentThread().setContextClassLoader(contextClassLoader); } }