com.wesleyhome.dao.processor.JDefinedObjectStreamClass Maven / Gradle / Ivy
package com.wesleyhome.dao.processor;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMods;
import com.sun.codemodel.JType;
import com.sun.codemodel.JVar;
public final class JDefinedObjectStreamClass {
public static class MemberSignature implements Comparable {
private final JMods mods;
private final String name;
private final String signature;
private MemberSignature(final JFieldVar field) {
mods = field.mods();
name = field.name();
signature = getClassSignature(field.type());
}
private MemberSignature(final JMethod meth) {
mods = meth.mods();
name = meth.name();
signature = getMethodSignature(meth.params(), meth.type());
}
@Override
public int compareTo(final MemberSignature o) {
return name.compareTo(o.name);
}
/**
* Returns JVM type signature for given list of parameters and return type.
*/
private static String getMethodSignature(final List list, final JType jType) {
StringBuilder sbuf = new StringBuilder();
sbuf.append('(');
for (JVar jVar : list) {
sbuf.append(getClassSignature(jVar.type()));
}
sbuf.append(')');
sbuf.append(getClassSignature(jType));
return sbuf.toString();
}
/**
* Returns JVM type signature for given class.
*/
private static String getClassSignature(final JType jType) {
StringBuilder sbuf = new StringBuilder();
if (jType == null) {
sbuf.append('V');
} else if (jType.isPrimitive()) {
String typeName = jType.name();
switch (typeName) {
case "int":
sbuf.append('I');
break;
case "byte":
sbuf.append('B');
break;
case "long":
sbuf.append('J');
break;
case "float":
sbuf.append('F');
break;
case "double":
sbuf.append('D');
break;
case "short":
sbuf.append('S');
break;
case "char":
sbuf.append('C');
break;
case "boolean":
sbuf.append('Z');
break;
case "void":
sbuf.append('V');
break;
default:
throw new InternalError();
}
} else {
sbuf.append('L' + jType.fullName().replace('.', '/') + ';');
}
return sbuf.toString();
}
}
public static long computeDefaultSUID(final JDefinedClass definedClass) {
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
dout.writeUTF(definedClass.fullName());
int classMods = definedClass.mods().getValue() & (Modifier.PUBLIC | Modifier.FINAL | Modifier.INTERFACE | Modifier.ABSTRACT);
Collection methods = definedClass.methods();
if ((classMods & Modifier.INTERFACE) != 0) {
classMods = !methods.isEmpty() ? classMods | Modifier.ABSTRACT : classMods & ~Modifier.ABSTRACT;
}
dout.writeInt(classMods);
if (!definedClass.isArray()) {
Iterator _implements = definedClass._implements();
List ifaceNames = new ArrayList<>();
while (_implements.hasNext()) {
ifaceNames.add(_implements.next().fullName());
}
Collections.sort(ifaceNames);
for (String name : ifaceNames) {
dout.writeUTF(name);
}
}
Collection fields = definedClass.fields().values();
List fieldSigs = new ArrayList<>();
for (JFieldVar jFieldVar : fields) {
fieldSigs.add(new MemberSignature(jFieldVar));
}
Collections.sort(fieldSigs);
for (MemberSignature sig : fieldSigs) {
int mods = sig.mods.getValue()
& (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL | Modifier.VOLATILE | Modifier.TRANSIENT);
if ((mods & Modifier.PRIVATE) == 0 || (mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0) {
dout.writeUTF(sig.name);
dout.writeInt(mods);
dout.writeUTF(sig.signature);
}
}
Iterator constructors = definedClass.constructors();
List constSigs = new ArrayList<>();
while (constructors.hasNext()) {
constSigs.add(new MemberSignature(constructors.next()));
}
Comparator methodComparator = new Comparator() {
@Override
public int compare(final MemberSignature ms1, final MemberSignature ms2) {
return ms1.signature.compareTo(ms2.signature);
}
};
Collections.sort(constSigs, methodComparator);
for (MemberSignature sig : constSigs) {
int mods = sig.mods.getValue()
& (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED
| Modifier.NATIVE | Modifier.ABSTRACT | Modifier.STRICT);
if ((mods & Modifier.PRIVATE) == 0) {
dout.writeUTF("");
dout.writeInt(mods);
dout.writeUTF(sig.signature.replace('/', '.'));
}
}
List methSigs = new ArrayList<>();
for (JMethod method : methods) {
methSigs.add(new MemberSignature(method));
}
Collections.sort(methSigs, methodComparator);
for (MemberSignature sig : methSigs) {
int mods = sig.mods.getValue()
& (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED
| Modifier.NATIVE | Modifier.ABSTRACT | Modifier.STRICT);
if ((mods & Modifier.PRIVATE) == 0) {
dout.writeUTF(sig.name);
dout.writeInt(mods);
dout.writeUTF(sig.signature.replace('/', '.'));
}
}
dout.flush();
MessageDigest md = MessageDigest.getInstance("SHA");
byte[] hashBytes = md.digest(bout.toByteArray());
long hash = 0;
for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
hash = hash << 8 | hashBytes[i] & 0xFF;
}
return hash;
} catch (IOException e) {
throw new InternalError();
} catch (NoSuchAlgorithmException e) {
throw new SecurityException(e.getMessage());
}
}
}