1 9 10 11 40 41 47 48 57 58 64 65 70 71 74 75 97 98 149 150 package JSX; 151 import java.lang.reflect.*; 152 import java.io.*; 153 import java.util.*; 154 import java.util.Hashtable ; import java.util.LinkedHashMap ; import java.util.Map ; 157 158 public class XMLSerialize { 159 static final boolean defWO_DIRECT = false; 160 162 static final boolean DEBUG = false; 163 165 static final boolean DEBUG_HASH = false; 168 static final boolean TESTCIRC = false; 169 171 static final boolean INTERNAL_DEBUG = false; 172 174 static final boolean CACHE_DEBUG = false; 175 177 static final boolean REENTRY_DEBUG = false; 178 180 static final boolean PUT_FIELD_DEBUG = false; 181 183 static final boolean OPT_DEBUG = false; 184 186 187 static final int ALIAS_INIT = -1; private int aliasSerialNumber; 190 static final String ALIAS_TAG_TOKEN = "alias-ref"; 191 static final String ALIAS_ATTR_TOKEN = "alias"; static final String ALIAS_STRING_TOKEN = "-alias"; 193 194 static final String VERSION = "Version: JSX0.8.13 (maybe out of date - sorry! See the name of the jar.)"; 196 201 static final String NAME_TOKEN = "obj-name"; 207 208 static final String CLASSNAME_TOKEN = "className"; 209 static final String ARRAY_TOKEN = "ArrayOf-"; 212 static final String ARRAY_PRIMITIVE_INDEX_TOKEN = "a"; static final String INTERNAL_PRIMITIVE_TOKEN = "_."; 226 static final String LENGTH_TOKEN = "length"; 227 static final String VALUE_TOKEN = "valueOf"; 228 static final String BINARY_DATA_TOKEN = "binary-data"; 229 static final String NULL_TOKEN = "null"; 230 231 static final String SUPER_TOKEN = "sub-class"; static final String OPT_DATA_TOKEN = "opt-data"; 236 static final String OPT_PRIM_DATA_TOKEN = "opt-prim-data"; 237 238 static final String ALIAS_ID_TOKEN = "alias-ID"; 239 240 241 static final String SPACER = " "; 243 static final String JSX_HEADER_TARGET = "jsx"; static final String XML_HEADER_TARGET = "xml"; 245 246 static final int NOT_SERIALIZED = 247 Modifier.STATIC | Modifier.TRANSIENT; 248 250 251 public static void main(String ars[]) { 252 System.err.println(VERSION); 253 } 254 260 private boolean stringAsElement = true; 264 private boolean includeAliasID = true; 268 269 private boolean superVersion = false; 273 private boolean optVersion = superVersion; private boolean primOrderVersion = optVersion; 280 private PrintWriter out; 281 public XMLSerialize(PrintWriter out) throws IOException { 282 this(out, new Config()); } 285 Config cfg = new Config(); public XMLSerialize(PrintWriter out, Config cfg) throws IOException { 289 if (cfg==null) throw new IOException("Config object must not be null"); 290 this.cfg = cfg; 291 setFormatted(cfg.formatted); 292 superVersion = cfg.superVersion; 293 optVersion = superVersion; primOrderVersion = optVersion; stringAsElement = cfg.aliasID; includeAliasID = cfg.aliasID; this.out = out; 298 } 299 public XMLSerialize(Config cfg) throws IOException { this(new PrintWriter(new OutputStreamWriter(System.out), true), cfg); 301 } 302 public XMLSerialize() throws IOException { this(new Config()); } 307 308 309 public void serialize(Object o, PrintWriter newOut) throws IOException { 311 out = newOut; commonSer(o); 313 } 314 public void serialize(Object o) throws IOException{ 315 commonSer(o); 316 } 317 323 328 int invocationCount = 0; private void commonSer(Object o) throws IOException{ 330 if (invocationCount!=0) { if (superVersion) 333 serializeObject(o, null, ""); else 335 objStore.add(o); return; 337 } else { 339 reset(); 340 invocationCount++; 341 String jsxVersion; 342 if (superVersion) 343 jsxVersion = "2"; 344 else 345 jsxVersion = "1"; 346 toOutPrintln("<?"+JSX_HEADER_TARGET+" version=\""+jsxVersion+"\"?>"); 347 348 serializeObject(o, null, ""); 349 toOutPrintln(); 350 if (TESTCIRC) { 351 System.err.println("Count was: " + (aliasSerialNumber-ALIAS_INIT)); 352 System.err.println(); 353 } 354 invocationCount--; 355 if (cfg.dtdGenerator!=null) cfg.dtdGenerator.generate(); } 357 } 358 359 360 361 365 369 370 371 static class MapProtect extends java.util.Stack { 372 void protect(Map [] cache) { 373 push(cache); 374 } 375 Map [] retrieve() { 376 return (Map [])pop(); 377 } 378 Map [] value() { 379 return (Map [])peek(); 380 } 381 } 382 383 static class MapCatcher extends java.util.Stack { 384 static final boolean DEBUG = false; 386 387 void newCatcher() { push(null); if (DEBUG) System.err.println("newCatcher: "+this); 390 } 391 void set(Map map) { pop(); push(map); 394 if (DEBUG) System.err.println("set(): "+this); 395 } 396 Map freeCatcher() { 397 if (DEBUG) System.err.println("freeCatcher: "+this); 398 return (Map )pop(); } 400 public String toString() { 401 if (size()==0) return "0"; 402 else return size()+", "+peek().toString(); 403 } 404 } 405 406 407 408 414 static class BooleanProtect extends java.util.Stack { 415 void protect(boolean[] cache) { 416 push(cache); 417 } 418 boolean[] retrieve() { 419 return (boolean[])pop(); 420 } 421 boolean[] value() { 422 return (boolean[])peek(); 423 } 424 } 425 426 427 431 static class BooleanCatcher extends java.util.Stack { 432 static final boolean DEBUG = false; 434 435 void newCatcher() { push(Boolean.FALSE); if (DEBUG) System.err.println("newCatcher: "+this); 438 } 439 void set(boolean input) { Boolean b = new Boolean (input); 441 pop(); push(b); 443 if (DEBUG) System.err.println("set(): "+this); 444 } 445 boolean is() { if (DEBUG) System.err.println("is(): "+this); 447 return ((Boolean )peek()).booleanValue(); } 449 boolean freeCatcher() { 450 if (DEBUG) System.err.println("freeCatcher: "+this); 451 return ((Boolean )pop()).booleanValue(); } 453 public String toString() { 454 if (size()==0) return "0"; 455 else return size()+", "+peek().toString(); 456 } 457 } 458 459 public void reset() { if (invocationCount!=0) 461 throw new Error ("Serialize: Attempt to reset alias table mid-way."); 462 defaultCatcher.clear(); 463 putFieldObjectsCatcher.clear(); 464 primStore = new Vector(); 465 initAlias(); 466 putFieldClassStack.clear(); 467 } 468 474 475 private BooleanCatcher defaultCatcher = new BooleanCatcher(); 476 private BooleanProtect defaultProtect = new BooleanProtect(); 477 478 private MapCatcher putFieldObjectsCatcher = new MapCatcher(); 479 private MapProtect putFieldObjectsProtect = new MapProtect(); 480 private Vector primStore; Vector objStore; public void defaultWriteObject() throws IOException { 483 if (DEBUG) 484 System.err.println("defaultWriteObject() in XMLSerialize: should store it"); 485 defaultCatcher.set(true); 486 if (defWO_DIRECT) { 487 System.err.println("Object "+thisObjectStack.get(thisObjectStack.size()-1)); 488 System.err.println("\tof class "+clazzStack.get(clazzStack.size()-1)); 489 System.err.println("\twith indent '"+indentStack.get(indentStack.size()-1)+"'"); 490 System.err.println("\tJust called defaultWriteObject"); 491 System.err.println(); 492 serializeReferences( 493 thisObjectStack.get(thisObjectStack.size()-1), 494 (Class )clazzStack.get(clazzStack.size()-1), 495 (String )indentStack.get(indentStack.size()-1) ); 496 } 497 498 } 499 public void flush() { out.flush(); } 500 public void close() { out.flush(); out.close(); } 501 502 509 public void writePrim(String str) { 510 if (DEBUG) 511 System.err.println("writeInt(i) in XMLSerialize: should store it"); 512 if (primOrderVersion) { 513 printOpenTag(OPT_PRIM_DATA_TOKEN, "", false); printAttr(VALUE_TOKEN, ParseUtilities.encodeXML(str)); 516 toOutPrintln("/>"); } else{ 519 primStore.add(str); 520 } 521 } 522 523 524 533 private Hashtable aliasHash = new Hashtable (); private void initAlias() { 535 aliasSerialNumber = ALIAS_INIT; 536 aliasHash.clear(); 537 } 538 549 class IdObject { 552 Object o; 553 public int hashCode() { 554 return System.identityHashCode(o); 555 } 556 public boolean equals(Object x) { return ((IdObject)x).o == this.o; } 560 public IdObject(Object o) { 561 this.o = o; 562 } 563 } 564 boolean areAliasesUsed=true; private boolean putAlias(Object o, String fieldName, boolean isStringAttr, String indent) { 569 if (DEBUG_HASH) System.err.println(" entering putAlias with "+o); 572 573 if (o==null) return true; Object alias; if (DEBUG_HASH) { 576 for (Enumeration keys=aliasHash.keys(); keys.hasMoreElements();) { 577 Object a = keys.nextElement(); 578 System.err.println(a + " -- " + a.getClass() + " -- " +a.hashCode()); 579 } 580 System.err.println("looking for: "+o+" -- "+o.getClass() + " -- " +System.identityHashCode(o)); 581 System.err.println("Got: "+myget(o)); 582 System.err.println("Same object? 1 " + (myget(o)!=null) ); 583 System.err.println("Same object? 2 " + (mycontainsKey(o)) ); 584 } 585 if ( (alias = myget(o))==null) { 586 ++aliasSerialNumber; myput(o, aliasSerialNumber+""); if (DEBUG_HASH) System.err.println(" recording new alias: "+indent +"inline " +aliasSerialNumber+ ":"); 589 return true; } 594 else 595 { 596 if (isStringAttr) { 597 printAttr(fieldName + ALIAS_STRING_TOKEN, alias+""); 598 } 599 else { 600 if (DEBUG_HASH) System.err.println(" repeating old alias: "+indent+ "alias " +alias+ ":"); 601 printOpenTag(ALIAS_TAG_TOKEN, indent, false); if (fieldName!=null) printAttr(NAME_TOKEN, fieldName); printAttr(ALIAS_ATTR_TOKEN, alias+""); 604 toOutPrintln("/>"); } 606 return false; } 608 } 609 private void removeAlias(Object key) { 610 if (areAliasesUsed) { } else { try { 613 Object oo = aliasHash.remove(new IdObject(key)); 614 if (oo==null) 615 throw new Exception ("Try to remove an object not in aliasHash: " +key); 616 } catch (Exception e) { 617 e.printStackTrace(); 618 } 619 } 620 } 621 public Object myput(Object key, Object value) { 622 if (cfg.dtdGenerator!=null) cfg.dtdGenerator.populate(key); return aliasHash.put(new IdObject(key), value); } 625 public Object myget(Object key) { 626 return aliasHash.get(new IdObject(key)); } 628 public boolean mycontainsKey(Object key) { 629 return aliasHash.containsKey(new IdObject(key)); } 631 632 633 634 644 645 Class [] OOS_ARGS = {ObjectOutputStream.class}; Object [] writeObjectArglist; ObjectOutputStream thisOut; 649 656 public void setArg(Object [] argList) { 657 writeObjectArglist = argList; 658 thisOut = (ObjectOutputStream)argList[0]; 659 } 660 661 662 698 boolean putFieldDiditAll; 700 final class PutFieldImpl extends java.io.ObjectOutputStream.PutField { 702 Map objMap = null; 703 Map primMap = null; Class holdingClass; 705 Map serialMap; 706 707 public PutFieldImpl() { if (PUT_FIELD_DEBUG) System.err.println("PutFieldImpl.<init>"); 709 holdingClass = (Class ) putFieldClassStack.peek(); 710 serialMap = SerialPF.getFieldNameType(holdingClass); 711 717 if (PUT_FIELD_DEBUG) { 718 System.err.println("Present class is: "+holdingClass); 719 System.err.println("Valid fields are: "+serialMap); 720 try { 721 SerialPF.main(new String []{holdingClass.getName()}); } catch (Exception e ) { 723 e.printStackTrace(); 724 } 725 } 726 727 try { objMap = (Map )Class.forName("java.util.LinkedHashMap").newInstance(); 732 primMap = (Map )Class.forName("java.util.LinkedHashMap").newInstance(); 733 } catch (ClassNotFoundException e) { 734 } catch (InstantiationException e) { 735 } catch (IllegalAccessException e) { 736 } 737 if (objMap==null || primMap==null) { objMap = new HashMap (); 739 primMap = new HashMap (); 740 } 741 742 for(Iterator i = serialMap.entrySet().iterator(); i.hasNext();) { 745 Map.Entry pair = (Map.Entry ) i.next(); 746 Class type = (Class ) pair.getValue(); 747 String fieldName = (String ) pair.getKey(); 748 if (type.isPrimitive()) { 749 if (type==boolean.class) 750 primMap.put(fieldName, "false"); 751 else 752 primMap.put(fieldName, "0"); 753 } else { objMap.put(fieldName, null); 755 } 756 } 757 } 758 759 760 766 772 778 public void write(ObjectOutput objectOutput) throws IOException { 779 XMLSerialize s = ((JSX.ObjOut) objectOutput).s; 782 String indent = " "; 784 788 for(Iterator i = primMap.entrySet().iterator(); i.hasNext();) { 790 Map.Entry pair = (Map.Entry ) i.next(); 791 s.printAttr(pair.getKey()+"", ParseUtilities.encodeXML(pair.getValue()+"")); 792 } 795 796 int i=0; 799 for (Enumeration keys=s.primStore.elements(); keys.hasMoreElements();i++){ 800 s.toOutPrintln(); s.toOutPrint(indent+s.spacer); s.printAttr(INTERNAL_PRIMITIVE_TOKEN+i, ParseUtilities.encodeXML((String )keys.nextElement())); 803 } 805 s.primStore.clear(); 808 816 819 putFieldObjectsCatcher.set(objMap); 822 829 830 849 850 if (PUT_FIELD_DEBUG) { 851 System.err.println("PutFieldImpl.write(out)"); 852 System.err.println("objMap:"); 853 System.err.println(objMap); 854 System.err.println("primMap:"); 855 System.err.println(primMap); 856 } 857 } 860 861 private void check(String name, Class clazz) { 862 if (PUT_FIELD_DEBUG) { 864 System.err.println("\texpected "+clazz+", got " +serialMap.get(name)); 865 } 866 if (!serialMap.containsKey(name)) 867 throw new IllegalArgumentException ("no such field - " +name +" is not a valid 'Serializable Field' of "+holdingClass); 868 if ( !((Class )serialMap.get(name)).isAssignableFrom(clazz) ) 872 throw new IllegalArgumentException ("no such field - "+name +" expects a "+serialMap.get(name)+" and cannot be assigned to from '"+ clazz+ "'"); 873 } 874 875 876 public void put(String name, boolean value) { 877 check(name, boolean.class); 878 primMap.put(name, value+""); 879 } 880 public void put(String name, char value) { 881 check(name, char.class); 882 primMap.put(name, value+""); 883 } 884 public void put(String name, byte value) { 885 check(name, byte.class); 886 primMap.put(name, value+""); 887 } 888 public void put(String name, short value) { 889 check(name, short.class); 890 primMap.put(name, value+""); 891 } 892 public void put(String name, int value) { 893 check(name, int.class); 894 primMap.put(name, value+""); 895 } 896 public void put(String name, long value) { 897 check(name, long.class); 898 primMap.put(name, value+""); 899 } 900 public void put(String name, float value) { 901 check(name, float.class); 902 primMap.put(name, value+""); 903 } 904 public void put(String name, double value) { 905 check(name, double.class); 906 primMap.put(name, value+""); 907 } 908 909 910 public void put(String name, Object value) { 911 check(name, value.getClass()); 912 916 918 objMap.put(name, value); } 920 921 930 931 } 932 933 934 944 private void serializeObject(Object o, String fieldName, String indent) 945 throws IOException { 946 if (o==null) { serializeObject(true, o, null, -1, fieldName, indent); } else { 950 Class [] superClasses = null; 951 if (superVersion) { 953 if (o.getClass()==Object .class || o.getClass()==Vector.class || 955 o.getClass()==Hashtable .class || 956 o.getClass()==Class .class || 957 o.getClass()==String .class 958 ) { superClasses = new Class [] { o.getClass() }; 960 } else { 961 superClasses = getReversedSuperClasses(o.getClass()); } 964 } 965 else { 966 superClasses = new Class [] { o.getClass() }; 967 } 968 serializeObject(true, o, superClasses, 0, fieldName, indent); 969 } 971 } 972 973 private void serializeObject(boolean superHeader, Object o, Class [] superClasses, int superI, String fieldName, String indent) throws IOException { 974 976 Class clazz = null; 977 if (o!=null) 978 clazz = superClasses[superI]; 979 980 if (REENTRY_DEBUG) { 981 System.err.println("-----------------------"); 982 if (o!=null) { 983 System.err.println(o); 984 System.err.println(o.getClass()); 985 System.err.println(clazz); 986 } 987 } 988 if (o==null) { printOpenTag(NULL_TOKEN, indent, false); if (fieldName!=null) printAttr(NAME_TOKEN, fieldName); toOutPrintln("/>"); return; } 997 1003 String runTimeClass = ParseUtilities.escapeDollar(clazz.getName()); 1005 if (clazz.isArray()) { 1007 serializeArrayReferences(o, fieldName, indent); 1008 } 1010 1011 else if (clazz==Class .class) { 1012 serializeClass((Class ) o, fieldName, indent); 1013 } 1015 1016 else if (clazz==String .class) { serializeWrapper(o, fieldName, indent); 1018 } 1020 1021 else if (clazz==Vector.class) { 1022 if ((clazz!=superClasses[0]) || putAlias(o, fieldName, false, indent)) { 1024 printOpenTag(runTimeClass, indent, true); if (fieldName!=null) printAttr(NAME_TOKEN, fieldName); if (((Vector)o).size() > 0) { 1028 toOutPrintln(">"); serializeVectorReferences((Vector)o, indent); printCloseTag(runTimeClass, indent); 1031 } else { 1032 toOutPrintln("/>"); } 1034 if (clazz==o.getClass()) removeAlias(o); } } 1039 else if (clazz==Hashtable .class) { 1040 if ((clazz!=superClasses[0]) || putAlias(o, fieldName, false, indent)) { 1041 printOpenTag(runTimeClass, indent, true); if (fieldName!=null) printAttr(NAME_TOKEN, fieldName); 1044 if (((Hashtable )o).size() > 0) { toOutPrintln(">"); serializeHashtableReferences((Hashtable )o, indent); printCloseTag(runTimeClass, indent); 1048 } else { 1049 toOutPrintln("/>"); } 1051 if (clazz==superClasses[0]) removeAlias(o); } } 1056 1057 1058 1059 else { 1062 if (!superVersion || (superVersion && (clazz==superClasses[0]))) { 1070 o = writeReplace(o); 1072 if (superVersion) { 1073 if (o.getClass()==Object .class) { superClasses = new Class [] { o.getClass() }; 1075 } else { 1076 superClasses = getReversedSuperClasses(o.getClass()); } 1079 } else { 1080 superClasses = new Class [] { o.getClass() }; 1081 } 1082 superI = 0; 1083 clazz = superClasses[superI]; 1084 1085 runTimeClass = ParseUtilities.escapeDollar(clazz.getName()); 1088 } 1089 1090 1096 boolean writeFull = false; 1097 if (superVersion) { 1098 if (superHeader) writeFull = putAlias(o, fieldName, false, indent); else 1101 writeFull = true; } else { 1103 writeFull = putAlias(o, fieldName, false, indent); 1104 } 1105 if (writeFull) { 1106 if (superVersion && superI==0 && superHeader) { String leafClassName = ParseUtilities.escapeDollar( 1110 superClasses[superClasses.length-1].getName() 1111 ); 1112 printOpenTag(leafClassName, indent, true); if (fieldName!=null) printAttr(NAME_TOKEN, fieldName); toOutPrintln(">"); serializeObject(false, o, superClasses, 0, SUPER_TOKEN, indent+spacer); 1117 printCloseTag(leafClassName, indent); } else { printOpenTag(runTimeClass, indent, true); if (fieldName!=null) printAttr(NAME_TOKEN, fieldName); 1123 if (optVersion) { serializeFields(o, clazz, indent); } else { serializeFields(o, clazz, indent); serializeOptAttr(o, clazz, indent); 1131 } 1132 1133 boolean hasChildren = false; Class superClass = null; 1138 if (superVersion) { if (superI+1<superClasses.length) 1141 hasChildren = true; } 1144 1145 if (!putFieldDiditAll) { try { 1148 hasChildren = hasChildren || hasChildren(o, clazz); 1149 } catch (IllegalAccessException ex) { 1151 throw new WriteAbortedException("", ex); } 1153 if (optVersion) hasChildren = true; if (hasChildren) { 1155 toOutPrintln(">"); if (optVersion) serializeReferences(o, clazz, indent); 1164 if (INTERNAL_DEBUG) System.err.println("internal objects:"); 1165 Vector localObjStore = objStore; Vector localDefaultCache = defaultCache; 1168 boolean possibleOptData = false; if (optVersion) { 1173 possibleOptData = doesOwnSer(clazz); 1176 if (possibleOptData) { 1177 printOpenTag(OPT_DATA_TOKEN, indent+spacer, false); toOutPrintln(">"); 1180 if (defWO_DIRECT) { 1181 clazzStack.add(clazz); thisObjectStack.add(o); 1183 indentStack.add(indent); 1184 } 1185 internalSer(clazz, o); 1188 if (defWO_DIRECT) { 1189 indentStack.remove(indentStack.size()-1); thisObjectStack.remove(thisObjectStack.size()-1); 1191 clazzStack.remove(clazzStack.size()-1); 1192 } 1193 1194 if (primStore.size()>0) { 1195 printOpenTag(OPT_PRIM_DATA_TOKEN, indent+spacer+spacer, false); serializeOptAttr(o, clazz, indent); 1197 toOutPrintln("/>"); } 1200 } 1201 } 1202 if (!superVersion) { for (Enumeration keys=localObjStore.elements(); keys.hasMoreElements();) { 1206 Object a = keys.nextElement(); 1207 if (INTERNAL_DEBUG && a!=null) System.err.println("in objStore: "+a+"\n"+a.getClass()); 1208 serializeObject(a, null, indent+spacer+spacer); } 1210 } 1211 if (optVersion && possibleOptData) { 1212 printCloseTag(OPT_DATA_TOKEN, indent+spacer); 1213 } 1214 1216 if (INTERNAL_DEBUG) { 1219 System.err.println("should be cleared: "+localObjStore.size()); 1220 System.err.println("references:"); 1222 } 1223 defaultCache = localDefaultCache; if (superVersion && superI+1<superClasses.length) { serializeObject(false, o, superClasses, superI+1, SUPER_TOKEN, indent+spacer); } 1227 if (!optVersion) { for (int j=0; j<putFieldObjectsProtect.value().length; j++) { 1233 Map putFieldObjMap = putFieldObjectsProtect.value()[j]; 1234 if (putFieldObjMap!=null) { 1235 for (Iterator iObj = putFieldObjMap.entrySet().iterator(); iObj.hasNext();) { 1236 Map.Entry pair = (Map.Entry ) iObj.next(); 1237 serializeObject(pair.getValue(), pair.getKey().toString(), indent+spacer); 1238 } 1240 } 1241 } 1242 1243 serializeReferences(o, clazz, indent); 1244 finalizeGetAllFields(); 1245 } 1246 printCloseTag(runTimeClass, indent); 1247 } else { 1248 finalizeGetAllFields(); 1249 toOutPrintln("/>"); } 1252 } else { printCloseTag(runTimeClass, indent); putFieldDiditAll = false; } 1256 } 1257 if (clazz==superClasses[0]) removeAlias(o); } } 1264 } 1265 Vector clazzStack = new Vector(); 1268 Vector thisObjectStack = new Vector(); 1269 Vector indentStack = new Vector(); 1270 1271 1276 private void printOpenTag(String tag, String indent, boolean isObject) { 1277 out.print(indent + "<" +tag); 1278 if (isObject && includeAliasID) 1279 printAttr(ALIAS_ID_TOKEN, aliasSerialNumber+""); 1280 } 1281 private void printCloseTag(String tag, String indent) { 1282 toOutPrintln(indent + "</" +tag+ ">"); 1283 } 1285 1286 1297 Object writeReplace(Object me) throws ObjectStreamException { 1298 try { 1299 Class replacedClass = me.getClass(); 1300 Method writeReplaceMethod = null; try { 1302 writeReplaceMethod = replacedClass.getDeclaredMethod("writeReplace", new Class []{}); 1303 } catch (NoSuchMethodException checkSuperClasses) { writeReplaceMethod = replacedClass.getMethod("writeReplace", new Class []{}); 1306 } 1308 1309 writeReplaceMethod.setAccessible(true); 1310 Object newme = writeReplaceMethod.invoke(me, new Object []{}); 1321 return newme; 1322 } catch (NoSuchMethodException e) { 1323 return me; } catch (IllegalAccessException e) { 1326 System.err.println("IllegalAccessException - this shouldn't happen, since we did setAccessible(). Perhaps security on the JVM precludes it?"); 1327 e.printStackTrace(); 1328 return me; } catch (InvocationTargetException e) { 1330 System.err.println("JSX InvocationTargetException:"); 1331 try { 1335 throw (ObjectStreamException) e.getTargetException(); } catch (ClassCastException f) { 1342 throw new Error ("writeReplace() of "+me.getClass()+ " threw an '"+e.getTargetException()+"'. It should only be of type ObjectStreamException"); 1343 } 1344 } 1346 } 1349 1350 1351 1357 private void serializeArrayReferences(Object o, String fieldName, String indent) throws IOException{ 1358 Class clazz; 1359 if (o==null || !( (clazz=o.getClass()).isArray() )) { 1360 serializeWrapperOrObject(o, indent); 1362 return; } 1364 if (!putAlias(o, fieldName, false, indent)) 1366 return; String runTimeClass = ParseUtilities.escapeDollar(o.getClass().getName()); if (clazz==byte[].class) { printOpenTag(BINARY_DATA_TOKEN, indent, true); if (fieldName!=null) printAttr(NAME_TOKEN, fieldName); 1374 printAttr(VALUE_TOKEN, ParseUtilities.encodeHex((byte[])o, formatted)); 1375 toOutPrintln("/>"); } else { 1378 runTimeClass = getArrayType(clazz); 1379 printOpenTag(runTimeClass, indent, true); if (fieldName!=null) printAttr(NAME_TOKEN, fieldName); 1381 int length = Array.getLength(o); 1382 printAttr(LENGTH_TOKEN, length+""); 1383 1395 { if ( clazz.getComponentType().isPrimitive() ) { 1401 for (int i=0; i<length; i++) { 1402 if (clazz.getComponentType() == byte.class) { } else { 1406 toOutPrintln(); 1407 out.print(indent); 1408 } 1409 if (clazz.getComponentType()==char.class) printAttr(ARRAY_PRIMITIVE_INDEX_TOKEN+i, ParseUtilities.encodeXML(Array.get(o,i)+"")); 1411 else 1412 printAttr(ARRAY_PRIMITIVE_INDEX_TOKEN+i, Array.get(o,i)+""); 1413 } 1414 toOutPrintln("/>"); } 1416 else { toOutPrintln(">"); for (int i=0; i<length; i++) { serializeArrayReferences(Array.get(o, i), null, indent+spacer); 1420 } 1421 printCloseTag(runTimeClass, indent); 1423 } 1424 } 1425 } 1426 removeAlias(o); 1427 } 1428 1429 1434 static String getArrayType(Class clazz) { String a = ""; String name = ParseUtilities.escapeDollar(clazz.getName()); if (DEBUG) System.err.println("Array type = \""+name+"\""); 1438 int i; 1439 for (i=0; name.charAt(i)=='['; i++) 1440 a += ARRAY_TOKEN; 1441 switch (name.charAt(i++)) { 1442 case 'B': a += "byte"; break; 1443 case 'C': a += "char"; break; 1444 case 'D': a += "double"; break; 1445 case 'F': a += "float"; break; 1446 case 'I': a += "int"; break; 1447 case 'J': a += "long"; break; 1448 case 'S': a += "short"; break; 1449 case 'Z': a += "boolean"; break; 1450 case 'L': a += name.substring(i, name.lastIndexOf(';')); break; 1451 } 1453 return a; 1456 } 1457 1458 1466 private boolean hasChildren(Object o, Class frameClass) throws 1467 IllegalAccessException , InvalidClassException { 1468 IllegalAccessException ex = null; if (objStore.size()>0) return true; 1472 for (int j=0; j<putFieldObjectsProtect.value().length; j++) { 1473 Map putFieldObjMap = putFieldObjectsProtect.value()[j]; 1474 if (putFieldObjMap!=null) { 1475 if (putFieldObjMap.size()>0) 1476 return true; 1477 } 1478 } 1479 Field[] fields = getAllFields(o, frameClass, false); for (int i=0; i<fields.length; i++) { 1484 Field f = fields[i]; 1485 if (Modifier.isStatic(f.getModifiers())) continue; 1488 if (!f.getType().isPrimitive()) { 1489 if (stringAsElement || f.getType()!=String .class) { 1490 return true; } 1497 } 1498 } 1499 if (ex != null) { 1503 throw ex; 1504 } 1505 return false; } 1510 1511 1512 1523 private void serializeFields(Object o, Class frameClass, String indent) 1524 throws InvalidClassException { 1525 if (o==null) return; 1528 Field[] fields = getAllFields(o, frameClass, true); try { 1538 for (int i=0; i<fields.length; i++) { 1539 Field f = fields[i]; 1540 String fieldName = shadowEncode(f, o.getClass()); if (DEBUG) System.err.println("Field "+i+": "+f); 1544 if (Modifier.isStatic(f.getModifiers())) continue; Class type = f.getType(); 1548 if (DEBUG) System.err.println("here1"); 1552 if (type.isPrimitive()) { 1553 toOutPrintln(); out.print(indent); String outStr = f.get(o).toString(); 1556 if (type==char.class) 1557 outStr = ParseUtilities.encodeXML(outStr); 1558 printAttr(fieldName, outStr); 1559 } 1560 else if (!stringAsElement && f.get(o)!=null && type==String .class){ toOutPrintln(); out.print(indent); if (DEBUG) System.err.println("here2"); 1565 if (DEBUG) System.err.println("here3"); 1567 if (DEBUG) System.err.println("here4"); 1569 if (putAlias(f.get(o), shadowEncode(f, o.getClass()), true, indent)) { 1571 printAttr(fieldName, ParseUtilities.encodeXML(f.get(o)+"")); 1574 removeAlias(f.get(o)); 1575 } 1576 } 1577 } 1579 1587 } catch (Exception e) { 1588 e.printStackTrace(); 1590 } 1592 } 1593 1594 1595 private void serializeOptAttr(Object o, Class frameClass, String indent) { 1596 int i=0; 1602 for (Enumeration keys=primStore.elements(); keys.hasMoreElements(); i++) { 1603 printAttr(INTERNAL_PRIMITIVE_TOKEN+i, ParseUtilities.encodeXML((String )keys.nextElement())); 1606 } 1608 1611 primStore.clear(); } 1617 1618 1619 1620 1643 boolean isShadowed(Field f, Class c) { 1644 Class stopc = f.getDeclaringClass(); 1645 for (; c!=stopc; c=c.getSuperclass()) { 1646 try { 1647 Field f2 = c.getDeclaredField(f.getName()); 1648 return true; 1651 } catch (NoSuchFieldException e) { 1652 } 1654 } 1655 return false; 1657 } 1658 1664 String qualField(Field f) { 1665 return f.getDeclaringClass().getName() 1666 +"."+f.getName(); 1667 } 1669 1670 1691 String shadowEncode(Field f, Class c) { 1692 if (isShadowed(f, c)) 1693 return qualField(f); 1694 else 1695 return f.getName(); 1696 } 1699 1700 1701 1704 private void printAttr(String attrName, String value) { 1705 out.print(" "+ ParseUtilities.escapeDollar(attrName)+ "=\"" +value+ "\""); 1707 } 1708 1709 1710 1715 private void serializeReferences(Object o, Class frameClass, String indent) throws IOException { 1717 if (o==null) return; 1719 Field[] f = getAllFields(o, frameClass, false); for (int i=0; i<f.length; i++) { 1724 if (Modifier.isStatic(f[i].getModifiers())) continue; 1728 Class type = f[i].getType(); 1729 try { 1730 if (!(type.isPrimitive() || (!stringAsElement && type==String .class))) serializeObject(f[i].get(o), shadowEncode(f[i], o.getClass()), indent+spacer); 1732 } catch (Exception e) { 1733 System.err.println("References: " +e); 1734 System.err.println("i = " +i); 1735 System.err.println("f.length = " +f.length); 1736 e.printStackTrace(); 1737 } 1738 } 1739 } 1740 1741 1742 1755 Vector defaultCache; private void finalizeGetAllFields() { 1757 defaultProtect.retrieve(); putFieldObjectsProtect.retrieve(); } 1760 private Field[] getAllFields(Object o, Class frameClass, boolean firstCall) 1762 throws InvalidClassException { 1763 Vector v = new Vector(); 1765 int cacheIndex = 0; 1766 if (CACHE_DEBUG) 1767 System.err.println("Entering " +firstCall); 1768 if (firstCall) { 1770 objStore = new Vector(); defaultCache = new Vector(); 1772 } 1773 1774 if (o instanceof Externalizable) { 1777 if (firstCall) { try { 1779 ((Externalizable)o).writeExternal(thisOut); 1780 } catch (IOException e) { 1781 } 1783 } 1784 return new Field[0]; 1785 } 1786 1787 1793 Class [] superClasses = null; 1795 if (superVersion) superClasses = new Class [] {frameClass}; 1797 else 1798 superClasses = getReversedSuperClasses(o.getClass()); if (firstCall) { 1800 defaultProtect.protect(new boolean[superClasses.length]); putFieldObjectsProtect.protect(new Map [superClasses.length]); } 1804 for (int j=0; j<superClasses.length; j++) { Class c = superClasses[j]; if (CACHE_DEBUG) 1809 System.err.print(o.getClass() +"CACHE INDEX: " +cacheIndex+"\t\t"); 1810 if (firstCall) { if (!optVersion) { defaultCatcher.newCatcher(); 1813 putFieldObjectsCatcher.newCatcher(); 1814 internalSer(c, o); putFieldObjectsProtect.value()[j] = putFieldObjectsCatcher.freeCatcher(); 1816 1817 boolean defaultResult = defaultCatcher.freeCatcher(); defaultProtect.value()[j] = defaultResult; } 1820 if (CACHE_DEBUG) 1821 System.err.println("firstcall: CACHE: " +defaultCache); 1822 } else { 1823 if (CACHE_DEBUG) 1824 System.err.println("not firstcall CACHE: " +defaultCache); 1825 } 1827 1828 boolean doesOwn = doesOwnSer(c); 1829 if (optVersion || 1834 (!doesOwn || (doesOwn && defaultProtect.value()[j])) ) { Field[] f = c.getDeclaredFields(); 1837 Map fmap = SerialPF.getFieldNameType(c); 1838 boolean allOK = SerialPF.areSerializableFieldsValidFor_defWO(fmap, c); 1840 if (!allOK) throw new InvalidClassException("unmatched serializable field(s) declared"); 1841 for (int i=0; i<f.length; i++) { 1842 if (fmap.containsKey(f[i].getName())) v.add(f[i]); 1844 } 1845 } 1846 } 1848 1860 Field[] f = new Field[v.size()]; v.copyInto(f); Field.setAccessible(f, true); return f; 1866 } 1867 1868 1874 static public Class [] getReversedSuperClasses(Class c) { 1875 if (c==Object .class) 1876 return new Class [0]; Class storeC = c; 1878 boolean isObjSer = Serializable.class.isAssignableFrom(storeC); 1879 1880 int numSerClasses = 0; do { 1883 if (!isObjSer) 1885 numSerClasses++; else if (Serializable.class.isAssignableFrom(c)) 1887 numSerClasses++; 1893 } while ( (c = c.getSuperclass()) != Object .class); 1897 Class [] superClasses = new Class [numSerClasses]; c = storeC; int iSuper=superClasses.length-1; do { 1903 if (!isObjSer) 1904 superClasses[iSuper--] = c; else if (Serializable.class.isAssignableFrom(c)) 1906 superClasses[iSuper--] = c; } while ( (c = c.getSuperclass()) != Object .class); 1910 if (DEBUG) { 1915 for (int j=0; j<superClasses.length; j++) 1916 System.err.println("superClasses["+j+"] = " + superClasses[j]); 1917 } 1918 return superClasses; 1919 } 1920 1921 1922 1946 Stack putFieldClassStack = new Stack(); 1947 private boolean internalSer(Class clazz, Object o) { 1949 defaultCatcher.set(false); 1951 Method m; 1952 if ((m=getDeclaredMethod(clazz, "writeObject", OOS_ARGS, 1953 Modifier.PRIVATE, Modifier.STATIC)) != null) { 1954 if (INTERNAL_DEBUG) 1955 System.err.print("--JSX serialize--"); 1956 try { 1960 if (INTERNAL_DEBUG) 1962 System.err.println("invoking: " +m); 1963 1971 putFieldClassStack.push(clazz); m.invoke(o, writeObjectArglist); putFieldClassStack.pop(); 1975 } catch (InvocationTargetException e) { 1979 try { 1980 RuntimeException r = (RuntimeException ) e.getTargetException(); 1982 throw r; 1984 } catch (ClassCastException nestedE) { nestedE.printStackTrace(); 1987 } 1988 } catch (Exception e) { 1989 System.err.println(e); 1990 e.printStackTrace(); 1991 } 1992 if (INTERNAL_DEBUG) { 1994 } 1995 if (INTERNAL_DEBUG) 1996 System.err.println("Object Store: "+objStore); if (INTERNAL_DEBUG) 1998 System.err.println("Primitive Store: "+primStore); 2000 return true; } 2002 else { 2003 if (INTERNAL_DEBUG) 2004 System.err.println("No writeObject() found"); 2005 defaultCatcher.set(true); 2006 return false; } 2008 } 2009 2010 2020 private boolean doesOwnSer(Class clazz) { 2021 return ((getDeclaredMethod(clazz, "writeObject", OOS_ARGS, 2022 Modifier.PRIVATE, Modifier.STATIC)) != null); 2023 } 2024 2025 2026 2027 2028 2041 private void serializeVectorReferences (Vector o, String indent) throws IOException{ 2042 final String spc = indent + spacer; 2043 if (o==null) throw new RuntimeException ("impossible; redundant safety"); 2044 for (Enumeration keys=o.elements(); keys.hasMoreElements(); ) { 2045 Object obj = keys.nextElement(); 2046 serializeWrapperOrObject(obj, spc); 2047 } 2049 }; 2051 2052 2053 2059 private void serializeWrapperOrObject (Object obj, String spc) throws IOException{ 2060 if (obj==null) { 2061 printOpenTag(NULL_TOKEN, spc, false); toOutPrintln("/>"); return; 2064 } 2065 Class type = obj.getClass(); 2066 if (type==Boolean .class || type==Byte .class || type==Short .class || 2069 type==Integer .class || 2070 type==Long .class || 2071 type==Float .class || 2072 type==Double .class) 2073 serializeWrapper(obj, null, spc); 2074 else if (type==String .class || 2075 type==Character .class) 2076 serializeWrapper(obj, null, spc); else 2078 serializeObject(obj, null, spc); } 2080 2081 2088 private void serializeHashtableReferences ( 2089 Hashtable o, String indent) throws IOException{ 2090 if (o==null) throw new RuntimeException ("impossible; redundant safety"); 2091 for (Enumeration keys=o.keys(); keys.hasMoreElements(); ) { 2092 Object key = keys.nextElement(); 2093 Object value = o.get(key); 2094 Object [] objs = {key, value}; 2095 String [] spc = {indent+spacer, indent+spacer}; for (int i=0; i<objs.length; i++) { 2097 Class type = objs[i].getClass(); 2098 if (type==Boolean .class || type==Byte .class || type==Short .class || 2101 type==Integer .class || 2102 type==Long .class || 2103 type==Float .class || 2104 type==Double .class) 2105 serializeWrapper(objs[i], null, spc[i]); 2106 else if (type==String .class || 2107 type==Character .class) 2108 serializeWrapper(objs[i], null, spc[i]); 2109 else 2110 serializeObject(objs[i], null, spc[i]); } 2112 if (keys.hasMoreElements()) toOutPrintln(); } 2114 } 2115 2116 2126 private void serializeWrapper(Object value, String name, String indent) { 2127 if (DEBUG_HASH) System.err.println("----enter serializeWrapper with "+name+"="+value); 2128 String tag = ParseUtilities.escapeDollar(value.getClass().getName()); if (putAlias(value, name, false, indent)) { if (DEBUG_HASH) System.err.println("found NO alias, so do inline (in serializeWrapper)"); 2133 printOpenTag(tag, indent, true); if (name!=null) 2135 printAttr(NAME_TOKEN, name); 2136 if (value.getClass()==String .class) printAttr(VALUE_TOKEN, ParseUtilities.encodeXML((String )value)); 2138 else if (value.getClass()==Character .class) { 2139 printAttr(VALUE_TOKEN, ParseUtilities.encodeXML(value+"")); 2140 } 2141 else { 2142 printAttr(VALUE_TOKEN, value+""); 2143 } 2144 out.print("/>"); toOutPrintln(); removeAlias(value); 2150 } 2151 else { 2152 if (DEBUG_HASH) System.err.println("found object aliased already (in serializeWrapper)"); 2154 } 2156 } 2157 2158 private void serializeClass(Class clazz, String name, String indent) { 2159 String tag = "java.lang.Class"; 2160 if (putAlias(clazz, name, false, indent)) { 2162 printOpenTag(tag, indent, true); if (name!=null) 2165 printAttr(NAME_TOKEN, name); 2166 printAttr(CLASSNAME_TOKEN, clazz.getName()); 2169 out.print("/>"); toOutPrintln(); removeAlias(clazz); 2172 } 2173 } 2174 2175 2176 2181 2190 static Method getDeclaredMethod(Class clazz, 2192 String methodName, Class [] args, 2193 int requiredModifierMask, 2194 int disallowedModifierMask) { 2195 Method method = null; 2196 try { 2197 method = 2198 clazz.getDeclaredMethod(methodName, args); 2199 if (method != null) { 2200 int mods = method.getModifiers(); 2201 if ((mods & disallowedModifierMask) != 0 || 2202 (mods & requiredModifierMask) != requiredModifierMask) { 2203 method = null; 2204 } else { 2205 method.setAccessible(true); } 2207 } 2208 } catch (NoSuchMethodException e) { 2209 } 2212 return method; 2213 } 2214 2215 2227 2228 2229 2236 private void invokeObjectWriter(Method m, Object obj) throws IOException { 2237 try { 2238 m.invoke(obj, writeObjectArglist); 2239 } catch (InvocationTargetException e) { 2240 Throwable t = e.getTargetException(); 2241 if (t instanceof IOException) 2242 throw (IOException)t; 2243 else if (t instanceof RuntimeException ) 2244 throw (RuntimeException ) t; 2245 else if (t instanceof Error ) 2246 throw (Error ) t; 2247 else 2248 throw new Error ("internal error"); 2249 } catch (IllegalAccessException e) { 2250 2255 throw new InternalError ("Unable to access writeObject method"); 2256 } 2257 } 2258 2259 2263 private boolean formatted = true; 2266 2270 private String spacer = SPACER; 2274 2278 public void setFormatted(boolean formatted) { 2279 this.formatted = formatted; 2280 spacer = (formatted?SPACER:""); 2281 } 2282 2283 2286 private void toOutPrint(String s) { 2287 out.print(s); 2288 } 2289 2292 private void toOutPrintln() { 2293 if (formatted) 2294 out.println(); 2295 } 2296 2299 private void toOutPrintln(String s) { 2300 if (formatted) 2301 out.println(s); 2302 else 2303 out.print(s); 2304 } 2305} 2306
| Popular Tags
|