1 16 package com.google.gwt.user.server.rpc.impl; 17 18 import com.google.gwt.user.client.rpc.IsSerializable; 19 20 import java.io.Serializable ; 21 import java.lang.reflect.Field ; 22 import java.lang.reflect.Modifier ; 23 import java.util.ArrayList ; 24 import java.util.Arrays ; 25 import java.util.Comparator ; 26 import java.util.HashMap ; 27 import java.util.HashSet ; 28 import java.util.Map ; 29 import java.util.Set ; 30 import java.util.zip.CRC32 ; 31 32 36 public class ServerSerializableTypeOracleImpl implements 37 ServerSerializableTypeOracle { 38 39 44 private static final Map classCRC32Cache = new HashMap (); 45 46 52 private static final Map classCustomSerializerCache = new HashMap (); 53 54 private static final Map SERIALIZED_PRIMITIVE_TYPE_NAMES = new HashMap (); 55 private static final Set TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES = new HashSet (); 56 57 static { 58 59 SERIALIZED_PRIMITIVE_TYPE_NAMES.put(boolean.class.getName(), "Z"); 60 SERIALIZED_PRIMITIVE_TYPE_NAMES.put(byte.class.getName(), "B"); 61 SERIALIZED_PRIMITIVE_TYPE_NAMES.put(char.class.getName(), "C"); 62 SERIALIZED_PRIMITIVE_TYPE_NAMES.put(double.class.getName(), "D"); 63 SERIALIZED_PRIMITIVE_TYPE_NAMES.put(float.class.getName(), "F"); 64 SERIALIZED_PRIMITIVE_TYPE_NAMES.put(int.class.getName(), "I"); 65 SERIALIZED_PRIMITIVE_TYPE_NAMES.put(long.class.getName(), "J"); 66 SERIALIZED_PRIMITIVE_TYPE_NAMES.put(short.class.getName(), "S"); 67 68 TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Boolean .class); 69 TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Byte .class); 70 TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Character .class); 71 TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Double .class); 72 TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Exception .class); 73 TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Float .class); 74 TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Integer .class); 75 TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Long .class); 76 TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Object .class); 77 TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Short .class); 78 TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(String .class); 79 TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Throwable .class); 80 } 81 82 private static boolean containsCachedSerializerForClass(Class instanceType) { 83 synchronized (classCustomSerializerCache) { 84 return classCustomSerializerCache.containsKey(instanceType); 85 } 86 } 87 88 private static String getCachedCRCForClass(Class instanceType) { 89 synchronized (classCRC32Cache) { 90 return (String ) classCRC32Cache.get(instanceType); 91 } 92 } 93 94 private static Class getCachedSerializerForClass(Class instanceType) { 95 synchronized (classCustomSerializerCache) { 96 return (Class ) classCustomSerializerCache.get(instanceType); 97 } 98 } 99 100 private static void putCachedCRCForClass(Class instanceType, String crc32) { 101 synchronized (classCRC32Cache) { 102 classCRC32Cache.put(instanceType, crc32); 103 } 104 } 105 106 private static void putCachedSerializerForClass(Class instanceType, 107 Class customFieldSerializer) { 108 synchronized (classCustomSerializerCache) { 109 classCustomSerializerCache.put(instanceType, customFieldSerializer); 110 } 111 } 112 113 private String [] packagePaths; 114 115 public ServerSerializableTypeOracleImpl(String [] packagePaths) { 116 this.packagePaths = packagePaths; 117 } 118 119 public Field [] applyFieldSerializationPolicy(Field [] fields) { 120 ArrayList fieldList = new ArrayList (); 121 for (int index = 0; index < fields.length; ++index) { 122 Field field = fields[index]; 123 assert (field != null); 124 125 int fieldModifiers = field.getModifiers(); 126 if (Modifier.isStatic(fieldModifiers) 127 || Modifier.isTransient(fieldModifiers) 128 || Modifier.isFinal(fieldModifiers)) { 129 continue; 130 } 131 132 fieldList.add(field); 133 } 134 135 Field [] fieldSubset = (Field []) fieldList.toArray(new Field [fieldList.size()]); 136 137 Comparator comparator = new Comparator () { 139 public int compare(Object o1, Object o2) { 140 Field f1 = (Field ) o1; 141 Field f2 = (Field ) o2; 142 143 return f1.getName().compareTo(f2.getName()); 144 } 145 }; 146 Arrays.sort(fieldSubset, 0, fieldSubset.length, comparator); 147 148 return fieldSubset; 149 } 150 151 public SerializedInstanceReference decodeSerializedInstanceReference( 152 String encodedSerializedInstanceReference) { 153 final String [] components = encodedSerializedInstanceReference.split(SerializedInstanceReference.SERIALIZED_REFERENCE_SEPARATOR); 154 return new SerializedInstanceReference() { 155 public String getName() { 156 return components.length > 0 ? components[0] : ""; 157 } 158 159 public String getSignature() { 160 return components.length > 1 ? components[1] : ""; 161 } 162 }; 163 } 164 165 public String encodeSerializedInstanceReference(Class instanceType) { 166 return instanceType.getName() 167 + SerializedInstanceReference.SERIALIZED_REFERENCE_SEPARATOR 168 + getSerializationSignature(instanceType); 169 } 170 171 public String getSerializationSignature(Class instanceType) { 172 String result = getCachedCRCForClass(instanceType); 173 if (result == null) { 174 CRC32 crc = new CRC32 (); 175 generateSerializationSignature(instanceType, crc); 176 result = Long.toString(crc.getValue()); 177 putCachedCRCForClass(instanceType, result); 178 } 179 return result; 180 } 181 182 public String getSerializedTypeName(Class instanceType) { 183 if (instanceType.isPrimitive()) { 184 return (String ) SERIALIZED_PRIMITIVE_TYPE_NAMES.get(instanceType.getName()); 185 } 186 187 return instanceType.getName(); 188 } 189 190 193 public Class hasCustomFieldSerializer(Class instanceType) { 194 assert (instanceType != null); 195 Class result = getCachedSerializerForClass(instanceType); 196 if (result != null) { 197 return result; 199 } 200 if (containsCachedSerializerForClass(instanceType)) { 201 return null; 203 } 204 result = computeHasCustomFieldSerializer(instanceType); 206 putCachedSerializerForClass(instanceType, result); 207 return result; 208 } 209 210 public boolean isSerializable(Class instanceType) { 211 if (instanceType.isArray()) { 212 return isSerializable(instanceType.getComponentType()); 213 } 214 if (instanceType.isPrimitive()) { 215 return true; 216 } 217 if (IsSerializable.class.isAssignableFrom(instanceType) || 218 Serializable.class.isAssignableFrom(instanceType)) { 219 return true; 220 } 221 return hasCustomFieldSerializer(instanceType) != null; 222 } 223 224 227 private Class computeHasCustomFieldSerializer(Class instanceType) { 228 assert (instanceType != null); 229 230 String qualifiedTypeName; 231 232 if (instanceType.isArray()) { 233 Class componentType = instanceType.getComponentType(); 234 235 if (componentType.isPrimitive()) { 236 qualifiedTypeName = "java.lang." + componentType.getName(); 237 } else { 238 qualifiedTypeName = Object .class.getName(); 239 } 240 241 qualifiedTypeName += "_Array"; 242 243 } else { 244 qualifiedTypeName = instanceType.getName(); 245 } 246 247 Class customSerializer = getCustomFieldSerializer(qualifiedTypeName 248 + "_CustomFieldSerializer"); 249 if (customSerializer != null) { 250 return customSerializer; 251 } 252 253 String simpleSerializerName = qualifiedTypeName + "_CustomFieldSerializer"; 255 for (int i = 0; i < packagePaths.length; ++i) { 256 Class customSerializerClass = getCustomFieldSerializer(packagePaths[i] 257 + "." + simpleSerializerName); 258 if (customSerializerClass != null) { 259 return customSerializerClass; 260 } 261 } 262 263 return null; 264 } 265 266 private boolean excludeImplementationFromSerializationSignature( 267 Class instanceType) { 268 if (TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.contains(instanceType)) { 269 return true; 270 } 271 return false; 272 } 273 274 private void generateSerializationSignature(Class instanceType, CRC32 crc) { 275 crc.update(getSerializedTypeName(instanceType).getBytes()); 276 277 if (excludeImplementationFromSerializationSignature(instanceType)) { 278 return; 279 } 280 281 Class customSerializer = hasCustomFieldSerializer(instanceType); 282 if (customSerializer != null) { 283 generateSerializationSignature(customSerializer, crc); 284 } else if (instanceType.isArray()) { 285 generateSerializationSignature(instanceType.getComponentType(), crc); 286 } else if (!instanceType.isPrimitive()) { 287 Field [] fields = applyFieldSerializationPolicy(instanceType.getDeclaredFields()); 288 for (int i = 0; i < fields.length; ++i) { 289 Field field = fields[i]; 290 assert (field != null); 291 292 crc.update(field.getName().getBytes()); 293 crc.update(getSerializedTypeName(field.getType()).getBytes()); 294 } 295 296 Class superClass = instanceType.getSuperclass(); 297 if (superClass != null) { 298 generateSerializationSignature(superClass, crc); 299 } 300 } 301 } 302 303 private Class getCustomFieldSerializer(String qualifiedSerialzierName) { 304 Class customSerializerClass; 305 try { 306 customSerializerClass = Class.forName(qualifiedSerialzierName, false, 307 this.getClass().getClassLoader()); 308 return customSerializerClass; 309 } catch (ClassNotFoundException e) { 310 return null; 311 } 312 } 313 314 private String [] getPackagePaths() { 315 return packagePaths; 316 } 317 } 318 | Popular Tags |