Files
redkale/src/org/redkale/util/ResourceFactory.java
wentch 216a15c3d8
2015-12-15 16:24:32 +08:00

246 lines
9.5 KiB
Java

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.util;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.*;
import java.util.regex.*;
import javax.annotation.*;
/**
* 如果Resource(name = "$") 表示资源name采用所属对象的name
*
* @see http://www.redkale.org
* @author zhangjx
*/
@SuppressWarnings("unchecked")
public final class ResourceFactory {
public static final String RESOURCE_PARENT_NAME = "$";
private static final Logger logger = Logger.getLogger(ResourceFactory.class.getSimpleName());
private final ResourceFactory parent;
private static final ResourceFactory instance = new ResourceFactory(null);
private final ConcurrentHashMap<Type, Intercepter> interceptmap = new ConcurrentHashMap();
private final ConcurrentHashMap<Class<?>, ConcurrentHashMap<String, ?>> store = new ConcurrentHashMap();
private final ConcurrentHashMap<Type, ConcurrentHashMap<String, ?>> gencstore = new ConcurrentHashMap();
private ResourceFactory(ResourceFactory parent) {
this.parent = parent;
}
public static ResourceFactory root() {
return instance;
}
public ResourceFactory createChild() {
return new ResourceFactory(this);
}
public void release() {
this.store.clear();
}
public void register(final Class clazz, final Object rs) {
register("", clazz, rs);
}
public void register(final Object rs) {
if (rs != null) register("", rs.getClass(), rs);
}
public void add(final Type clazz, final Intercepter rs) {
if (clazz == null || rs == null) return;
interceptmap.put(clazz, rs);
}
public void register(final String name, final Object rs) {
register(name, rs.getClass(), rs);
}
public <A> void register(final String name, final Class<? extends A> clazz, final A rs) {
ConcurrentHashMap map = this.store.get(clazz);
if (map == null) {
ConcurrentHashMap<String, A> sub = new ConcurrentHashMap();
sub.put(name, rs);
store.put(clazz, sub);
} else {
map.put(name, rs);
}
}
public <A> void register(final String name, final Type clazz, final A rs) {
if (clazz instanceof Class) {
register(name, (Class) clazz, rs);
return;
}
ConcurrentHashMap map = this.gencstore.get(clazz);
if (map == null) {
ConcurrentHashMap<String, A> sub = new ConcurrentHashMap();
sub.put(name, rs);
gencstore.put(clazz, sub);
} else {
map.put(name, rs);
}
}
public <A> A find(Class<? extends A> clazz) {
return find("", clazz);
}
public <A> A find(String name, Type clazz) {
Map<String, ?> map = this.gencstore.get(clazz);
if (map != null) {
A rs = (A) map.get(name);
if (rs != null) return rs;
}
if (parent != null) return parent.find(name, clazz);
return null;
}
public <A> A find(String name, Class<? extends A> clazz) {
Map<String, ?> map = this.store.get(clazz);
if (map != null) {
A rs = (A) map.get(name);
if (rs != null) return rs;
}
if (parent != null) return parent.find(name, clazz);
return null;
}
public <A> A findChild(final String name, final Class<? extends A> clazz) {
A rs = find(name, clazz);
if (rs != null) return rs;
for (Map.Entry<Class<?>, ConcurrentHashMap<String, ?>> en : this.store.entrySet()) { //不用forEach为兼容JDK 6
if (!clazz.isAssignableFrom(en.getKey())) continue;
Object v = en.getValue().get(name);
if (v != null) return (A) v;
}
return null;
}
public <A> Map<String, A> find(final Pattern reg, Class<? extends A> clazz, A exclude) {
Map<String, A> result = new LinkedHashMap();
load(reg, clazz, exclude, result);
return result;
}
private <A> void load(final Pattern reg, Class<? extends A> clazz, final A exclude, final Map<String, A> result) {
ConcurrentHashMap<String, ?> map = this.store.get(clazz);
if (map != null) {
for (Map.Entry<String, ?> en : map.entrySet()) { // 不用forEach为兼容JDK 6
String x = en.getKey();
Object y = en.getValue();
if (y != exclude && reg.matcher(x).find() && result.get(x) == null) result.put(x, (A) y);
}
}
if (parent != null) parent.load(reg, clazz, exclude, result);
}
public <T> boolean inject(final Object src) {
return inject(src, null);
}
public <T> boolean inject(final Object src, final T attachment) {
return inject(src, attachment, new ArrayList());
}
private <T> boolean inject(final Object src, final T attachment, final List<Object> list) {
if (src == null) return false;
try {
list.add(src);
Class clazz = src.getClass();
do {
for (Field field : clazz.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) continue;
field.setAccessible(true);
final Class classtype = field.getType();
final Type genctype = field.getGenericType();
Resource rc = field.getAnnotation(Resource.class);
if (rc == null) {
boolean flag = true;
Object ns = field.get(src);
for (Object o : list) {
if (o == ns) {
flag = false;
break;
}
}
if (ns == null) continue;
if (ns.getClass().isPrimitive() || ns.getClass().isArray() || ns.getClass().getName().startsWith("java")) continue;
if (flag) this.inject(ns, attachment, list);
continue;
}
if (Modifier.isFinal(field.getModifiers())) continue;
final String rcname = (rc.name().contains(RESOURCE_PARENT_NAME) && src instanceof Nameable) ? rc.name().replace(RESOURCE_PARENT_NAME, ((Nameable) src).name()) : rc.name();
Object rs = genctype == classtype ? null : find(rcname, genctype);
if (rs == null) {
if (Map.class.isAssignableFrom(classtype)) {
rs = find(Pattern.compile(rcname.isEmpty() ? ".*" : rcname), (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[1], src);
} else if (rcname.startsWith("property.")) {
rs = find(rcname, String.class);
} else {
rs = find(rcname, classtype);
}
}
if (rs == null) {
Intercepter it = findIntercepter(field.getGenericType(), field);
if (it != null) it.invoke(this, src, field, attachment);
continue;
}
if (!rs.getClass().isPrimitive() && classtype.isPrimitive()) {
if (classtype == int.class) {
rs = Integer.decode(rs.toString());
} else if (classtype == long.class) {
rs = Long.decode(rs.toString());
} else if (classtype == short.class) {
rs = Short.decode(rs.toString());
} else if (classtype == boolean.class) {
rs = "true".equalsIgnoreCase(rs.toString());
} else if (classtype == byte.class) {
rs = Byte.decode(rs.toString());
} else if (classtype == float.class) {
rs = Float.parseFloat(rs.toString());
} else if (classtype == double.class) {
rs = Double.parseDouble(rs.toString());
}
}
field.set(src, rs);
}
} while ((clazz = clazz.getSuperclass()) != Object.class);
return true;
} catch (Exception ex) {
logger.log(Level.FINER, "inject " + src + " error", ex);
return false;
}
}
private Intercepter findIntercepter(Type ft, Field field) {
Intercepter it = this.interceptmap.get(ft);
if (it != null) return it;
Class c = field.getType();
for (Map.Entry<Type, Intercepter> en : this.interceptmap.entrySet()) {
Type t = en.getKey();
if (t == ft) return en.getValue();
if (t instanceof Class && (((Class) t)).isAssignableFrom(c)) return en.getValue();
}
return parent == null ? null : parent.findIntercepter(ft, field);
}
public static interface Intercepter {
public void invoke(ResourceFactory factory, Object src, Field field, Object attachment);
}
}