use of com.alibaba.dubbo.common.bytecode.ClassGenerator in project dubbo by alibaba.
the class Builder method newEnumBuilder.
private static Builder<?> newEnumBuilder(Class<?> c) {
ClassLoader cl = ClassHelper.getCallerClassLoader(Builder.class);
String cn = c.getName();
String bcn = BUILDER_CLASS_NAME + "$bc" + BUILDER_CLASS_COUNTER.getAndIncrement();
// writeTo code.
StringBuilder cwt = new StringBuilder("public void writeTo(Object obj, ").append(GenericObjectOutput.class.getName()).append(" out) throws java.io.IOException{");
cwt.append(cn).append(" v = (").append(cn).append(")$1;");
cwt.append("if( $1 == null ){ $2.writeUTF(null); }else{ $2.writeUTF(v.name()); } }");
// parseFrom code.
StringBuilder cpf = new StringBuilder("public Object parseFrom(").append(GenericObjectInput.class.getName()).append(" in) throws java.io.IOException{");
cpf.append("String name = $1.readUTF(); if( name == null ) return null; return (").append(cn).append(")Enum.valueOf(").append(cn).append(".class, name); }");
ClassGenerator cg = ClassGenerator.newInstance(cl);
cg.setClassName(bcn);
cg.setSuperClass(Builder.class);
cg.addDefaultConstructor();
cg.addMethod("public Class getType(){ return " + cn + ".class; }");
cg.addMethod(cwt.toString());
cg.addMethod(cpf.toString());
try {
Class<?> wc = cg.toClass();
return (Builder<?>) wc.newInstance();
} catch (RuntimeException e) {
throw e;
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
cg.release();
}
}
use of com.alibaba.dubbo.common.bytecode.ClassGenerator in project dubbo by alibaba.
the class Builder method newObjectBuilder.
private static Builder<?> newObjectBuilder(final Class<?> c) {
if (c.isEnum())
return newEnumBuilder(c);
if (c.isAnonymousClass())
throw new RuntimeException("Can not instantiation anonymous class: " + c);
if (c.getEnclosingClass() != null && !Modifier.isStatic(c.getModifiers()))
throw new RuntimeException("Can not instantiation inner and non-static class: " + c);
if (Throwable.class.isAssignableFrom(c))
return SerializableBuilder;
ClassLoader cl = ClassHelper.getCallerClassLoader(Builder.class);
// is same package.
boolean isp;
String cn = c.getName(), bcn;
if (// is system class. if( cn.startsWith("java.") || cn.startsWith("javax.") || cn.startsWith("sun.") )
c.getClassLoader() == null) {
isp = false;
bcn = BUILDER_CLASS_NAME + "$bc" + BUILDER_CLASS_COUNTER.getAndIncrement();
} else {
isp = true;
bcn = cn + "$bc" + BUILDER_CLASS_COUNTER.getAndIncrement();
}
// is Collection, is Map, is Serializable.
boolean isc = Collection.class.isAssignableFrom(c);
boolean ism = !isc && Map.class.isAssignableFrom(c);
boolean iss = !(isc || ism) && Serializable.class.isAssignableFrom(c);
// deal with fields.
// fix-order fields names
String[] fns = null;
// load field-config file.
InputStream is = c.getResourceAsStream(c.getSimpleName() + FIELD_CONFIG_SUFFIX);
if (is != null) {
try {
int len = is.available();
if (len > 0) {
if (len > MAX_FIELD_CONFIG_FILE_SIZE)
throw new RuntimeException("Load [" + c.getName() + "] field-config file error: File-size too larger");
String[] lines = IOUtils.readLines(is);
if (lines != null && lines.length > 0) {
List<String> list = new ArrayList<String>();
for (int i = 0; i < lines.length; i++) {
fns = lines[i].split(",");
Arrays.sort(fns, FNC);
for (int j = 0; j < fns.length; j++) list.add(fns[j]);
}
fns = list.toArray(new String[0]);
}
}
} catch (IOException e) {
throw new RuntimeException("Load [" + c.getName() + "] field-config file error: " + e.getMessage());
} finally {
try {
is.close();
} catch (IOException e) {
}
}
}
Field f, fs[];
if (fns != null) {
fs = new Field[fns.length];
for (int i = 0; i < fns.length; i++) {
String fn = fns[i];
try {
f = c.getDeclaredField(fn);
int mod = f.getModifiers();
if (Modifier.isStatic(mod) || (serializeIgnoreFinalModifier(c) && Modifier.isFinal(mod)))
throw new RuntimeException("Field [" + c.getName() + "." + fn + "] is static/final field.");
if (Modifier.isTransient(mod)) {
if (iss)
return SerializableBuilder;
throw new RuntimeException("Field [" + c.getName() + "." + fn + "] is transient field.");
}
f.setAccessible(true);
fs[i] = f;
} catch (SecurityException e) {
throw new RuntimeException(e.getMessage());
} catch (NoSuchFieldException e) {
throw new RuntimeException("Field [" + c.getName() + "." + fn + "] not found.");
}
}
} else {
Class<?> t = c;
List<Field> fl = new ArrayList<Field>();
do {
fs = t.getDeclaredFields();
for (Field tf : fs) {
int mod = tf.getModifiers();
if (Modifier.isStatic(mod) || (serializeIgnoreFinalModifier(c) && Modifier.isFinal(mod)) || // skip static or inner-class's 'this$0' field.
tf.getName().equals("this$0") || //skip private inner-class field
!Modifier.isPublic(tf.getType().getModifiers()))
continue;
if (Modifier.isTransient(mod)) {
if (iss)
return SerializableBuilder;
continue;
}
tf.setAccessible(true);
fl.add(tf);
}
t = t.getSuperclass();
} while (t != Object.class);
fs = fl.toArray(new Field[0]);
if (fs.length > 1)
Arrays.sort(fs, FC);
}
// deal with constructors.
Constructor<?>[] cs = c.getDeclaredConstructors();
if (cs.length == 0) {
Class<?> t = c;
do {
t = t.getSuperclass();
if (t == null)
throw new RuntimeException("Can not found Constructor?");
cs = c.getDeclaredConstructors();
} while (cs.length == 0);
}
if (cs.length > 1)
Arrays.sort(cs, CC);
// writeObject code.
StringBuilder cwf = new StringBuilder("protected void writeObject(Object obj, ").append(GenericObjectOutput.class.getName()).append(" out) throws java.io.IOException{");
cwf.append(cn).append(" v = (").append(cn).append(")$1; ");
cwf.append("$2.writeInt(fields.length);");
// readObject code.
StringBuilder crf = new StringBuilder("protected void readObject(Object ret, ").append(GenericObjectInput.class.getName()).append(" in) throws java.io.IOException{");
crf.append("int fc = $2.readInt();");
crf.append("if( fc != ").append(fs.length).append(" ) throw new IllegalStateException(\"Deserialize Class [").append(cn).append("], field count not matched. Expect ").append(fs.length).append(" but get \" + fc +\".\");");
crf.append(cn).append(" ret = (").append(cn).append(")$1;");
// newInstance code.
StringBuilder cni = new StringBuilder("protected Object newInstance(").append(GenericObjectInput.class.getName()).append(" in){ return ");
Constructor<?> con = cs[0];
int mod = con.getModifiers();
boolean dn = Modifier.isPublic(mod) || (isp && !Modifier.isPrivate(mod));
if (dn) {
cni.append("new ").append(cn).append("(");
} else {
con.setAccessible(true);
cni.append("constructor.newInstance(new Object[]{");
}
Class<?>[] pts = con.getParameterTypes();
for (int i = 0; i < pts.length; i++) {
if (i > 0)
cni.append(',');
cni.append(defaultArg(pts[i]));
}
if (!dn)
// close object array.
cni.append("}");
cni.append("); }");
// get bean-style property metadata.
Map<String, PropertyMetadata> pms = propertyMetadatas(c);
List<Builder<?>> builders = new ArrayList<Builder<?>>(fs.length);
// field name, field type name.
String fn, ftn;
// field type.
Class<?> ft;
// direct access.
boolean da;
PropertyMetadata pm;
for (int i = 0; i < fs.length; i++) {
f = fs[i];
fn = f.getName();
ft = f.getType();
ftn = ReflectUtils.getName(ft);
da = isp && (f.getDeclaringClass() == c) && (Modifier.isPrivate(f.getModifiers()) == false);
if (da) {
pm = null;
} else {
pm = pms.get(fn);
if (pm != null && (pm.type != ft || pm.setter == null || pm.getter == null))
pm = null;
}
crf.append("if( fc == ").append(i).append(" ) return;");
if (ft.isPrimitive()) {
if (ft == boolean.class) {
if (da) {
cwf.append("$2.writeBool(v.").append(fn).append(");");
crf.append("ret.").append(fn).append(" = $2.readBool();");
} else if (pm != null) {
cwf.append("$2.writeBool(v.").append(pm.getter).append("());");
crf.append("ret.").append(pm.setter).append("($2.readBool());");
} else {
cwf.append("$2.writeBool(((Boolean)fields[").append(i).append("].get($1)).booleanValue());");
crf.append("fields[").append(i).append("].set(ret, ($w)$2.readBool());");
}
} else if (ft == byte.class) {
if (da) {
cwf.append("$2.writeByte(v.").append(fn).append(");");
crf.append("ret.").append(fn).append(" = $2.readByte();");
} else if (pm != null) {
cwf.append("$2.writeByte(v.").append(pm.getter).append("());");
crf.append("ret.").append(pm.setter).append("($2.readByte());");
} else {
cwf.append("$2.writeByte(((Byte)fields[").append(i).append("].get($1)).byteValue());");
crf.append("fields[").append(i).append("].set(ret, ($w)$2.readByte());");
}
} else if (ft == char.class) {
if (da) {
cwf.append("$2.writeShort((short)v.").append(fn).append(");");
crf.append("ret.").append(fn).append(" = (char)$2.readShort();");
} else if (pm != null) {
cwf.append("$2.writeShort((short)v.").append(pm.getter).append("());");
crf.append("ret.").append(pm.setter).append("((char)$2.readShort());");
} else {
cwf.append("$2.writeShort((short)((Character)fields[").append(i).append("].get($1)).charValue());");
crf.append("fields[").append(i).append("].set(ret, ($w)((char)$2.readShort()));");
}
} else if (ft == short.class) {
if (da) {
cwf.append("$2.writeShort(v.").append(fn).append(");");
crf.append("ret.").append(fn).append(" = $2.readShort();");
} else if (pm != null) {
cwf.append("$2.writeShort(v.").append(pm.getter).append("());");
crf.append("ret.").append(pm.setter).append("($2.readShort());");
} else {
cwf.append("$2.writeShort(((Short)fields[").append(i).append("].get($1)).shortValue());");
crf.append("fields[").append(i).append("].set(ret, ($w)$2.readShort());");
}
} else if (ft == int.class) {
if (da) {
cwf.append("$2.writeInt(v.").append(fn).append(");");
crf.append("ret.").append(fn).append(" = $2.readInt();");
} else if (pm != null) {
cwf.append("$2.writeInt(v.").append(pm.getter).append("());");
crf.append("ret.").append(pm.setter).append("($2.readInt());");
} else {
cwf.append("$2.writeInt(((Integer)fields[").append(i).append("].get($1)).intValue());");
crf.append("fields[").append(i).append("].set(ret, ($w)$2.readInt());");
}
} else if (ft == long.class) {
if (da) {
cwf.append("$2.writeLong(v.").append(fn).append(");");
crf.append("ret.").append(fn).append(" = $2.readLong();");
} else if (pm != null) {
cwf.append("$2.writeLong(v.").append(pm.getter).append("());");
crf.append("ret.").append(pm.setter).append("($2.readLong());");
} else {
cwf.append("$2.writeLong(((Long)fields[").append(i).append("].get($1)).longValue());");
crf.append("fields[").append(i).append("].set(ret, ($w)$2.readLong());");
}
} else if (ft == float.class) {
if (da) {
cwf.append("$2.writeFloat(v.").append(fn).append(");");
crf.append("ret.").append(fn).append(" = $2.readFloat();");
} else if (pm != null) {
cwf.append("$2.writeFloat(v.").append(pm.getter).append("());");
crf.append("ret.").append(pm.setter).append("($2.readFloat());");
} else {
cwf.append("$2.writeFloat(((Float)fields[").append(i).append("].get($1)).floatValue());");
crf.append("fields[").append(i).append("].set(ret, ($w)$2.readFloat());");
}
} else if (ft == double.class) {
if (da) {
cwf.append("$2.writeDouble(v.").append(fn).append(");");
crf.append("ret.").append(fn).append(" = $2.readDouble();");
} else if (pm != null) {
cwf.append("$2.writeDouble(v.").append(pm.getter).append("());");
crf.append("ret.").append(pm.setter).append("($2.readDouble());");
} else {
cwf.append("$2.writeDouble(((Double)fields[").append(i).append("].get($1)).doubleValue());");
crf.append("fields[").append(i).append("].set(ret, ($w)$2.readDouble());");
}
}
} else if (ft == c) {
if (da) {
cwf.append("this.writeTo(v.").append(fn).append(", $2);");
crf.append("ret.").append(fn).append(" = (").append(ftn).append(")this.parseFrom($2);");
} else if (pm != null) {
cwf.append("this.writeTo(v.").append(pm.getter).append("(), $2);");
crf.append("ret.").append(pm.setter).append("((").append(ftn).append(")this.parseFrom($2));");
} else {
cwf.append("this.writeTo((").append(ftn).append(")fields[").append(i).append("].get($1), $2);");
crf.append("fields[").append(i).append("].set(ret, this.parseFrom($2));");
}
} else {
int bc = builders.size();
builders.add(register(ft));
if (da) {
cwf.append("builders[").append(bc).append("].writeTo(v.").append(fn).append(", $2);");
crf.append("ret.").append(fn).append(" = (").append(ftn).append(")builders[").append(bc).append("].parseFrom($2);");
} else if (pm != null) {
cwf.append("builders[").append(bc).append("].writeTo(v.").append(pm.getter).append("(), $2);");
crf.append("ret.").append(pm.setter).append("((").append(ftn).append(")builders[").append(bc).append("].parseFrom($2));");
} else {
cwf.append("builders[").append(bc).append("].writeTo((").append(ftn).append(")fields[").append(i).append("].get($1), $2);");
crf.append("fields[").append(i).append("].set(ret, builders[").append(bc).append("].parseFrom($2));");
}
}
}
// skip any fields.
crf.append("for(int i=").append(fs.length).append(";i<fc;i++) $2.skipAny();");
// collection or map
if (isc) {
cwf.append("$2.writeInt(v.size()); for(java.util.Iterator it=v.iterator();it.hasNext();){ $2.writeObject(it.next()); }");
crf.append("int len = $2.readInt(); for(int i=0;i<len;i++) ret.add($2.readObject());");
} else if (ism) {
cwf.append("$2.writeInt(v.size()); for(java.util.Iterator it=v.entrySet().iterator();it.hasNext();){ java.util.Map.Entry entry = (java.util.Map.Entry)it.next(); $2.writeObject(entry.getKey()); $2.writeObject(entry.getValue()); }");
crf.append("int len = $2.readInt(); for(int i=0;i<len;i++) ret.put($2.readObject(), $2.readObject());");
}
cwf.append(" }");
crf.append(" }");
ClassGenerator cg = ClassGenerator.newInstance(cl);
cg.setClassName(bcn);
cg.setSuperClass(AbstractObjectBuilder.class);
cg.addDefaultConstructor();
cg.addField("public static java.lang.reflect.Field[] fields;");
cg.addField("public static " + BUILDER_CLASS_NAME + "[] builders;");
if (!dn)
cg.addField("public static java.lang.reflect.Constructor constructor;");
cg.addMethod("public Class getType(){ return " + cn + ".class; }");
cg.addMethod(cwf.toString());
cg.addMethod(crf.toString());
cg.addMethod(cni.toString());
try {
Class<?> wc = cg.toClass();
// set static field
wc.getField("fields").set(null, fs);
wc.getField("builders").set(null, builders.toArray(new Builder<?>[0]));
if (!dn)
wc.getField("constructor").set(null, con);
return (Builder<?>) wc.newInstance();
} catch (RuntimeException e) {
throw e;
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
cg.release();
}
}
use of com.alibaba.dubbo.common.bytecode.ClassGenerator in project dubbo by alibaba.
the class Builder method newArrayBuilder.
private static Builder<?> newArrayBuilder(Class<?> c) {
Class<?> cc = c.getComponentType();
if (cc.isInterface())
return GenericArrayBuilder;
ClassLoader cl = ClassHelper.getCallerClassLoader(Builder.class);
// get class name as int[][], double[].
String cn = ReflectUtils.getName(c), ccn = ReflectUtils.getName(cc);
String bcn = BUILDER_CLASS_NAME + "$bc" + BUILDER_CLASS_COUNTER.getAndIncrement();
int ix = cn.indexOf(']');
// if name='int[][]' then s1='int[', s2='][]'
String s1 = cn.substring(0, ix), s2 = cn.substring(ix);
// writeTo code.
StringBuilder cwt = new StringBuilder("public void writeTo(Object obj, ").append(GenericObjectOutput.class.getName()).append(" out) throws java.io.IOException{");
// parseFrom code.
StringBuilder cpf = new StringBuilder("public Object parseFrom(").append(GenericObjectInput.class.getName()).append(" in) throws java.io.IOException{");
cwt.append("if( $1 == null ){ $2.write0(OBJECT_NULL); return; }");
cwt.append(cn).append(" v = (").append(cn).append(")$1; int len = v.length; $2.write0(OBJECT_VALUES); $2.writeUInt(len); for(int i=0;i<len;i++){ ");
cpf.append("byte b = $1.read0(); if( b == OBJECT_NULL ) return null; if( b != OBJECT_VALUES ) throw new java.io.IOException(\"Input format error, expect OBJECT_NULL|OBJECT_VALUES, get \" + b + \".\");");
cpf.append("int len = $1.readUInt(); if( len == 0 ) return new ").append(s1).append('0').append(s2).append("; ");
cpf.append(cn).append(" ret = new ").append(s1).append("len").append(s2).append("; for(int i=0;i<len;i++){ ");
Builder<?> builder = null;
if (cc.isPrimitive()) {
if (cc == boolean.class) {
cwt.append("$2.writeBool(v[i]);");
cpf.append("ret[i] = $1.readBool();");
} else if (cc == byte.class) {
cwt.append("$2.writeByte(v[i]);");
cpf.append("ret[i] = $1.readByte();");
} else if (cc == char.class) {
cwt.append("$2.writeShort((short)v[i]);");
cpf.append("ret[i] = (char)$1.readShort();");
} else if (cc == short.class) {
cwt.append("$2.writeShort(v[i]);");
cpf.append("ret[i] = $1.readShort();");
} else if (cc == int.class) {
cwt.append("$2.writeInt(v[i]);");
cpf.append("ret[i] = $1.readInt();");
} else if (cc == long.class) {
cwt.append("$2.writeLong(v[i]);");
cpf.append("ret[i] = $1.readLong();");
} else if (cc == float.class) {
cwt.append("$2.writeFloat(v[i]);");
cpf.append("ret[i] = $1.readFloat();");
} else if (cc == double.class) {
cwt.append("$2.writeDouble(v[i]);");
cpf.append("ret[i] = $1.readDouble();");
}
} else {
builder = register(cc);
cwt.append("builder.writeTo(v[i], $2);");
cpf.append("ret[i] = (").append(ccn).append(")builder.parseFrom($1);");
}
cwt.append(" } }");
cpf.append(" } return ret; }");
ClassGenerator cg = ClassGenerator.newInstance(cl);
cg.setClassName(bcn);
cg.setSuperClass(Builder.class);
cg.addDefaultConstructor();
if (builder != null)
cg.addField("public static " + BUILDER_CLASS_NAME + " builder;");
cg.addMethod("public Class getType(){ return " + cn + ".class; }");
cg.addMethod(cwt.toString());
cg.addMethod(cpf.toString());
try {
Class<?> wc = cg.toClass();
// set static field.
if (builder != null)
wc.getField("builder").set(null, builder);
return (Builder<?>) wc.newInstance();
} catch (RuntimeException e) {
throw e;
} catch (Throwable e) {
throw new RuntimeException(e.getMessage());
} finally {
cg.release();
}
}
Aggregations