1 2 12 package com.versant.core.metadata; 13 14 import java.util.*; 15 import java.lang.reflect.Modifier ; 16 import java.lang.reflect.Field ; 17 import java.lang.reflect.Method ; 18 import java.math.BigDecimal ; 19 import java.math.BigInteger ; 20 import java.io.IOException ; 21 import java.io.DataOutputStream ; 22 import java.io.ByteArrayOutputStream ; 23 import java.security.MessageDigest ; 24 import java.security.DigestOutputStream ; 25 import java.security.NoSuchAlgorithmException ; 26 27 import com.versant.core.common.BindingSupportImpl; 28 29 36 public final class MetaDataUtils { 37 38 41 private static boolean isJDK_1_5 = false; 42 43 static { 44 try { 45 Class.forName("java.lang.StringBuilder"); 46 isJDK_1_5 = true; 47 } catch (Exception e) { 48 } 50 } 51 52 56 private final HashSet MUTABLE_TYPES = new HashSet(); 57 58 61 private static final int PM_NONE_FIELD_MODS = 62 Modifier.STATIC | Modifier.FINAL; 63 64 67 protected final HashSet PM_PERSISTENT_TYPES = new HashSet(); 68 69 72 protected final HashSet DFG_TYPES = new HashSet(); 73 74 77 protected final HashSet EMBEDDED_ARRAY_TYPES = new HashSet(); 78 79 protected static Set BASIC_TYPES = new HashSet(); 80 81 private Set classIdSet = new HashSet(); 82 private MessageDigest messageDigest; 83 private DataOutputStream hashOut; 84 85 protected HashSet storeTypes = new HashSet(17); 87 protected HashSet externalizedTypes = new HashSet(17); 90 public MetaDataUtils() { 91 Class [] mTypes = new Class []{ 92 java.util.Date .class, 93 94 java.util.List .class, 95 java.util.ArrayList .class, 96 97 java.util.LinkedList .class, 98 java.util.Vector .class, 99 100 java.util.Collection .class, 101 java.util.Set .class, 102 java.util.HashSet .class, 103 java.util.TreeSet .class, 104 java.util.SortedSet .class, 105 java.util.SortedMap .class, 106 107 java.util.Map .class, 108 java.util.HashMap .class, 109 java.util.TreeMap .class, 110 java.util.Hashtable .class, 111 }; 112 113 114 for (int i = 0; i < mTypes.length; i++) { 115 MUTABLE_TYPES.add(mTypes[i]); 116 } 117 Class [] dfg = new Class []{ 118 Boolean.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, 119 Long.TYPE, Character.TYPE, Float.TYPE, Double.TYPE, 120 Boolean .class, Byte .class, Short .class, Integer .class, 121 Long .class, Character .class, Float .class, Double .class, 122 String .class, BigDecimal .class, BigInteger .class, Date.class, 123 124 }; 125 Class [] t = new Class []{ 126 Locale.class, ArrayList.class, 127 128 HashMap.class, HashSet.class, 129 Hashtable.class, LinkedList.class, TreeMap.class, TreeSet.class, 130 SortedSet.class, SortedMap.class, 131 Vector.class, Collection.class, Set.class, List.class, Map.class, 132 }; 133 134 135 for (int i = dfg.length - 1; i >= 0; i--) { 136 DFG_TYPES.add(dfg[i]); 137 PM_PERSISTENT_TYPES.add(dfg[i]); 138 } 139 for (int i = t.length - 1; i >= 0; i--) { 140 PM_PERSISTENT_TYPES.add(t[i]); 141 } 142 Class [] emb = new Class []{ 143 Boolean.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, 144 Long.TYPE, Character.TYPE, Float.TYPE, Double.TYPE, 145 Boolean .class, Byte .class, Short .class, Integer .class, 146 Long .class, Character .class, Float .class, Double .class, 147 148 }; 149 for (int i = emb.length - 1; i >= 0; i--) { 150 if (emb[i].isPrimitive()) EMBEDDED_ARRAY_TYPES.add(emb[i]); 151 } 152 153 Class [] basicTypes = new Class []{ 154 Boolean.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, 155 Long.TYPE, Character.TYPE, Float.TYPE, Double.TYPE, 156 Boolean .class, Byte .class, Short .class, Integer .class, 157 Long .class, Character .class, Float .class, Double .class, 158 byte[].class, char[].class, Byte [].class, Character [].class, 159 String .class, BigDecimal .class, BigInteger .class, Date.class, 160 Calendar.class, java.sql.Date .class, java.sql.Time .class, 161 java.sql.Timestamp .class, 162 }; 163 for (int i = 0; i < basicTypes.length; i++) { 164 BASIC_TYPES.add(basicTypes[i]); 165 } 166 167 ByteArrayOutputStream devnull = new ByteArrayOutputStream (512); 168 try { 169 messageDigest = MessageDigest.getInstance("SHA"); 170 DigestOutputStream mdo = new DigestOutputStream (devnull, 171 messageDigest); 172 hashOut = new DataOutputStream (mdo); 173 } catch (NoSuchAlgorithmException complain) { 174 throw BindingSupportImpl.getInstance().security( 175 complain.getMessage()); 176 } 177 } 178 179 183 public void clear() { 184 classIdSet.clear(); 185 storeTypes.clear(); 186 externalizedTypes.clear(); 187 } 188 189 192 public boolean isMutableType(Class type) { 193 return MUTABLE_TYPES.contains(type); 194 } 195 196 199 public boolean isPersistentModifiers(int modifiers) { 200 return (modifiers & PM_NONE_FIELD_MODS) == 0; 201 } 202 203 206 public boolean isDefaultPersistentModifiers(int modifiers) { 207 return isPersistentModifiers(modifiers) && 208 !Modifier.isTransient(modifiers); 209 } 210 211 217 public boolean isPersistentType(Class type, Map classMap) { 218 return isDefaultPersistentType(type, classMap) 219 || type == Object .class || type.isInterface() 220 || (type.getComponentType() != null); 221 } 222 223 226 public boolean isPersistableOnlyUsingExternalization(Class type, Map classMap) { 227 boolean et = externalizedTypes.contains(type); 228 if (et) externalizedTypes.remove(type); 229 boolean ans = !isPersistentType(type, classMap); 230 if (et) externalizedTypes.add(type); 231 return ans; 232 } 233 234 240 public boolean isDefaultPersistentType(Class type, 241 Map classMap) { 242 243 if (PM_PERSISTENT_TYPES.contains(type) || classMap.containsKey(type) 244 || isTypeRegistered(type) 245 || externalizedTypes.contains(type)) { 246 return true; 247 } 248 type = type.getComponentType(); 249 if (type == null) return false; 250 return PM_PERSISTENT_TYPES.contains(type) || classMap.containsKey(type) 251 || isTypeRegistered(type); 252 } 253 254 261 public boolean isPersistentField(Class type, int modifiers, 262 Map classMap) { 263 return isPersistentModifiers(modifiers) 264 && isPersistentType(type, classMap); 265 } 266 267 270 public boolean isEnhancerAddedField(String fieldName) { 271 return 272 273 fieldName.startsWith("jdo"); 274 } 275 276 279 public boolean isDefaultPersistentField(ClassMetaData.FieldInfo f, Map classMap) { 280 return !isEnhancerAddedField(f.getName()) 281 && isDefaultPersistentModifiers(f.getModifiers()) 282 && isDefaultPersistentType(f.getType(), classMap); 283 } 284 285 288 public boolean isDefaultPersistentField(Field f, 289 Map classMap) { 290 return !isEnhancerAddedField(f.getName()) 291 && isDefaultPersistentModifiers(f.getModifiers()) 292 && isDefaultPersistentType(f.getType(), classMap); 293 } 294 295 298 public boolean isPersistableField(Field f, Map classMap) { 299 return !isEnhancerAddedField(f.getName()) 300 && isPersistentModifiers(f.getModifiers()); 301 } 302 303 306 public boolean isDefaultFetchGroupType(Class type) { 307 return DFG_TYPES.contains(type) 308 || isTypeRegistered(type) 309 || externalizedTypes.contains(type); 310 } 311 312 315 public boolean isEmbeddedType(Class type) { 316 if (DFG_TYPES.contains(type) || externalizedTypes.contains(type)) { 317 return true; 318 } 319 type = type.getComponentType(); 320 return type != null && EMBEDDED_ARRAY_TYPES.contains(type); 321 } 322 323 332 public int getFieldCategory(int persistenceModifier, Class type, 333 Map classMap) { 334 switch (persistenceModifier) { 335 336 case MDStatics.PERSISTENCE_MODIFIER_PERSISTENT: 337 if (externalizedTypes.contains(type)) { 338 return MDStatics.CATEGORY_EXTERNALIZED; 339 } else if (type.getComponentType() != null) { 340 return MDStatics.CATEGORY_ARRAY; 341 } else if (classMap.containsKey(type)) { 342 if (type.isInterface()) return MDStatics.CATEGORY_POLYREF; 343 return MDStatics.CATEGORY_REF; 344 } else if (Collection.class.isAssignableFrom(type)) { 345 return MDStatics.CATEGORY_COLLECTION; 346 347 } else if (Map.class.isAssignableFrom(type)) { 348 return MDStatics.CATEGORY_MAP; 349 } else if (type.isInterface() || type == Object .class) { 350 return MDStatics.CATEGORY_POLYREF; 351 } else if (!Map.class.isAssignableFrom(type) 352 && !Collection.class.isAssignableFrom(type) 353 && !isPersistentType(type, classMap)) { 354 return MDStatics.CATEGORY_EXTERNALIZED; 355 } 356 return MDStatics.CATEGORY_SIMPLE; 357 358 case MDStatics.PERSISTENCE_MODIFIER_TRANSACTIONAL: 359 return MDStatics.CATEGORY_TRANSACTIONAL; 360 361 case MDStatics.PERSISTENCE_MODIFIER_NONE: 362 return MDStatics.CATEGORY_NONE; 363 } 364 throw BindingSupportImpl.getInstance().internal("Bad persistence-modifier code: " + 365 persistenceModifier); 366 } 367 368 373 public int generateClassId(String qname) { 374 int classId = computeClassId(qname); 375 for (; 376 classIdSet.contains(new Integer (classId)); 377 classId = (classId + 1) & 0x7FFFFFFF) { 378 ; 379 } 380 classIdSet.add(new Integer (classId)); 381 return classId; 382 } 383 384 private int computeClassId(String className) { 385 int hash = 0; 386 try { 387 hashOut.writeUTF(className); 388 391 hashOut.flush(); 392 byte hasharray[] = messageDigest.digest(); 393 int len = hasharray.length; 394 if (len > 8) len = 8; 395 for (int i = 0; i < len; i++) { 396 hash += (hasharray[i] & 255) << (i * 4); 397 } 398 hash &= 0x7FFFFFFF; } catch (IOException ignore) { 400 401 hash = -1; 402 } 403 return hash; 404 } 405 406 409 public void registerStoreType(Class type) { 410 storeTypes.add(type); 411 } 412 413 416 public boolean isTypeRegistered(Class type) { 417 return storeTypes.contains(type); 418 } 419 420 424 public static Class getGenericElementType(Field field) { 425 return getType(field, 0); 426 } 427 428 432 public static Class getGenericKeyType(Field field) { 433 return getType(field, 0); 434 } 435 436 440 public static Class getGenericValueType(Field field) { 441 return getType(field, 1); 442 } 443 444 448 private static Class getType(Field field, int index) { 449 if (isJDK_1_5) { 450 Class clazz = null; 452 try { 453 Method methodGetGenericType = field.getClass().getMethod( 454 "getGenericType", 455 new Class []{}); 456 if (methodGetGenericType == null) return null; 457 Object type = methodGetGenericType.invoke(field, 458 new Object []{}); 459 if (type == null) return null; 460 Method methodActualTypeArguments = type.getClass().getMethod( 461 "getActualTypeArguments", 462 new Class []{}); 463 if (methodActualTypeArguments == null) return null; 464 Object typeArray = methodActualTypeArguments.invoke(type, 465 new Object []{}); 466 if (typeArray == null) return null; 467 Object [] types = (Object [])typeArray; 468 clazz = (Class )types[index]; 469 } catch (Exception e) { 470 471 } 472 return clazz; 473 } else { 474 return null; 475 } 476 } 477 478 481 public void registerExternalizedType(Class t) { 482 externalizedTypes.add(t); 483 } 484 485 488 public boolean isBasicType(Class t) { 489 return BASIC_TYPES.contains(t); 490 } 491 492 493 } 494 | Popular Tags |