1 29 30 package com.caucho.make; 31 32 import com.caucho.util.Crc64; 33 import com.caucho.vfs.PersistentDependency; 34 35 import java.lang.reflect.Field ; 36 import java.lang.reflect.Method ; 37 import java.lang.reflect.Modifier ; 38 import java.util.Arrays ; 39 import java.util.Comparator ; 40 import java.util.logging.Level ; 41 import java.util.logging.Logger ; 42 43 46 public class ClassDependency implements PersistentDependency { 47 private final static Logger log 48 = Logger.getLogger(ClassDependency.class.getName()); 49 50 private Class _cl; 51 52 private boolean _checkFields = true; 53 private boolean _checkStatic = true; 54 private boolean _checkProtected = true; 55 private boolean _checkPrivate = true; 56 57 private boolean _isDigestModified; 58 private long _newDigest; 59 60 63 public ClassDependency(Class cl) 64 { 65 _cl = cl; 66 } 67 68 74 public ClassDependency(Class cl, long digest) 75 { 76 _cl = cl; 77 78 long newDigest = getDigest(); 79 80 if (newDigest != digest) { 81 if (log.isLoggable(Level.FINE)) 82 log.fine(_cl.getName() + " digest is modified (old=" + digest + ",new=" + newDigest + ")"); 83 84 _isDigestModified = true; 85 } 86 } 87 88 91 public boolean isModified() 92 { 93 return _isDigestModified; 94 } 95 96 99 public long getDigest() 100 { 101 try { 102 if (_newDigest != 0) 103 return _newDigest; 104 105 if (_cl == null) 106 return -1; 107 108 long digest = 37; 109 110 digest = addDigest(digest, _cl); 111 112 _newDigest = digest; 113 } catch (Throwable e) { 114 log.log(Level.FINER, e.toString(), e); 115 116 _newDigest = -1; 117 } 118 119 return _newDigest; 120 } 121 122 125 private long addDigest(long digest, Class cl) 126 throws Exception 127 { 128 if (_cl == null) 129 return digest; 130 131 digest = addDigest(digest, cl.getName()); 132 133 digest = addDigest(digest, cl.getModifiers()); 134 135 Class superClass = cl.getSuperclass(); 136 if (superClass != null 137 && superClass.getName().startsWith("java.") 138 && ! superClass.getName().startsWith("javax.")) { 139 digest = addDigest(digest, superClass); 140 } 141 142 Class []interfaces = cl.getInterfaces(); 143 Arrays.sort(interfaces, ClassComparator.CMP); 144 for (int i = 0; i < interfaces.length; i++) 145 digest = addDigest(digest, interfaces[i].getName()); 146 147 if (_checkFields) { 148 Field []fields = cl.getDeclaredFields(); 149 150 Arrays.sort(fields, FieldComparator.CMP); 151 152 for (int i = 0; i < fields.length; i++) { 153 int modifiers = fields[i].getModifiers(); 154 155 if (Modifier.isPrivate(modifiers) && ! _checkPrivate) 156 continue; 157 if (Modifier.isProtected(modifiers) && ! _checkProtected) 158 continue; 159 160 digest = addDigest(digest, fields[i].getName()); 161 digest = addDigest(digest, fields[i].getModifiers()); 162 digest = addDigest(digest, fields[i].getType().getName()); 163 } 164 } 165 166 Method []methods = cl.getDeclaredMethods(); 167 Arrays.sort(methods, MethodComparator.CMP); 168 169 for (int i = 0; i < methods.length; i++) { 170 Method method = methods[i]; 171 int modifiers = method.getModifiers(); 172 173 if (Modifier.isPrivate(modifiers) && ! _checkPrivate) 174 continue; 175 if (Modifier.isProtected(modifiers) && ! _checkProtected) 176 continue; 177 if (Modifier.isStatic(modifiers) && ! _checkStatic) 178 continue; 179 180 digest = addDigest(digest, method.getName()); 181 digest = addDigest(digest, method.getModifiers()); 182 digest = addDigest(digest, method.getName()); 183 184 Class []param = method.getParameterTypes(); 185 for (int j = 0; j < param.length; j++) 186 digest = addDigest(digest, param[j].getName()); 187 188 digest = addDigest(digest, method.getReturnType().getName()); 189 190 Class []exn = method.getExceptionTypes(); 191 Arrays.sort(exn, ClassComparator.CMP); 192 for (int j = 0; j < exn.length; j++) 193 digest = addDigest(digest, exn[j].getName()); 194 } 195 196 return digest; 197 } 198 199 202 public String getJavaCreateString() 203 { 204 return ("new com.caucho.make.ClassDependency(" + 205 _cl.getName().replace('$', '.') + ".class, " + getDigest() + "L)"); 206 } 207 208 211 private static long addDigest(long digest, long v) 212 { 213 digest = Crc64.generate(digest, (byte) (v >> 24)); 214 digest = Crc64.generate(digest, (byte) (v >> 16)); 215 digest = Crc64.generate(digest, (byte) (v >> 8)); 216 digest = Crc64.generate(digest, (byte) v); 217 218 return digest; 219 } 220 221 224 private static long addDigest(long digest, String string) 225 { 226 return Crc64.generate(digest, string); 227 } 228 229 public int hashCode() 230 { 231 return _cl.hashCode(); 232 } 233 234 public boolean equals(Object o) 235 { 236 if (o == this) 237 return true; 238 239 if (! (o instanceof ClassDependency)) 240 return false; 241 242 ClassDependency depend = (ClassDependency) o; 243 244 return _cl.equals(depend._cl); 245 } 246 247 static class ClassComparator implements Comparator <Class > { 248 static final ClassComparator CMP = new ClassComparator(); 249 250 public int compare(Class a, Class b) 251 { 252 if (a == b) 253 return 0; 254 else if (a == null) 255 return -1; 256 else if (b == null) 257 return 1; 258 259 return a.getName().compareTo(b.getName()); 260 } 261 } 262 263 static class FieldComparator implements Comparator <Field > { 264 static final FieldComparator CMP = new FieldComparator(); 265 266 public int compare(Field a, Field b) 267 { 268 if (a == b) 269 return 0; 270 else if (a == null) 271 return -1; 272 else if (b == null) 273 return 1; 274 275 int cmp = a.getName().compareTo(b.getName()); 276 if (cmp != 0) 277 return cmp; 278 279 cmp = a.getDeclaringClass().getName().compareTo(b.getDeclaringClass().getName()); 280 if (cmp != 0) 281 return cmp; 282 283 return a.getType().getName().compareTo(b.getType().getName()); 284 } 285 } 286 287 static class MethodComparator implements Comparator <Method > { 288 static final MethodComparator CMP = new MethodComparator(); 289 290 public int compare(Method a, Method b) 291 { 292 if (a == b) 293 return 0; 294 else if (a == null) 295 return -1; 296 else if (b == null) 297 return 1; 298 299 int cmp = a.getName().compareTo(b.getName()); 300 if (cmp != 0) 301 return cmp; 302 303 Class []paramA = a.getParameterTypes(); 304 Class []paramB = b.getParameterTypes(); 305 306 if (paramA.length < paramB.length) 307 return -1; 308 else if (paramB.length < paramA.length) 309 return 1; 310 311 for (int i = 0; i < paramA.length; i++) { 312 cmp = paramA[i].getName().compareTo(paramB[i].getName()); 313 if (cmp != 0) 314 return cmp; 315 } 316 317 cmp = a.getDeclaringClass().getName().compareTo(b.getDeclaringClass().getName()); 318 if (cmp != 0) 319 return cmp; 320 321 return a.getReturnType().getName().compareTo(b.getReturnType().getName()); 322 } 323 } 324 } 325 | Popular Tags |