package com.snowcattle.game.common.loader;
import com.snowcattle.game.common.constant.Loggers;
import org.slf4j.Logger;
import java.io.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class FileClassLoader extends ClassLoader {
public static final Logger logger = Loggers.serverLogger;
private Hashtable<String, Class> loadedClasses;
private File rootPath;
private HashMap<String, byte[]> classFiles;
public FileClassLoader(File root) throws Exception {
classFiles = new HashMap<String, byte[]>();
loadedClasses = new Hashtable<String, Class>();
if (root.isDirectory()) {
rootPath = root;
} else{
loadJarContent(root);
}
}
public void initJarPath(JarFile root) throws Exception {
rootPath = null;
loadJarContent(root);
}
public void initClassPath(File root, String classString) throws Exception {
if(root.getName().endsWith(".class")){
//class
byte[] classData = loadFileData(root);
classFiles.put(classString, classData);
}
}
private void loadJarContent(JarFile jf) throws Exception {
Enumeration<JarEntry> ee = jf.entries();
while (ee.hasMoreElements()) {
JarEntry je = ee.nextElement();
if (je.getName().endsWith(".class")) {
String className = je.getName().substring(0, je.getName().length() - 6);
className = className.replace('/', '.');
InputStream is = jf.getInputStream(je);
byte[] classData = getBytesFromInput(is);
is.close();
logger.info("jar load Name()" + jf.getName() + "class" + className);
classFiles.put(className, classData);
}
}
jf.close();
}
private void loadJarContent(File f) throws Exception {
JarFile jf = new JarFile(f);
loadJarContent(jf);
}
private static byte[] getBytesFromInput(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int rd = 0;
int len = 0;
byte[] buf = new byte[64];
while((rd = in.read(buf)) != -1){
len += rd;
out.write(buf, 0, rd);
}
byte[] rt = out.toByteArray();
out.close();
return rt;
}
@Override
public synchronized Class loadClass(String className, boolean resolve) throws ClassNotFoundException {
Class newClass;
byte[] classData;
newClass = loadedClasses.get(className);
if (newClass != null) {
if (resolve) {
resolveClass(newClass);
}
return newClass;
}
try {
newClass = findSystemClass(className);
if(newClass != null){
return newClass;
}
} catch (ClassNotFoundException e) {
throw new ClassNotFoundException(className);
}
try {
classData = getClassData(className);
if(classData != null){
newClass = defineClass(className, classData, 0, classData.length);
if (newClass != null) {
logger.info("class loader put:" + className);
loadedClasses.put(className, newClass);
if (resolve) {
resolveClass(newClass);
}
return newClass;
}
}
} catch (Exception e) {
}
loadedClasses.put(className, newClass);
if (resolve) {
resolveClass(newClass);
}
return newClass;
}
public static byte[] loadFileData(File src) throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream(src);
BufferedInputStream bis = new BufferedInputStream(fis);
return getBytesFromInput(bis);
} catch (IOException e) {
throw e;
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
}
}
}
}
public byte[] getClassData(String className) throws IOException {
if (rootPath != null) {
try {
String subPath = className.replace('.', '/') + ".class";
File file = new File(rootPath, subPath);
return loadFileData(file);
} catch (Exception e) {
throw new IOException(className);
}
} else {
return classFiles.get(className);
}
}
}