/** * Constructor. The first time an RJavaClassLoader is created, it is cached as the primary loader. * * @param path path of the rJava package * @param libpath lib sub directory of the rJava package */ public RJavaClassLoader(String path, String libpath) { super(new URL[] {}); // respect rJava.debug level String rjd = System.getProperty("rJava.debug"); if (rjd != null && rjd.length() > 0 && !rjd.equals("0")) verbose = true; if (verbose) System.out.println("RJavaClassLoader(\"" + path + "\",\"" + libpath + "\")"); if (primaryLoader == null) { primaryLoader = this; if (verbose) System.out.println(" - primary loader"); } else { if (verbose) System.out.println(" - NOT primrary (this=" + this + ", primary=" + primaryLoader + ")"); } libMap = new HashMap /*<String,UnixFile>*/(); classPath = new Vector /*<UnixFile>*/(); classPath.add(new UnixDirectory(path + "/java")); rJavaPath = path; rJavaLibPath = libpath; /* load the rJava library */ UnixFile so = new UnixFile(rJavaLibPath + "/rJava.so"); if (!so.exists()) so = new UnixFile(rJavaLibPath + "/rJava.dll"); if (so.exists()) libMap.put("rJava", so); /* load the jri library */ UnixFile jri = new UnixFile(path + "/jri/libjri.so"); String rarch = System.getProperty("r.arch"); if (rarch != null && rarch.length() > 0) { UnixFile af = new UnixFile(path + "/jri" + rarch + "/libjri.so"); if (af.exists()) jri = af; else { af = new UnixFile(path + "/jri" + rarch + "/jri.dll"); if (af.exists()) jri = af; } } if (!jri.exists()) jri = new UnixFile(path + "/jri/libjri.jnilib"); if (!jri.exists()) jri = new UnixFile(path + "/jri/jri.dll"); if (jri.exists()) { libMap.put("jri", jri); if (verbose) System.out.println(" - registered JRI: " + jri); } /* if we are the primary loader, make us the context loader so projects that rely on the context loader pick us */ if (primaryLoader == this) Thread.currentThread().setContextClassLoader(this); if (verbose) { System.out.println("RJavaClassLoader initialized.\n\nRegistered libraries:"); for (Iterator entries = libMap.keySet().iterator(); entries.hasNext(); ) { Object key = entries.next(); System.out.println(" " + key + ": '" + libMap.get(key) + "'"); } System.out.println("\nRegistered class paths:"); for (Enumeration e = classPath.elements(); e.hasMoreElements(); ) System.out.println(" '" + e.nextElement() + "'"); System.out.println("\n-- end of class loader report --"); } }
// {{{ findLibrary protected String findLibrary(String name) { if (verbose) System.out.println("RJavaClassLoader.findLibrary(\"" + name + "\")"); // if (name.equals("rJava")) // return rJavaLibPath+"/"+name+".so"; UnixFile u = (UnixFile) libMap.get(name); String s = null; if (u != null && u.exists()) s = u.getPath(); if (verbose) System.out.println(" - mapping to " + ((s == null) ? "<none>" : s)); return s; }
// {{{ findResource public URL findResource(String name) { if (verbose) System.out.println("RJavaClassLoader: findResource('" + name + "')"); // {{{ use the standard way if (useSystem) { try { URL u = super.findResource(name); if (u != null) { if (verbose) System.out.println("RJavaClassLoader: found resource in " + u + " using URL loader."); return u; } } catch (Exception fre) { } } // }}} // {{{ iterate through the classpath if (verbose) System.out.println(" - resource not found with URL loader, trying alternative"); Enumeration /*<UnixFile>*/ e = classPath.elements(); while (e.hasMoreElements()) { UnixFile cp = (UnixFile) e.nextElement(); try { /* is a file - assume it is a jar file */ if (cp instanceof UnixJarFile) { URL u = ((UnixJarFile) cp).getResource(name); if (u != null) { if (verbose) System.out.println(" - found in a JAR file, URL " + u); return u; } } else if (cp instanceof UnixDirectory) { UnixFile res_f = new UnixFile(cp.getPath() + "/" + name); if (res_f.isFile()) { if (verbose) System.out.println(" - find as a file: " + res_f); return res_f.toURL(); } } } catch (Exception iox) { } } // }}} return null; }
/* @Override */ public void update() { try { if (zfile != null) { zfile.close(); } zfile = new ZipFile(this); } catch (Exception tryCloseX) { } /* time stamp */ super.update(); }
/** adds an entry to the class path */ public void addClassPath(String cp) { UnixFile f = new UnixFile(cp); // use the URLClassLoader if (useSystem) { try { addURL(f.toURL()); if (verbose) System.out.println("RJavaClassLoader: added '" + cp + "' to the URL class path loader"); // return; // we need to add it anyway so it appears in .jclassPath() } catch (Exception ufe) { } } UnixFile g = null; if (f.isFile() && (f.getName().endsWith(".jar") || f.getName().endsWith(".JAR"))) { g = new UnixJarFile(cp); if (verbose) System.out.println( "RJavaClassLoader: adding Java archive file '" + cp + "' to the internal class path"); } else if (f.isDirectory()) { g = new UnixDirectory(cp); if (verbose) System.out.println( "RJavaClassLoader: adding class directory '" + cp + "' to the internal class path"); } else if (verbose) System.err.println( f.exists() ? ("WARNING: the path '" + cp + "' is neither a directory nor a .jar file, it will NOT be added to the internal class path!") : ("WARNING: the path '" + cp + "' does NOT exist, it will NOT be added to the internal class path!")); if (g != null && !classPath.contains(g)) { // this is the real meat - add it to our internal list classPath.add(g); // this is just cosmetics - it doesn't really have any meaning System.setProperty( "java.class.path", System.getProperty("java.class.path") + File.pathSeparator + g.getPath()); } }
// {{{ findClass protected Class findClass(String name) throws ClassNotFoundException { Class cl = null; if (verbose) System.out.println("" + this + ".findClass(" + name + ")"); if ("RJavaClassLoader".equals(name)) return getClass(); // {{{ use the usual method of URLClassLoader if (useSystem) { try { cl = super.findClass(name); if (cl != null) { if (verbose) System.out.println("RJavaClassLoader: found class " + name + " using URL loader"); return cl; } } catch (Exception fnf) { if (verbose) System.out.println(" - URL loader did not find it: " + fnf); } } if (verbose) System.out.println("RJavaClassLoader.findClass(\"" + name + "\")"); // }}} // {{{ iterate through the elements of the class path InputStream ins = null; Exception defineException = null; Enumeration /*<UnixFile>*/ e = classPath.elements(); while (e.hasMoreElements()) { UnixFile cp = (UnixFile) e.nextElement(); if (verbose) System.out.println(" - trying class path \"" + cp + "\""); try { ins = null; /* a file - assume it is a jar file */ if (cp instanceof UnixJarFile) { ins = ((UnixJarFile) cp).getResourceAsStream(classNameToFile(name) + ".class"); if (verbose) System.out.println( " JAR file, can get '" + classNameToFile(name) + "'? " + ((ins == null) ? "NO" : "YES")); } else if (cp instanceof UnixDirectory) { UnixFile class_f = new UnixFile(cp.getPath() + "/" + classNameToFile(name) + ".class"); if (class_f.isFile()) { ins = new FileInputStream(class_f); } if (verbose) System.out.println( " Directory, can get '" + class_f + "'? " + ((ins == null) ? "NO" : "YES")); } /* some comments on the following : we could call ZipEntry.getSize in case of a jar file to find out the size of the byte[] directly also ByteBuffer seems more efficient, but the ByteBuffer class is java >= 1.4 and the defineClass method that uses the class is java >= 1.5 */ if (ins != null) { int al = 128 * 1024; byte fc[] = new byte[al]; int n = ins.read(fc); int rp = n; if (verbose) System.out.println(" loading class file, initial n = " + n); while (n > 0) { if (rp == al) { int nexa = al * 2; if (nexa < 512 * 1024) nexa = 512 * 1024; byte la[] = new byte[nexa]; System.arraycopy(fc, 0, la, 0, al); fc = la; al = nexa; } n = ins.read(fc, rp, fc.length - rp); if (verbose) System.out.println(" next n = " + n + " (rp=" + rp + ", al=" + al + ")"); if (n > 0) rp += n; } ins.close(); n = rp; if (verbose) System.out.println("RJavaClassLoader: loaded class " + name + ", " + n + " bytes"); try { cl = defineClass(name, fc, 0, n); } catch (Exception dce) { // we want to save this one so we can pass it on defineException = dce; break; } if (verbose) System.out.println(" defineClass('" + name + "') returned " + cl); // System.out.println(" - class = "+cl); return cl; } } catch (Exception ex) { // System.out.println(" * won't work: "+ex.getMessage()); } } // }}} if (defineException != null) // we bailed out on class interpretation, re-throw it throw (new ClassNotFoundException( "Class not found - candidate class binary found but could not be loaded", defineException)); // giving up if (verbose) System.out.println(" >> ClassNotFoundException "); if (cl == null) { throw (new ClassNotFoundException()); } return cl; }