Skip to content

Instantly share code, notes, and snippets.

@LunNova
Created April 27, 2013 00:48
Show Gist options
  • Save LunNova/5471404 to your computer and use it in GitHub Desktop.
Save LunNova/5471404 to your computer and use it in GitHub Desktop.
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
if (invalidClasses.contains(name)) {
throw new ClassNotFoundException(name);
}
Class<?> cachedClass = cachedClasses.get(name);
if (cachedClass != null) {
return cachedClass;
}
for (String st : classLoaderExceptions) {
if (name.startsWith(st)) {
return parent.loadClass(name);
}
}
boolean transform = true;
for (String st : transformerExceptions) {
if (name.startsWith(st)) {
transform = false;
break;
}
}
byte[] basicClass = null;
@SuppressWarnings ("NonConstantStringShouldBeStringBuffer")
String path = name.replace('.', '/') + ".class";
if (name.indexOf('.') == -1) {
for (String res : RESERVED) {
if (name.toUpperCase(Locale.ENGLISH).startsWith(res)) {
path = '_' + path;
break;
}
}
}
CodeSource codeSource = null;
InputStream classStream = null;
Manifest mf = null;
CodeSigner[] signers = null;
try {
byte[] patchedData = getReplacementClassBytes(path);
boolean loaded = false;
if (patchedData == null) {
try {
Resource classResource = ucp.getResource(path, true);
if (classResource != null) {
if (DEBUG_CLASSLOADING) {
FMLRelaunchLog.finest("Loading class %s from resource %s", name, classResource.getCodeSourceURL().toString());
}
if (patchedData == null) {
ByteBuffer byteBuffer = classResource.getByteBuffer();
if (byteBuffer == null) {
basicClass = classResource.getBytes();
} else {
basicClass = new byte[byteBuffer.remaining()];
byteBuffer.get(basicClass);
}
}
mf = classResource.getManifest();
signers = classResource.getCodeSigners();
if (signers != null && signers.length != 0) {
codeSource = new CodeSource(classResource.getCodeSourceURL(), signers);
}
loaded = true;
}
} catch (Throwable t) {
if (!(t instanceof NoClassDefFoundError)) {
log(Level.WARNING, t, "Failed to use fast I/O to read class " + name + " from " + path);
}
}
}
if (!loaded) {
URL classURL = findResource(path);
if (classURL == null) {
if (DEBUG_CLASSLOADING) {
FMLRelaunchLog.finest("Failed to find class resource %s", path);
}
return null;
}
if (DEBUG_CLASSLOADING) {
FMLRelaunchLog.finest("Loading class %s from resource %s", name, classURL.toString());
}
classStream = classURL.openStream();
basicClass = readFully(classStream);
}
basicClass = patchedData == null ? basicClass : patchedData;
} catch (Throwable t) {
log(Level.SEVERE, t, "Exception loading class " + name);
return null;
} finally {
if (classStream != null) {
try {
classStream.close();
} catch (IOException ignored) {
}
}
}
try {
int lastDot = name.lastIndexOf('.');
String pkgname = lastDot == -1 ? "" : name.substring(0, lastDot);
Package pkg = getPackage(pkgname);
URLConnection urlConnection = null;
if (codeSource == null || pkg == null) {
if (mf != null && codeSource != null) {
if (pkg == null) {
if (lastDot > -1) {
pkg = definePackage(pkgname, mf, codeSource.getLocation());
}
} else {
if (pkg.isSealed() && !pkg.isSealed(codeSource.getLocation())) {
FMLRelaunchLog.severe("The jar file %s is trying to seal already secured path %s", codeSource.getLocation(), pkgname);
} else if (isSealed(pkgname, mf)) {
FMLRelaunchLog.severe("The jar file %s has a security seal for path %s, but that path is defined and not secure", codeSource.getLocation(), pkgname);
}
}
} else {
urlConnection = findCodeSourceConnectionFor(path);
if (urlConnection instanceof JarURLConnection) {
JarURLConnection jarUrlConn = (JarURLConnection) urlConnection;
JarFile jf = jarUrlConn.getJarFile();
if (jf != null && jf.getManifest() != null) {
mf = jf.getManifest();
JarEntry ent = jf.getJarEntry(path);
signers = ent.getCodeSigners();
if (pkg == null) {
if (lastDot > -1) {
pkg = definePackage(pkgname, mf, jarUrlConn.getJarFileURL());
}
} else {
if (pkg.isSealed() && !pkg.isSealed(jarUrlConn.getJarFileURL())) {
FMLRelaunchLog.severe("The jar file %s is trying to seal already secured path %s", jf.getName(), pkgname);
} else if (isSealed(pkgname, mf)) {
FMLRelaunchLog.severe("The jar file %s has a security seal for path %s, but that path is defined and not secure", jf.getName(), pkgname);
}
}
}
}
if (mf == null) {
if (pkg == null) {
if (lastDot > -1) {
pkg = definePackage(pkgname, null, null, null, null, null, null, null);
}
} else if (pkg.isSealed()) {
FMLRelaunchLog.severe("The URL %s is defining elements for sealed path %s", urlConnection.getURL(), pkgname);
}
}
}
if (pkg == null && lastDot > -1) {
log(Level.SEVERE, null, "No package defined for " + pkgname + " getting " + path);
}
}
if (codeSource == null && urlConnection != null) {
codeSource = new CodeSource(urlConnection.getURL(), signers);
}
byte[] transformedClass = transform ? runTransformers(name, basicClass) : basicClass;
Class<?> cl = defineClass(name, transformedClass, 0, transformedClass.length, codeSource);
if (cl.getPackage() != pkg) {
log(Level.SEVERE, null, "Package mismatch: got " + cl.getPackage() + ", expected " + pkg);
}
resolveClass(cl);
cachedClasses.put(name, cl);
return cl;
} catch (Throwable e) {
invalidClasses.add(name);
if (DEBUG_CLASSLOADING) {
FMLRelaunchLog.log(Level.FINEST, e, "Exception encountered attempting classloading of %s", name);
}
throw new ClassNotFoundException(name, e);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment