KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > JSX > ObjIn


1 /** (c) Brendan Macmillan 2001, licensed under GNU's GPL 2
2         (If your project is not GPL, then a fee is due - see license on website)
3     Website: http://www.csse.monash.edu.au/~bren/JSX
4     Website: http://freshmeat.net/projects/jsx
5     List (can read without subscribing, need to join to post):
6       http://groups.yahoo.com/group/JSX-ideas/messages
7         Commercial licensing enquiries only:
8             bren@mail.csse.monash.edu.au */

9
10
11 /** ===========================================================================
12     * ObjIn - (could be called XMLObjectInputStream)
13     * =====
14     * Input/deserialization.
15     * Class-specific readObject() and writeObject() serialization.
16     * USAGE:
17     * java JSX.ObjIn < test.xml
18     *
19     * There are many possible calls to the Serialization API; but they are
20     * all callbacks, from within readObject(), and so in a sense are invisible.
21     **/

22
23 //package ObjOutDev;
24
package JSX;
25 //import JSX.*; //use this, not "package", if truly a "wrapper"
26
import java.io.*; //Stream
27

28 public class ObjIn extends ObjectInputStream {
29     //static final boolean DEBUG = false;
30
static final boolean DEBUG = true;
31
32     static final boolean TRACE = false;
33     //static final boolean TRACE = true;
34

35     static final boolean NONSTREAM = false;
36     //static final boolean NONSTREAM = true;
37

38     public static ClassLoader JavaDoc cl = null;
39
40
41     /** ==========================================================================
42         * CONSTRUCTORS
43         * ============
44         **/

45     /** -------------------------------------------------------------------------
46         * ObjIn(in) - core constructor (others call it).
47         * ------
48         **/

49     final private ValidationList vlist = new ValidationList();
50     private XMLDeserialize d;
51     private Config config; //we keep a reference to it, as well as XMLDeserialize
52
public ObjIn(Reader in) throws IOException {
53         super(); //sets flag, so readObject() defers to readObjectOverride()
54
d = new XMLDeserialize(in);
55         d.setArg(new Object JavaDoc[] {this});
56             //d.readObjectArglist = new Object[] {this};
57
if (TRACE) System.err.println("ObjIn(inReader)");
58     }
59
60     public ObjIn(Reader in, Config cfg) throws IOException {
61         super(); //sets flag, so readObject() defers to readObjectOverride()
62
config = cfg; //for resolveClass
63
if (cfg.importFile!=null) {
64             try {
65                 XSLTimportI xsltImport = (XSLTimportI) Class.forName("JSX.XSLTimport").newInstance();
66                     //need an instance to invoke method (even tho it's a static method)
67
in = xsltImport.preprocess(in, cfg); //chain ahead
68
} catch (ClassNotFoundException JavaDoc noXSLTimport) {
69                 throw new IOException(noXSLTimport.toString()); //poor man's wrapping
70
} catch (InstantiationException JavaDoc cannotConstruct) {
71                 throw new IOException(cannotConstruct.toString());
72             } catch (IllegalAccessException JavaDoc cannotAccess) {
73                 throw new IOException(cannotAccess.toString());
74             }
75         }
76         d = new XMLDeserialize(in, cfg);
77         d.setArg(new Object JavaDoc[] {this}); //why not send this in via the constructor?
78
//d.readObjectArglist = new Object[] {this};
79
if (TRACE) System.err.println("ObjIn(inReader)");
80     }
81
82     /** -------------------------------------------------------------------------
83         * ObjIn(in)
84         * ------
85         * Convenience: wraps as a Reader.
86         **/

87     public ObjIn(InputStream in) throws IOException { //concession to convenience
88
this((Reader)new InputStreamReader(in));
89         if (TRACE) System.err.println("ObjIn(in)");
90     }
91     public ObjIn(InputStream in, Config cfg) throws IOException {
92         this((Reader)new InputStreamReader(in), cfg);
93         if (TRACE) System.err.println("ObjIn(in)");
94     }
95
96     /** -------------------------------------------------------------------------
97         * ObjIn()
98         * ------
99         * Default to System.in (so can redirect files in etc).
100         * Incidentally: SecurityException is RunTime, so needn't explicitly throw.
101         **/

102     public ObjIn() throws IOException, SecurityException JavaDoc {
103         this(System.in); //default
104
if (TRACE) System.err.println("ObjIn()");
105     }
106
107     public ObjIn(Config cfg) throws IOException, SecurityException JavaDoc {
108         this(System.in, cfg); //default
109
if (TRACE) System.err.println("ObjIn()");
110     }
111
112
113     /** ==========================================================================
114         * METHODS
115         * =======
116         **/

117     /** -------------------------------------------------------------------------
118         * reset()
119         * -------
120         * To reset alias table, mainly.
121         * Not needed: resets automatically upon each new invocation.
122         * Consider: option to change this when common objects are repeatedly
123         * messaged.
124         * Question: is this in OIS API?
125         **/

126     public void reset() { d.reset(); } //for aliases
127
public void close() {
128         d.close(); // should clear aliases, too
129
// vlist.clear(); //already clear on our model, if doCallbacks called...
130
}
131
132     /** -------------------------------------------------------------------------
133         * readObjectOverride() -- different arg/return form output version
134         * --------------------
135         * The heart. ObjectInputStream.readObject() defers to this, if flag set.
136         * Consider: only IOException should be thrown.
137         **/

138 //maybe should make a general loader for this stuff? Eg MagicClass routines?
139

140 // Comment out, because we do in Java now
141
/*
142     static Object vlist;
143     static {
144         try {
145             Class validClass = Class.forName("java.io.ObjectInputStream$ValidationList");
146                 // vlist = magicClass.newInstance(validClass); //create it
147             java.lang.reflect.Constructor cons = validClass.getDeclaredConstructor(new Class[0]);
148             cons.setAccessible(true);
149             vlist = cons.newInstance(new Object[0]);
150         } catch (Exception e) {
151             //e.printStackTrace(); // SILENT, simply means "not 1.4"
152         }
153     }
154 */

155
156 // Comment out old doValidation, because now we do it all in Java.
157
/*
158     static java.lang.reflect.Method doValidationsMethod;
159     static { //class initializer
160         if (vlist!=null) { //should be 1.4... should move to MagicClass
161             try { //1.4 - also expect vlist to be non-null
162                 doValidationsMethod = vlist.getClass().getDeclaredMethod("doCallbacks", new Class[]{});
163             } catch (NoSuchMethodException ee) { // means "not 1.3 either"
164                 ee.printStackTrace(); //fail silently
165                 System.err.println("Couldn't invoke doCallbacks");
166             }
167         }
168
169         if (doValidationsMethod==null) { //so, it wasn't 1.4... let's try 1.3
170             try { //1.3
171                 doValidationsMethod = java.io.ObjectInputStream.class.getDeclaredMethod("doValidations", new Class[]{});
172             } catch (NoSuchMethodException e) {
173                 e.printStackTrace(); //fail silently
174                     // hyp: this was printed for Alex in j9
175                 System.err.println("--- J9? Unable to set-up doValidationMethod ---");
176             }
177         }
178
179         if (doValidationsMethod!=null) { // if we couldn't find it (eg j9)
180             doValidationsMethod.setAccessible(true);
181                 // before if, this caused a NullPointerException for Alex in j9
182         } else {
183             System.err.println("--- J9? Unable to set-up doValidationMethod ---");
184         }
185     }
186 */

187
188     protected Object JavaDoc readObjectOverride() throws OptionalDataException,
189                                                ClassNotFoundException JavaDoc,
190                                                IOException {
191         try {
192             if (!d.superVersion) { //only for non-super version
193
if (d.invocationCount>0) //ie if already inside
194
defaultReadObject(); //false = don't read in fields hmmmm....????
195
}
196             if (TRACE) System.err.println("readObjectOverride()");
197             Object JavaDoc o = null;
198             o = d.deserialize(); // if an error thrown from here, still need to clear
199
if (TRACE) System.err.println("Object returned:" + o);
200     
201             if (d.invocationCount==0) //only if *not* inside (ie if really finished)
202
vlist.doCallbacks(); // clears list - JOS keeps open, in case more
203
/*
204             try { //only at *very* end - not in a nested readObject call?
205                 recursionDepthField.setInt(this, 0); //just a hack, to use superclass
206                 if (vlist==null) //1.3
207                     doValidationsMethod.invoke(this, new Object[]{}); //and that's it!
208                 else
209                     doValidationsMethod.invoke(vlist, new Object[]{}); //and that's it!
210                 //} catch (java.io.NotActiveException notOn) {
211                 // notOn.printStackTrace();
212                 //fail silently for 1.4 tests at the moment, for Shine Lu
213             } catch (IllegalAccessException e) {
214                 e.printStackTrace();
215             } catch (IllegalArgumentException e) {
216                 e.printStackTrace();
217             } catch (java.lang.reflect.InvocationTargetException e) {
218                 e.printStackTrace();
219             //see java pattern for this (from ObjectInputStream... should make it
220             //into a utility method)
221             } catch (NullPointerException e) {
222                 e.printStackTrace(); //fail silently
223                 System.err.println("attempt to doValidationsMethod.invoke()");
224             }
225 */

226             return o;
227         } finally {
228             vlist.clear(); // odd: JOS keeps priorities open between streams...
229
}
230     }
231
232     /** -------------------------------------------------------------------------
233         * defaultReadObject()
234         * -----------------
235         * Not implemented: presently, default stuff is written anyway.
236         **/

237     public void defaultReadObject() throws IOException, ClassNotFoundException JavaDoc {
238         if (TRACE) System.err.println("defaultReadObject()");
239         //This does nothing!!
240
//What if a class *depends* on these values *not* being read in?
241
//Can we simulate the effect by not writing if defaultWriteObject() not
242
//called? That would help!! Classes then *shouldn't* create this problem!
243

244         d.defaultReadObject(); //forward it.
245
}
246
247     public void readFully(byte[] dst) throws
248     // ClassNotFoundException,
249
IOException {
250             //the "fully" is to do with blocking, not the array being full
251

252         byte[] src = null;
253         try {
254             src = (byte[]) readObject();
255         } catch (ClassNotFoundException JavaDoc e) {
256             //it would be pretty serious if "byte[].class" could not be found!
257
//This could happen if some other class...
258
throw new IOException("Reading for a byte[]; but: "+e); //rethrow corked
259
}
260          //byte[] src = (byte[]) readObjectOverride(); //so needn't catch exception
261
System.arraycopy(src, 0, dst, 0, src.length); //err if dst too short
262
//this is the odd thing you have to do in Java, to return by reference.
263
//it would be nice if we could point the dst at the src instead...
264
//probably *can* do this with the private native trick... ;-)
265
}
266
267
268     /** -------------------------------------------------------------------------
269         * internalDefaultReadObject()
270         * -----------------
271         * Re-throws ClassNotFound as ClassNotFoundInDefault. This subclasses
272         * IOException, to fit the sig of readInt etc. JSX requires this hack
273         * because of the funny way it uses defaultReadObject to set up the
274         * custom fields.
275         **/

276     void internalDefaultReadObject() throws IOException { //for readInt etc
277
if (d.superVersion) //not needed for superVersion
278
return; //ineff to factored out here, but in one place
279
try {
280             d.defaultReadObject(); //forward it.
281
} catch (ClassNotFoundException JavaDoc e) {
282             throw new ClassNotFoundInDefaultException(e.getMessage());
283         }
284     }
285     class ClassNotFoundInDefaultException extends IOException {
286         ClassNotFoundInDefaultException(String JavaDoc msg) { super(msg); }
287     }
288
289     public int readInt() throws IOException {
290         internalDefaultReadObject(); //false = don't read in fields
291
return Integer.parseInt(d.getPrimString());
292     }
293     public float readFloat() throws IOException {
294         internalDefaultReadObject(); //false = don't read in fields
295
//return Float.parseFloat(d.getPrimString());
296
return ParseUtilities.parseFloat(d.getPrimString());
297     }
298         //we are stricter than Java's own parse of Boolean...
299
//(Suggest: This could go into ParseUtilities)
300
public boolean readBoolean() throws IOException {
301         internalDefaultReadObject(); //false = don't read in fields
302
return ParseUtilities.parseBoolean(d.getPrimString());
303     }
304     public byte readByte() throws IOException {
305         internalDefaultReadObject(); //false = don't read in fields
306
return Byte.parseByte(d.getPrimString());
307     }
308     public char readChar() throws IOException {
309         internalDefaultReadObject(); //false = don't read in fields
310
//XML...
311
return (char) Integer.parseInt(d.getPrimString());
312         //return d.getPrimString().charAt(0);
313
//return ParseUtilities.decodeXML(d.getPrimString());
314
}
315     public double readDouble() throws IOException {
316         internalDefaultReadObject(); //false = don't read in fields
317
//return Double.parseDouble(d.getPrimString());
318
return ParseUtilities.parseDouble(d.getPrimString());
319     }
320     //Float - see above
321
//Int - see above
322
public short readShort() throws IOException {
323         internalDefaultReadObject(); //false = don't read in fields
324
return Short.parseShort(d.getPrimString());
325     }
326         //Also thanks to Andy Thomas - odd that both were left out!
327
public long readLong() throws IOException {
328         internalDefaultReadObject(); //false = don't read in fields
329
return Long.parseLong(d.getPrimString());
330     }
331
332 /* deprecated in java.io.ObjectInputStream
333     public String readLine() throws IOException {
334         System.err.println("readLine() not implemented");
335         return null;
336     }
337 */

338     public String JavaDoc readUTF() throws IOException {
339         internalDefaultReadObject(); //false = don't read in fields
340
//System.err.println("getPrimString() is correct, not readObject()");
341
return d.getPrimString();
342 /*
343         try {
344             return (String) readObject(); //if it's not String, then an error!
345         } catch (ClassNotFoundException e) {
346             e.printStackTrace(); //shouldn't be needed: it should be a String.
347         }
348         return null;
349 */

350     }
351
352     /** --------------------------------------------------------------------------
353         * Non-stream API
354         * --------------
355         * This is for stuff that is not actually reading (or writing, for ObjOut).
356         * Eg: validation
357         **/

358
359 /** registerValidation: we simply let this fall through to the superclass
360     * implementation. All we need do is call "doValidation()" when the entire
361     * object graph is done.
362     * (1). Where do we put it, so we know when it is done?
363     * (2). How do we call it with reflection?
364     */

365 // Comment out, and do it in Java now
366
/*
367     static java.lang.reflect.Field recursionDepthField;
368     static { //class initializer
369         try { //should do in MagicClass; or dup code myself
370             recursionDepthField = java.io.ObjectInputStream.class.getDeclaredField("depth");
371         } catch (NoSuchFieldException e) {
372             //e.printStackTrace(); //SILENT 1.4 fail: it expects a "depth" field
373             try {
374                 recursionDepthField = java.io.ObjectInputStream.class.getDeclaredField("recursionDepth");
375             } catch (NoSuchFieldException ee) {
376                 ee.printStackTrace(); //1.3 fail: it expects a "recursionDepth" field
377             }
378         }
379         recursionDepthField.setAccessible(true);
380     }
381
382     { //instance initializer - need an instance of field, to set it
383         try {
384             recursionDepthField.setInt(this, 1); //just a hack, to use superclass
385         } catch (IllegalAccessException e) {
386             e.printStackTrace();
387         } catch (NullPointerException e) {
388             //e.printStackTrace(); //fail silently
389         }
390     }
391 */

392
393
394     public void registerValidation(ObjectInputValidation obj, int prio) throws InvalidObjectException, NotActiveException {
395         //throw new RuntimeException("registerValidation() invoked - not implemented");
396
if (d.invocationCount==0) //ie not active
397
throw new NotActiveException("JSX.ObjIn: readObject not Active");
398         vlist.register(obj, prio);
399
400 /*
401         else {
402             try {
403                 try { //1.4 - better to detect, and do within MagicClass - or dup self
404                     JSX.magic.MagicClassI magicClass = JSX.magic.MagicClassFactory.newInstance();
405
406
407                     java.lang.reflect.Field f = java.io.ObjectInputStream.class.getDeclaredField("vlist");
408                     magicClass.setObjectFieldValue(this, f, f.getType(), vlist);
409                 } catch (Exception problem) {
410                     //problem.printStackTrace(); //SILENT means not 1.4
411                 }
412                 super.registerValidation(obj, prio); //forward it
413             } catch (java.io.NotActiveException notOn) {
414                     //sh fail silently for 1.4 tests at the moment, for Shine Lu
415                 throw new InternalError("Stream not active");
416             }
417         }
418 */

419     }
420
421
422     protected Class JavaDoc resolveClass(ObjectStreamClass v) throws IOException, ClassNotFoundException JavaDoc {
423             //return Class.forName(v.getName(), true, this.getClass().getClassLoader()); //Wolf test: same as forName(name)
424
//return Class.forName(v.getName(), false, cl);
425
String JavaDoc classname = v.getName();
426         if (config!=null && config.refactor!=null)
427             classname = config.refactor.mapClassname(classname);
428         Class JavaDoc clazz = null;
429         try {
430             //clazz = Class.forName(v.getName()); //this *would* solve Wolf's problem
431
clazz=Thread.currentThread().getContextClassLoader().loadClass(classname); //this brilliant bug-fix courtesy Ing Thomas Margreiter, 13 June 2002
432

433         } catch (ClassNotFoundException JavaDoc e) {
434             throw new ClassNotFoundException JavaDoc("forName(\""+v.getName()+"\") didn't find the class. Please report this problem. Wrapped: "+e.getMessage());
435             //Will it work, in general? We'll see...
436
//clazz = super.resolveClass(v); //best: but latestUserDefinedLoader...
437
}
438         return clazz;
439     }
440
441     protected Object JavaDoc resolveObject(Object JavaDoc obj) {
442         throw new RuntimeException JavaDoc("resolveObject() invoked - not implemented");
443     // return null;
444
}
445     public int skipBytes(int len) {
446         throw new RuntimeException JavaDoc("skipBytes() invoked - not implemented");
447     // return 0;
448
}
449
450 /** communicate with XMLDeserilize */
451     public ObjectInputStream.GetField readFields() throws
452             IOException,
453             ClassNotFoundException JavaDoc {
454         defaultReadObject(); //false = don't read in fields
455
if (TRACE) System.err.println("in.readFields(); invoked - about to return");
456         return (GetField)d.getCurrentGetField();
457             // we could even send in "d", to get the current class, instead of
458
// making it non-static
459
}
460  
461
462
463     /** ==========================================================================
464         * TEST CODE
465         * =========
466         **/

467     public static void main(String JavaDoc[] args) throws Exception JavaDoc {
468         
469         InputStream fin = System.in;
470         if (args.length!=0) { //a filename
471
fin = new FileInputStream(args[0]);
472         }
473 /*
474     Config cfg = new Config().setFormatted(true).setNoSuchFieldHandler(
475       new NoSuchFieldHandler() {
476         public String noSuchField(Class c, String fieldName) {
477           System.err.println("--------wanting to map field "+fieldName);
478           return fieldName.substring(1);
479         }
480       });
481     cfg.setNoSuchFieldHandler(new NoSuchFieldHandler()); //default, so gives
482 */

483
484     Config c = new Config().setFormatted(true).aliasID(false); // turn aliases off for eg
485
//Config cfg = new Config().setFormatted(true).superVersion(true);
486

487         //errors
488

489         ObjIn in = new ObjIn(fin, c);
490         //ObjIn in = new ObjIn(fin);
491
//Config cfg2 = new Config().superVersion(true);
492
//Config cfg2 = new Config().superVersion(false);
493
//ObjOut out = new ObjOut(cfg2);
494
ObjOut out = new ObjOut(c);
495         Object JavaDoc o;
496             //What if the object returned *is* null?
497
while (true) {
498             try {
499                 o = in.readObject();
500                 if (DEBUG) { //sep debug info from deserialization and serialization
501
System.err.println();
502                     System.err.println("Finished reading--------");
503                     System.err.println();
504                 }
505                 out.writeObject(o);
506                 out.flush();
507                 //NB: The Config object should work as an extension to the object,
508
//that does not work through inheritance (and thus has a different
509
//namespace).
510

511                 if (DEBUG)
512                     System.err.println("Finished writing--------");
513             } catch (EOFException e) { //simply end of file.
514
break;
515             } catch (Exception JavaDoc e) {
516                 System.err.println(e);
517                 e.printStackTrace();
518                 continue;
519             }
520         }
521         out.close();
522         in.close();
523         System.exit(0); //in case one of the deserialized objects started a thread
524
}
525 }
526
Popular Tags