package com.aggrepoint.winlet.spring;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.springframework.core.annotation.AnnotationUtils;
import com.aggrepoint.winlet.spring.annotation.Action;
import com.aggrepoint.winlet.spring.annotation.Window;
import com.aggrepoint.winlet.spring.annotation.Winlet;
/**
* 修改Winlet类定义:修改类注解。
*
* @see WinletClassVisitor
* @author Jiangming Yang (yangjm@gmail.com)
*/
public class WinletClassLoader extends ClassLoader {
private ClassLoader innerLoader;
Map<Class<?>, Class<?>> classMap = Collections
.synchronizedMap(new HashMap<Class<?>, Class<?>>());
static Map<String, Class<?>> pathToClassMap = new HashMap<String, Class<?>>();
public WinletClassLoader(ClassLoader inner) {
super(inner);
innerLoader = inner;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> clz = innerLoader.loadClass(name);
if (classMap.containsKey(clz))
return classMap.get(clz);
Class<?> ret = clz;
Winlet winlet = AnnotationUtils.findAnnotation(clz, Winlet.class);
boolean process = winlet != null;
if (!process) {
try {
for (Method m : clz.getMethods()) {
process = AnnotationUtils.findAnnotation(m, Action.class) != null
|| AnnotationUtils.findAnnotation(m, Window.class) != null;
if (process)
break;
}
} catch (NoClassDefFoundError e) {
}
}
if (process) {
try {
ClassReader cr = new ClassReader(clz.getResource(
"/" + name.replace('.', '/') + ".class").openStream());
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cr.accept(new WinletClassVisitor(cw), 0);
byte[] b = cw.toByteArray();
ret = defineClass(name, b, 0, b.length);
if (winlet != null)
pathToClassMap.put(
winlet.value().startsWith("/") ? winlet.value()
: "/" + winlet.value(), ret);
} catch (Throwable e) {
e.printStackTrace();
}
}
classMap.put(clz, ret);
return ret;
}
public static Class<?> getWinletClassByPath(String path) {
if (path == null)
return null;
if (!path.startsWith("/"))
path = "/" + path;
return pathToClassMap.get(path);
}
public static Collection<Class<?>> getClasses() {
return pathToClassMap.values();
}
}