/************************************************************************** * Parts copyright (c) 2001 by Punch Telematix. All rights reserved. * * Parts copyright (c) 2005, 2006, 2008, 2009 by /k/ Embedded Java * * Solutions. All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * 1. Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * 3. Neither the name of Punch Telematix or of /k/ Embedded Java Solutions* * nor the names of other contributors may be used to endorse or promote* * products derived from this software without specific prior written * * permission. * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * * IN NO EVENT SHALL PUNCH TELEMATIX, /K/ EMBEDDED JAVA SOLUTIONS OR OTHER * * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ package wonka.vm; import java.io.File; import java.io.InputStream; import java.io.IOException; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.net.MalformedURLException; import java.net.URL; import java.security.AllPermission; import java.security.PermissionCollection; import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Enumeration; import java.util.Vector; import java.util.jar.JarFile; import java.util.jar.JarEntry; /** The system class loader is a singleton. ** It searches for class and resource files in the system class path, ** e.g. fsroot/system. */ public final class SystemClassLoader extends ClassLoader { /** ** The bootstrap classpath. Each element of the array contains one of ** the following: ** - the String bootstrap_zipfile_path, representing the bootstrap zipfile; ** - a File, which must be a directory; ** - a JarFile. */ private static Object[] bootclasspath; /** ** The path to the bootstrap zipfile. For this file we don't create a ** JarFile object, we use the native bootstrap loader instead. */ private static String bootstrap_zipfile_path; /** ** The one and only instance of SystemClassLoader. */ private static SystemClassLoader theSystemClassLoader; /** ** A PermissionCollection which contains AllPermission. */ /** ** The unique instance which represents the the System domain. */ private static ProtectionDomain systemProtectionDomain; /** ** Set 'scl' as the system class loader. May only be called once! */ private static native void setSystemClassLoader(SystemClassLoader scl); /** ** Get the identity of the system class loader. ** The instance is created if it does not already exist. ** The caller must have RuntimePermission "getClassLoader". ** (In fact normally this method should only be called by ** java.lang.ClassLoader). ** ** While creating the SystemClassLoader singleton we also create ** the systemProtectionDomain. */ public synchronized static SystemClassLoader getInstance() { if (theSystemClassLoader == null) { PermissionCollection theAllPermission; if (wonka.vm.SecurityConfiguration.ENABLE_SECURITY_CHECKS) { theAllPermission = new wonka.security.DefaultPermissionCollection(); theAllPermission.add(new AllPermission()); systemProtectionDomain = new ProtectionDomain(null, theAllPermission); } theSystemClassLoader = new SystemClassLoader(); setSystemClassLoader(theSystemClassLoader); } else { if (wonka.vm.SecurityConfiguration.ENABLE_SECURITY_CHECKS) { SecurityManager sm = System.getSecurityManager(); if(sm!=null) { sm.checkPermission(new RuntimePermission("getClassLoader")); } } } return theSystemClassLoader; } /** ** A private constructor, so that only getInstance() can create an instance. ** Its parent is the bootstrap class loader, represented by `null'. ** ** We parse the bootclasspath into its component jarfiles or directories, ** and put them in an array of Object (as JarFile and File respectively). */ private SystemClassLoader() { super((ClassLoader)null); ArrayList list = new ArrayList(); String bcp = getBootclasspath(); Etc.woempa(9, "bcp = " + bcp); try { // just to prevent a bootstrapping problem Class.forName("java.util.jar.JarFile"); new ClassCastException(); } catch (ClassNotFoundException e) { e.printStackTrace(); } while (true) { int colon = bcp.indexOf(':'); String s = colon < 0 ? bcp : bcp.substring(0, colon); if (s.endsWith("/")) { File f = new File(s); if (f.isDirectory()) { list.add(f); } } else { try { JarFile jf = new JarFile(s, false); if (bootstrap_zipfile_path == null) { bootstrap_zipfile_path = s; } list.add(jf); } catch (IOException ioe) { // Etc.woempa(9, "SystemClassLoader/<init>: unable to create JarFile" + "(" + s + ") : " + ioe); } } if (colon < 0) { break; } bcp = bcp.substring(colon + 1); } bootclasspath = list.toArray(); } /** ** Extract one file from the bootstrap zipfile, as an array of bytes. */ protected native byte[] getBootstrapFile(String filename); /** **Find the class with a given name, by searching bootclasspath. */ protected Class findClass(String dotname) throws ClassNotFoundException { String filename = dotname.replace('.','/') + ".class"; byte[] bytes = null; InputStream in = null; for (int i = 0; i < bootclasspath.length; ++i) { Object bootclasspath_entry = bootclasspath[i]; //Etc.woempa(9, "Checking bootclasspath[" + i + "] = " + bootclasspath_entry); if (bootclasspath_entry == bootstrap_zipfile_path) { bytes = getBootstrapFile(filename); } else { try { JarFile jf = (JarFile)bootclasspath_entry; try { JarEntry je = jf.getJarEntry(filename); if (je != null){ int length = (int)je.getSize(); in = jf.getInputStream(je); //Etc.woempa(7, "System Class Loader: findClass("+dotname+"): found " + filename + " in " + jf + ", length = " + length); bytes = new byte[length]; length = in.read(bytes); } else { //Etc.woempa(7, "System Class Loader: findClass("+dotname+"): failed to find file " + filename + " in " + jf); } } catch (IOException e){ e.printStackTrace(); } } catch (ClassCastException cce) { File f = new File(bootclasspath_entry + filename); if (f.isFile()) { try { int length = (int)f.length(); in = new FileInputStream(f); //Etc.woempa(7, "System Class Loader: findClass("+dotname+"): found file " + f + ", length = " + length); bytes = new byte[length]; length = in.read(bytes); } catch (FileNotFoundException fnfe) { //Etc.woempa(7, "System Class Loader: findClass("+dotname+"): failed top find file " + f); } catch(IOException ioe) { ioe.printStackTrace(); } } } } if (bytes != null) { int j = filename.lastIndexOf('/'); if(j > 0){ String packagename = dotname.substring(0,j); if (getPackage(packagename) == null) { definePackage(packagename,"","","","","","",null); } } return defineClass(dotname, bytes, 0, bytes.length, systemProtectionDomain); } } throw new ClassNotFoundException("SystemClassLoader couldn't find "+dotname); } /** ** Private method to see if a resource is present in a particular element ** of bootclasspath. */ private URL tryResource(String name, Object bcpelem) throws MalformedURLException { URL url = null; if (bcpelem == bootstrap_zipfile_path && getBootstrapFile(name) != null) { url = new URL("jar:file:" + ((JarFile)bcpelem).getName() + "!/"+name); } else { try { JarFile jf = (JarFile)bcpelem; JarEntry je = jf.getJarEntry(name); if (je != null) { url = new URL("jar:file:" + jf.getName() + "!/"+name); } } catch (ClassCastException cce) { File f = new File((File)bcpelem, name); if (f.isFile()) { url = new URL("file:" + f); } } } return url; } /** ** Find the (first) resource with a given name, by searching bootclasspath. ** If the name is absolute or fsroot-relative, search the filesystem directly. */ protected URL findResource(String name) { URL url = null; try { if (name.startsWith("/") || name.startsWith("{}/")) { File f = new File(name); if (f.isFile()) { return new URL("file:"+f); } } for (int i = 0; i < bootclasspath.length; ++i) { url = tryResource(name, bootclasspath[i]); if (url != null) { break; } } } catch (MalformedURLException e) { //e.printStackTrace(); } return url; } public InputStream getResourceAsStream(String name){ for (int i = 0; i < bootclasspath.length; ++i) { if (bootclasspath[i] == bootstrap_zipfile_path) { byte[] bytes = getBootstrapFile(name); if (bytes != null) { return new java.io.ByteArrayInputStream(bytes); } } try { JarFile jf = (JarFile)bootclasspath[i]; try { JarEntry je = jf.getJarEntry(name); if (je != null){ return jf.getInputStream(je); } } catch (IOException e){} } catch (ClassCastException cce) { // if it's not a jarfile it must be a directory File f = new File((File)bootclasspath[i], name); if (f.isFile()) { try { return new FileInputStream(f); } catch (FileNotFoundException fnfe) {} } } } return null; } /** ** Find all resources with a given name, by searching bootclasspath. */ protected Enumeration findResources (String name) throws IOException { URL url = null; Vector v = new Vector(); for (int i = 0; i < bootclasspath.length; ++i) { url = tryResource(name, bootclasspath[i]); if (url != null) { v.addElement(url);; } } return v.elements(); } protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { Class loaded = findLoadedClass(name); if (loaded == null) { loaded = findClass(name); } if (resolve) { try { resolveClass(loaded); } catch (NullPointerException e) {} } return loaded; } public String toString() { return ("System Class Loader"); } private static native String getBootclasspath(); /** ** Enter the standard packages into the `packages' hashtable. ** TODO: get this info from wre.jar or our defined classes. */ private void defineStandardPackages() { definePackage("com.acunia.device","","","","","","",null); definePackage("com.acunia.device.uart","","","","","","",null); definePackage("com.acunia.device.serial","","","","","","",null); definePackage("wonka.resource","","","","","","",null); definePackage("wonka.security","","","","","","",null); definePackage("java.lang","","","","","","",null); definePackage("java.lang.ref","","","","","","",null); definePackage("java.lang.reflect","","","","","","",null); definePackage("java.io","","","","","","",null); definePackage("java.util","","","","","","",null); definePackage("java.util.jar","","","","","","",null); definePackage("java.util.zip","","","","","","",null); definePackage("java.net","","","","","","",null); definePackage("java.awt.event","","","","","","",null); definePackage("java.awt","","","","","","",null); definePackage("java.security","","","","","","",null); definePackage("java.security.cert","","","","","","",null); definePackage("java.math","","","","","","",null); definePackage("java.text","","","","","","",null); definePackage("java.rmi","","","","","","",null); definePackage("javax.comm","","","","","","",null); definePackage("wonka.vm","","","","","","",null); } /** Get a list of packages defined by the bootstrap class loader. */ protected Package[] getPackages() { synchronized (this) { if (packages.size() == 0) { defineStandardPackages(); } } Enumeration ownpackages = packages.keys(); Package[] package_array = new Package[packages.size()]; int i = 0; while(ownpackages.hasMoreElements()) { package_array[i++] = (Package)ownpackages.nextElement(); } return package_array; } /** Find a Package defined by the system or bootstrap class loader. */ protected Package getPackage(String pkgname) { synchronized (this) { if (packages.size() == 0) { defineStandardPackages(); } } return (Package)packages.get(pkgname); } }