001: package org.drools.rule;
002:
003: import java.io.ByteArrayInputStream;
004: import java.io.InputStream;
005: import java.io.Serializable;
006: import java.security.AccessController;
007: import java.security.PrivilegedAction;
008: import java.security.ProtectionDomain;
009: import java.util.HashMap;
010: import java.util.Map;
011:
012: public class MapBackedClassLoader extends ClassLoader implements
013: DroolsClassLoader, Serializable {
014:
015: private static final long serialVersionUID = 400L;
016:
017: private static final ProtectionDomain PROTECTION_DOMAIN;
018:
019: private Map store;
020:
021: static {
022: PROTECTION_DOMAIN = (ProtectionDomain) AccessController
023: .doPrivileged(new PrivilegedAction() {
024: public Object run() {
025: return MapBackedClassLoader.class
026: .getProtectionDomain();
027: }
028: });
029: }
030:
031: public MapBackedClassLoader(final ClassLoader parentClassLoader) {
032: super (parentClassLoader);
033: this .store = new HashMap();
034: }
035:
036: public void addResource(String className, byte[] bytes) {
037: addClass(className, bytes);
038: }
039:
040: private String convertResourcePathToClassName(final String pName) {
041: return pName.replaceAll(".java$|.class$", "").replace('/', '.');
042: }
043:
044: public void addClass(final String className, byte[] bytes) {
045:
046: this .store
047: .put(convertResourcePathToClassName(className), bytes);
048: }
049:
050: public Class fastFindClass(final String name) {
051: final Class clazz = findLoadedClass(name);
052:
053: if (clazz == null) {
054: final byte[] clazzBytes = (byte[]) this .store.get(name);
055: if (clazzBytes != null) {
056: return defineClass(name, clazzBytes, 0,
057: clazzBytes.length, PROTECTION_DOMAIN);
058: }
059: }
060: return clazz;
061: }
062:
063: /**
064: * Javadocs recommend that this method not be overloaded. We overload this so that we can prioritise the fastFindClass
065: * over method calls to parent.loadClass(name, false); and c = findBootstrapClass0(name); which the default implementation
066: * would first - hence why we call it "fastFindClass" instead of standard findClass, this indicates that we give it a
067: * higher priority than normal.
068: *
069: */
070: protected synchronized Class loadClass(final String name,
071: final boolean resolve) throws ClassNotFoundException {
072: Class clazz = fastFindClass(name);
073:
074: if (clazz == null) {
075: final ClassLoader parent = getParent();
076: if (parent != null) {
077: clazz = parent.loadClass(name);
078: } else {
079: throw new ClassNotFoundException(name);
080: }
081: }
082:
083: if (resolve) {
084: resolveClass(clazz);
085: }
086:
087: return clazz;
088: }
089:
090: protected Class findClass(final String name)
091: throws ClassNotFoundException {
092: final Class clazz = fastFindClass(name);
093: if (clazz == null) {
094: throw new ClassNotFoundException(name);
095: }
096: return clazz;
097: }
098:
099: public InputStream getResourceAsStream(final String name) {
100: final byte[] bytes = (byte[]) this .store.get(name);
101: if (bytes != null) {
102: return new ByteArrayInputStream(bytes);
103: } else {
104: InputStream input = this.getParent().getResourceAsStream(
105: name);
106: if (input == null) {
107: input = super.getResourceAsStream(name);
108: }
109: return input;
110: }
111: }
112:
113: }
|