org.drools.android.MapBackedClassLoader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of drools-android Show documentation
Show all versions of drools-android Show documentation
Integration code that enables Drools to run on the Android platform
/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* 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 org.drools.android;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.Map;
public class MapBackedClassLoader extends MultiDexClassLoader {
private static final long serialVersionUID = 510l;
private static final ProtectionDomain PROTECTION_DOMAIN;
private Map store;
static {
PROTECTION_DOMAIN = (ProtectionDomain) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return MapBackedClassLoader.class.getProtectionDomain();
}
});
}
public MapBackedClassLoader(final ClassLoader parentClassLoader) {
this(parentClassLoader, new HashMap());
}
public MapBackedClassLoader(final ClassLoader parentClassLoader,
final Map store) {
super(parentClassLoader);
this.store = store;
}
public void addResource(String className,
byte[] bytes) {
addClass(className,
bytes);
}
private String convertResourcePathToClassName(final String pName) {
return pName.replaceAll(".java$|.class$",
"").replace('/',
'.');
}
public void addClass(final String className,
byte[] bytes) {
synchronized (this.store) {
this.store.put(convertResourcePathToClassName(className),
bytes);
}
}
public Class fastFindClass(final String name) {
final Class clazz = findLoadedClass(name);
if (clazz == null) {
byte[] clazzBytes;
synchronized (this.store) {
clazzBytes = this.store.get(name);
}
if (clazzBytes != null) {
return defineClass(name, clazzBytes);
}
}
return clazz;
}
/**
* Javadocs recommend that this method not be overloaded. We overload this so that we can prioritise the fastFindClass
* over method calls to parent.loadClass(name, false); and c = findBootstrapClass0(name); which the default implementation
* would first - hence why we call it "fastFindClass" instead of standard findClass, this indicates that we give it a
* higher priority than normal.
*/
public synchronized Class loadClass(final String name,
final boolean resolve) throws ClassNotFoundException {
Class clazz = fastFindClass(name);
if (clazz == null) {
final ClassLoader parent = getParent();
if (parent != null) {
clazz = Class.forName(name,
true,
parent);
}
}
if (resolve) {
resolveClass(clazz);
}
return clazz;
}
protected Class findClass(final String name) throws ClassNotFoundException {
return fastFindClass(name);
}
public InputStream getResourceAsStream(final String name) {
byte[] bytes = null;
synchronized (this.store) {
bytes = this.store.get(convertResourcePathToClassName(name));
}
if (bytes != null) {
return new ByteArrayInputStream(bytes);
} else {
InputStream input = this.getParent().getResourceAsStream(name);
if (input == null) {
input = super.getResourceAsStream(name);
}
return input;
}
}
public Map getStore() {
return this.store;
}
}