/* * Copyright (C) 2012 Sony Mobile Communications AB * * This file is part of ApkAnalyser. * * Licensed 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 analyser; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; import java.util.jar.JarFile; import java.util.zip.ZipEntry; public class ResourceJarClassLoader extends URLClassLoader { ClassLoader sibling; List<String> classpaths = new ArrayList<String>(); List<File> tempFiles = new ArrayList<File>(); boolean initiated = false; public ResourceJarClassLoader(URL[] urls, ClassLoader parent, ClassLoader sibling) { super(urls, parent); this.sibling = sibling; } public void addClasspath(String resourceClasspath) { classpaths.add(resourceClasspath); } public void arm() { initiate(); } @Override public InputStream getResourceAsStream(String resource) { InputStream is = null; is = super.getResourceAsStream(resource); if (is == null) { is = getParent().getResourceAsStream(resource); } if (is == null && sibling != null) { is = sibling.getResourceAsStream(resource); } return is; } @Override public URL getResource(String resource) { URL url = null; url = super.getResource(resource); if (url == null) { url = getParent().getResource(resource); } if (url == null && sibling != null) { url = sibling.getResource(resource); } return url; } @Override @SuppressWarnings("deprecation") public Class<?> findClass(String name) throws ClassNotFoundException { Class<?> c = null; try { c = super.findClass(name); } catch (NoClassDefFoundError ncdfe) { } catch (ClassNotFoundException cnfe) { } if (c == null) { byte[] b = loadClassData(name); if (b != null) { c = defineClass(b, 0, b.length); } } if (c == null) { try { c = getParent().loadClass(name); } catch (NoClassDefFoundError ncdfe) { } catch (ClassNotFoundException cnfe) { } } if (c == null && sibling != null) { try { c = sibling.loadClass(name); } catch (NoClassDefFoundError ncdfe) { } catch (ClassNotFoundException cnfe) { } } if (c == null) { throw new ClassNotFoundException(name); } return c; } byte[] loadClassData(String name) { initiate(); byte[] b = null; for (int i = 0; b == null && i < tempFiles.size(); i++) { File tmpf = tempFiles.get(i); b = loadClassDataFromJar(name, tmpf); } // per tempfile return b; } byte[] loadClassDataFromJar(String name, File tmpf) { byte[] b = null; JarFile jar = null; InputStream is = null; try { jar = new JarFile(tmpf); String entryName = name.replace('.', '/') + ".class"; ZipEntry entry = jar.getEntry(entryName); if (entry != null) { is = jar.getInputStream(entry); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int data; while ((data = is.read()) != -1) { baos.write(data); } b = baos.toByteArray(); } else { } } catch (IOException ignore) { } finally { if (is != null) { try { is.close(); } catch (IOException ignore) { } } if (jar != null) { try { jar.close(); } catch (IOException ignore) { } } } return b; } synchronized void initiate() { if (!initiated) { // create temporary lib files byte[] buf = new byte[1024]; for (int i = 0; i < classpaths.size(); i++) { String cp = classpaths.get(i); InputStream is = null; FileOutputStream fos = null; try { is = Thread.currentThread().getContextClassLoader().getResourceAsStream(cp); if (is != null) { int sepIx = cp.indexOf("/"); String fname = sepIx < 0 ? cp : cp.substring(sepIx); File f = new File("." + File.separator + fname); if (f.exists()) { f.delete(); } f.createNewFile(); f.deleteOnExit(); fos = new FileOutputStream(f); int len; while ((len = is.read(buf)) > 0) { fos.write(buf, 0, len); } fos.flush(); tempFiles.add(f); } else { //System.err.println("Warning: " + cp + " not found"); } } catch (Throwable t) { t.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException ignore) { } } if (fos != null) { try { fos.close(); } catch (IOException ignore) { } } } } // per classpath initiated = true; } } }