All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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());
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy