KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > JSX > ObjOut


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     * ObjOut - (could be called XMLObjectOutputStream)
13     * ======
14     * Output/serialization.
15     * There are many possible calls to the Serialization API; but they are
16     * all callbacks, from within writeObject(), and so in a sense are invisible.
17     **/

18
19 package JSX;
20 //package ObjOutDev;
21
//import JSX.*; //use this, not package, if trully a "wrapper"
22
import java.io.*; //Stream
23
import java.util.*; //Vector eg
24

25 public class ObjOut extends ObjectOutputStream {
26     final boolean DEBUG = false;
27     //final boolean DEBUG = true;
28

29     XMLSerialize s; //new, for thread-safe version
30
//package, so can extract from within PutField...
31
public ObjOut(PrintWriter out) throws IOException {
32         super();
33         s = new XMLSerialize(out);
34             //this.out = out; //now maintained within XMLSerialize
35
s.setArg(new Object JavaDoc[] {this}); //call-back (best: all in one)
36
}
37     public ObjOut(PrintWriter out, Config cfg) throws IOException {
38         super();
39         s = new XMLSerialize(out, cfg);
40             //this.out = out; //now maintained within XMLSerialize
41
s.setArg(new Object JavaDoc[] {this}); //call-back (best: all in one)
42
}
43
44 //replaced OutputStreamWriter with Writer (suggested by /lim/)
45
public ObjOut(Writer out) throws IOException {
46         this(new PrintWriter(out, true)); //so don't need to close it...
47
}
48     public ObjOut(Writer out, boolean autoFlush) throws IOException {
49         this(new PrintWriter(out, autoFlush));
50     }
51     public ObjOut(Writer out, boolean autoFlush, Config cfg) throws IOException {
52         this(new PrintWriter(out, autoFlush), cfg);
53     }
54     public ObjOut(boolean areAliasesUsed, Writer out) throws IOException { //links to above
55
this(out, true); //autoFlush by defualt, nice for demo
56
s.areAliasesUsed = areAliasesUsed;
57     }
58     public ObjOut(boolean areAliasesUsed, Writer out, Config cfg) throws IOException { //links to above
59
this(out, true, cfg); //autoFlush by defualt, nice for demo
60
s.areAliasesUsed = areAliasesUsed;
61     }
62
63     public ObjOut(OutputStream out, boolean autoFlush) throws IOException {
64         this(new OutputStreamWriter(out), autoFlush); //pass on autoFlush switch
65
}
66     public ObjOut(OutputStream out, boolean autoFlush, Config cfg) throws IOException {
67         this(new OutputStreamWriter(out), autoFlush, cfg); //pass on autoFlush switch
68
}
69
70         //to avoid conflict of sig with above. Need to rationalize this con API!
71
public ObjOut(boolean areAliasesUsed, OutputStream out) throws IOException { //links to above...
72
this(out, true); //autoFlush by default
73
s.areAliasesUsed = areAliasesUsed;
74     }
75     public ObjOut(OutputStream out) throws IOException { //links to above...
76
this(out, true); //autoFlush by default
77
}
78     public ObjOut(OutputStream out, Config cfg) throws IOException { //links to above...
79
this(out, true, cfg); //autoFlush by default
80
}
81     //private boolean areAliasesUsed=true; //default "on"; set in constructor
82

83
84     //protected ObjOut() throws IOException, SecurityException {
85
public ObjOut(boolean areAliasesUsed) throws IOException, SecurityException JavaDoc {
86         this(System.out); //NB: of class "OutputStream"
87
s.areAliasesUsed = areAliasesUsed;
88     }
89     public ObjOut(boolean areAliasesUsed, Config cfg) throws IOException, SecurityException JavaDoc {
90         this(System.out, cfg); //NB: of class "OutputStream"
91
s.areAliasesUsed = areAliasesUsed;
92     }
93
94     public ObjOut() throws IOException, SecurityException JavaDoc {
95         this(System.out); //NB: of class "OutputStream"
96
}
97     public ObjOut(Config cfg) throws IOException, SecurityException JavaDoc {
98         this(System.out, cfg); //NB: of class "OutputStream"
99
}
100
101
102
103 /* ObjectOutputStream API */
104     public void reset() { s.reset(); }
105     public void flush() { s.flush(); }
106     public void close() { s.close(); }
107
108     protected void writeObjectOverride(Object JavaDoc obj) throws IOException {
109         //s.serialize(obj);
110
if (DEBUG) System.err.println("writeObject: " +obj);
111         s.serialize(obj); //fine; wrapper APIs must dup a little
112
s.flush();
113         //we flush automatically for when one whole object graph is
114
//written; but it *might* not be what users want for multiple objects...
115
//We could just implement it, and add a switch if people complain.
116
}
117         //NB: *must* override, or OOS's version is called
118
public void defaultWriteObject() throws IOException {
119         if (DEBUG) System.err.println("defaultWriteObject() - need to pass in");
120         s.defaultWriteObject(); //just "return" a flag
121
}
122
123 /**
124     * PutField support (for symbolic evolution of objects)
125     * --------
126     * Q: why isn't PutField an interface? It an abstract class because (at one
127     * time) it had a public constructor?
128     **/

129     PutField currentPutField = null; //NOT ACCOUNT FOR NESTED FIELDS - needed?
130
//Imagine two objects in the PutField. First one has writeObject which
131
//is called, which uses PutField, thus replacing currentPutField...
132
//does JOS suffer from this problem?
133
//It would seem to - it is implemented same as here (but "currentPutFields")
134

135     public PutField putFields() {
136         if (currentPutField!=null) { //a fake check for stack overflow
137
if (DEBUG) System.err.println("about to overwrite the currentPutField... need a stack");
138             //Because the object is called, the *field* holding it is free; and we
139
//don't need to stack. It is because we actually *call* the object - I
140
//guess this puts all its data on the stack, too... ;-)");
141

142         }
143                 // use "new this.s.PutFieldImpl()" so non-static & can access outer
144
return currentPutField = this.s.new PutFieldImpl();//a fake "push"
145
//will need to stack this - how does JOS do it?
146
}
147     public void writeFields() throws IOException { //redundant: also do PutField.write(OOS);
148
currentPutField.write(this); //need a stack (for nested PutFields)
149
//in a proper implementation, this would write out the object,
150
//and invoke its readObject(), which could create a new a OutField
151
//object, displacing the "currentPutFields" field... need to use a stack
152

153         currentPutField = null; //a fake "pop"
154
if (DEBUG) System.err.println("writeFields() fields and values buffered.");
155     }
156
157
158     public void write(byte[] b) throws IOException {
159         writeObject(b); //handle it as an object (why not?)
160
}
161 /** don't use this! Meant to be efficient, but horrifically ineff! ;-) **/
162     public void write(byte[] b, int off, int len) throws IOException {
163         byte[] b2 = new byte[len];
164         System.arraycopy(b, off, b2, 0, len);
165         writeObject(b2); //handle it as an object (why not?)
166
}
167     public void write(int b) throws IOException { // was missed, until 8Oct2002
168
s.writePrim(b+"");
169     }
170     public void writeInt(int data) throws IOException {
171         s.writePrim(data+"");
172     }
173     public void writeFloat(float data) throws IOException {
174         s.writePrim(data+"");
175     }
176     public void writeBoolean(boolean data) throws IOException {
177         s.writePrim(data+"");
178     }
179     public void writeByte(int data) throws IOException {
180         s.writePrim(data+"");
181     }
182     public void writeBytes(String JavaDoc data) throws IOException {
183         //System.err.println("Should this be written as an object (so alias is used?)");
184
//The above comment has never been reported
185
writeObject(data); //handle it as an object (why not?)
186
}
187     public void writeChar(int data) throws IOException { //"int" matches OOS sig
188
s.writePrim(data+""); //Writes out as a decimal number
189
//s.writePrim(ParseUtilities.encodeXML( ((char)data)+"");
190
//s.writePrim(((char)data)+""); //Excellent bug diagnosis by Teck Hooi!
191
//easier for back-compatibility, to simply write a char as a number,
192
//instead of the complex escaping.
193
//The problem is the XML issue of representing the null (char) 0 and
194
//control characters.
195
}
196     public void writeChars(String JavaDoc data) throws IOException {
197         System.err.println("writeChars() is not properly implemented");
198         //System.err.println("Should this be written as an object (so alias is used?)");
199
writeObject(data); //handle it as an object (why not?)
200
// write with or without aliases? How to tell?
201
}
202     public void writeDouble(double data) throws IOException {
203         s.writePrim(data+"");
204     }
205     //Float - see above
206
//Int - see above
207
//writeLong() is thanks Andy Thomas (who found Date didn't work).
208
//He's the first successful JSX Challenger. Wed, 10 Jan 2001 22:33:57 +0000
209
//James Skinnell found it, too (through java.sql.Timestamp not working).
210
//He's the second successful JSX Challenger. Thu Jan 11 08:06:28 2001
211
public void writeLong(long data) throws IOException {
212         s.writePrim(data+"");
213     }
214     public void writeShort(int data) throws IOException { //"int" matches OOS
215
s.writePrim(data+"");
216     }
217         /**
218             * writeUTF(str)
219             * ------------
220             * writeUTF specifies the data format, which is not relevant to us, as
221             * we use an XML format. However, it does have the side-effect of
222             * treating a String 100% as a primitive, in the sense that there is
223             * no aliasing (confirmed with Java's own Serialization: "java TestSuite e"
224             **/

225     public void writeUTF(String JavaDoc data) throws IOException {
226     //System.err.println("writePrim() is correct, not writeObject()");
227
s.writePrim(data+"");
228 /*
229         writeObject(data); //handle it as an object (why not?)
230 */

231     }
232     static class Non_method_innerclassTest {}
233     
234     
235     /**
236         * setFormatted(boolean)
237         * -----------------
238         * Turns XML Output formatting on or off..
239         * Formatted XML is spaced and indented
240         * Non-formatted XML is contained without indentation or whitespaces between
241         * tags, or any CR/LF
242         * Added by Gil
243         **/

244     public void setFormatted(boolean formatted) {
245     s.setFormatted(formatted);
246     }
247     
248
249     public static void main(String JavaDoc[] args) throws Exception JavaDoc {
250         Config c = new Config().aliasID(false); // turn aliases off for eg
251
ObjOut out = new ObjOut(c);
252         Object JavaDoc obj;
253         if (args.length>0) {
254             Class JavaDoc clazz = Class.forName(args[0]);
255             // invoke no-arg constructor
256
// was: obj = clazz.newInstance();
257
java.lang.reflect.Constructor JavaDoc cons = clazz.getDeclaredConstructor(new Class JavaDoc[] {});
258             cons.setAccessible(true); // necessary
259
obj = cons.newInstance(new Object JavaDoc[] {}); // exceptions at main()
260
} else {
261             obj = new MyTyreClass("wheels on my car",
262                 new Wheel("Michelin", new MyDate(31,10,1997)),
263                 new Wheel("Michelin", new MyDate(31,10,1997)),
264                 new Wheel("Michelin", new MyDate(2,3,1999)),
265                 new Wheel("Michelin", new MyDate(14,9,2000))
266             );
267         }
268 /*
269             obj = new java.util.Hashtable();
270             ((Hashtable)obj).put("a", "alpha");
271             ((Hashtable)obj).put("b", "beta");
272             ((Hashtable)obj).put("g", "gamma");
273 */

274         out.writeObject(obj); //so simple to use!
275
}
276 }
277
Popular Tags