1 2 12 package com.versant.core.jdo.tools.enhancer.utils; 13 14 import com.versant.lib.bcel.classfile.JavaClass; 15 import com.versant.lib.bcel.classfile.Method; 16 import com.versant.lib.bcel.classfile.Field; 17 import com.versant.lib.bcel.Repository; 18 import com.versant.lib.bcel.Constants; 19 20 import java.io.ByteArrayOutputStream ; 21 import java.io.DataOutputStream ; 22 import java.io.IOException ; 23 import java.security.MessageDigest ; 24 import java.security.DigestOutputStream ; 25 import java.security.NoSuchAlgorithmException ; 26 import java.util.*; 27 28 29 30 32 public class SerialUIDHelper { 33 34 38 private static boolean hasStaticInitializer(JavaClass javaClass){ 39 Method[] methods = javaClass.getMethods(); 40 for(int i = 0; i < methods.length; i++) { 41 Method m = methods[i]; 42 if (m.getName().equals("<clinit>")){ return true; 44 } 45 } 46 return false; 47 } 48 49 private static Comparator compareMethodBySig = new SerialUIDHelper.MethodSortSig(); 50 51 private static class MethodSortSig implements Comparator { 52 public int compare(Object a, Object b){ 53 Method methodA = (Method)a; 54 Method methodB = (Method)b; 55 String sigA = methodA.getSignature(); 56 String sigB = methodB.getSignature(); 57 return sigA.compareTo(sigB); 58 } 59 } 60 61 private static Comparator compareMethodByName = new SerialUIDHelper.MethodSortName(); 62 63 private static class MethodSortName implements Comparator { 64 public int compare(Object a, Object b){ 65 Method methodA = (Method)a; 66 Method methodB = (Method)b; 67 String sigA = methodA.getName(); 68 String sigB = methodB.getName(); 69 return sigA.compareTo(sigB); 70 } 71 } 72 73 private static Comparator compareFieldByName = new SerialUIDHelper.FieldSort(); 74 75 private static class FieldSort implements Comparator { 76 public int compare(Object a, Object b){ 77 Field fieldA = (Field)a; 78 Field fieldB = (Field)b; 79 return fieldA.getName().compareTo(fieldB.getName()); 80 } 81 } 82 83 86 private static Comparator compareStringByName = new SerialUIDHelper.CompareStringByName(); 87 88 private static class CompareStringByName implements Comparator { 89 public int compare(Object o1, Object o2) { 90 String c1 = (String )o1; 91 String c2 = (String )o2; 92 return c1.compareTo(c2); 93 } 94 } 95 96 private static Set removePrivateConstructorsAndSort(JavaClass javaClass){ 97 TreeSet set = new TreeSet(compareMethodBySig); 98 Method[] methods = javaClass.getMethods(); 99 for(int i = 0; i < methods.length; i++) { 100 com.versant.lib.bcel.classfile.Method m = methods[i]; 101 if (m.getName().equals("<init>") && (!m.isPrivate())){ 102 set.add(m); 103 } 104 } 105 return set; 106 } 107 108 private static Set removePrivateAndConstructorsAndSort(JavaClass javaClass){ 109 TreeSet set = new TreeSet(compareMethodByName); 110 Method[] methods = javaClass.getMethods(); 111 for(int i = 0; i < methods.length; i++) { 112 Method m = methods[i]; 113 if (!m.getName().startsWith("<")){ 114 if (!m.isPrivate()){ 115 set.add(m); 116 } 117 } 118 } 119 return set; 120 } 121 122 123 128 public static long computeSerialVersionUID(JavaClass clazz) { 129 ByteArrayOutputStream devnull = new ByteArrayOutputStream (512); 130 131 long h = 0; 132 try { 133 MessageDigest md = MessageDigest.getInstance("SHA"); 134 DigestOutputStream mdo = new DigestOutputStream (devnull, md); 135 DataOutputStream data = new DataOutputStream (mdo); 136 137 data.writeUTF(clazz.getClassName()); 138 140 141 int classaccess = clazz.getAccessFlags(); 142 classaccess &= (Constants.ACC_PUBLIC | Constants.ACC_FINAL | 143 Constants.ACC_INTERFACE | Constants.ACC_ABSTRACT); 144 145 152 Method[] method = clazz.getMethods(); 153 if ((classaccess & Constants.ACC_INTERFACE) != 0) { 154 classaccess &= (~Constants.ACC_ABSTRACT); 155 if (method.length > 0) { 156 classaccess |= Constants.ACC_ABSTRACT; 157 } 158 } 159 160 data.writeInt(classaccess); 161 163 168 169 String interfaces[] = clazz.getInterfaceNames(); 170 Arrays.sort(interfaces, compareStringByName); 171 172 for (int i = 0; i < interfaces.length; i++) { 173 data.writeUTF(interfaces[i]); 174 } 176 177 178 179 com.versant.lib.bcel.classfile.Field[] field = clazz.getFields(); 180 Arrays.sort(field, compareFieldByName); 181 182 for (int i = 0; i < field.length; i++) { 183 Field f = field[i]; 184 185 188 int m = f.getAccessFlags(); 189 if ((f.isPrivate() && f.isStatic()) || 190 (f.isPrivate() && f.isTransient())){ 191 continue; 192 } 193 194 data.writeUTF(f.getName()); 195 data.writeInt(m); 197 data.writeUTF(f.getSignature()); 198 199 } 200 if (hasStaticInitializer(clazz)) { 202 data.writeUTF("<clinit>"); 203 data.writeInt(Constants.ACC_STATIC); data.writeUTF("()V"); 206 207 } 208 214 215 Iterator nonPrivateConstructorsIter = removePrivateConstructorsAndSort(clazz).iterator(); 216 while (nonPrivateConstructorsIter.hasNext()){ 217 Method m = (Method)nonPrivateConstructorsIter.next(); 218 String mname = "<init>"; 219 String desc = m.getSignature(); 220 desc = desc.replace('/', '.'); 221 data.writeUTF(mname); 222 data.writeInt(m.getAccessFlags()); 224 data.writeUTF(desc); 225 } 226 228 231 232 Iterator nonPrivateAndNoConstructorsIter = removePrivateAndConstructorsAndSort(clazz).iterator(); 233 while (nonPrivateAndNoConstructorsIter.hasNext()){ 234 Method m = (Method)nonPrivateAndNoConstructorsIter.next(); 235 String mname = m.getName(); 236 String desc = m.getSignature(); 237 desc = desc.replace('/', '.'); 238 data.writeUTF(mname); 239 data.writeInt(m.getAccessFlags()); 241 data.writeUTF(desc); 242 } 243 247 data.flush(); 248 byte hasharray[] = md.digest(); 249 for (int i = 0; i < Math.min(8, hasharray.length); i++) { 250 h += (long)(hasharray[i] & 255) << (i * 8); 251 } 252 } catch (IOException ignore) { 253 254 h = -1; 255 } catch (NoSuchAlgorithmException complain) { 256 throw new SecurityException (complain.getMessage()); 257 } 258 return h; 259 } 260 261 } 262 | Popular Tags |