001/* 002 * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. 003 * Use is subject to license terms. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, are 006 * permitted provided that the following conditions are met: Redistributions of source code 007 * must retain the above copyright notice, this list of conditions and the following disclaimer. 008 * Redistributions in binary form must reproduce the above copyright notice, this list of 009 * conditions and the following disclaimer in the documentation and/or other materials 010 * provided with the distribution. Neither the name of the Sun Microsystems nor the names of 011 * is contributors may be used to endorse or promote products derived from this software 012 * without specific prior written permission. 013 014 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS 015 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 016 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 017 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 018 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 019 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 020 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 021 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 022 * POSSIBILITY OF SUCH DAMAGE. 023 */ 024 025/* 026 * MemoryClassLoader.java 027 * @author A. Sundararajan 028 */ 029 030package org.kepler.scriptengine.java; 031 032import java.io.File; 033import java.net.MalformedURLException; 034import java.net.URL; 035import java.net.URLClassLoader; 036import java.util.ArrayList; 037import java.util.List; 038import java.util.Map; 039import java.util.StringTokenizer; 040 041/** 042 * ClassLoader that loads .class bytes from memory. 043 */ 044public final class MemoryClassLoader extends URLClassLoader { 045 private Map<String, byte[]> classBytes; 046 047 public MemoryClassLoader(Map<String, byte[]> classBytes, 048 String classPath, ClassLoader parent) { 049 super(toURLs(classPath), parent); 050 this.classBytes = classBytes; 051 } 052 053 public MemoryClassLoader(Map<String, byte[]> classBytes, String classPath) { 054 this(classBytes, classPath, null); 055 } 056 057 public Class<?> load(String className) throws ClassNotFoundException { 058 return loadClass(className); 059 } 060 061 public Iterable<Class<?>> loadAll() throws ClassNotFoundException { 062 List<Class<?>> classes = new ArrayList<Class<?>>(classBytes.size()); 063 for (String name : classBytes.keySet()) { 064 classes.add(loadClass(name)); 065 } 066 return classes; 067 } 068 069 @Override 070 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 071 072 byte[] buf = classBytes.get(name); 073 if (buf != null) { 074 //System.out.println("found defn for " + name); 075 076 // clear the bytes in map -- we don't need it anymore 077 classBytes.put(name, null); 078 Class<?> clazz = defineClass(name, buf, 0, buf.length); 079 if(resolve) { 080 resolveClass(clazz); 081 } 082 return clazz; 083 } 084 return super.loadClass(name, resolve); 085 } 086 087 /* NOTE: this does not allow us to override existing classes. Instead we 088 * override the loadClass(String, boolean) method. 089 */ 090 /* 091 @Override 092 protected Class<?> findClass(String className) throws ClassNotFoundException { 093 byte[] buf = classBytes.get(className); 094 if (buf != null) { 095 // clear the bytes in map -- we don't need it anymore 096 classBytes.put(className, null); 097 return defineClass(className, buf, 0, buf.length); 098 } else { 099 return super.findClass(className); 100 } 101 } 102 */ 103 104 private static URL[] toURLs(String classPath) { 105 if (classPath == null) { 106 return new URL[0]; 107 } 108 109 List<URL> list = new ArrayList<URL>(); 110 StringTokenizer st = new StringTokenizer(classPath, File.pathSeparator); 111 while (st.hasMoreTokens()) { 112 String token = st.nextToken(); 113 File file = new File(token); 114 if (file.exists()) { 115 try { 116 list.add(file.toURI().toURL()); 117 } catch (MalformedURLException mue) {} 118 } else { 119 try { 120 list.add(new URL(token)); 121 } catch (MalformedURLException mue) {} 122 } 123 } 124 URL[] res = new URL[list.size()]; 125 list.toArray(res); 126 return res; 127 } 128}