KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > upgrade > systemoptions > SerParser


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.upgrade.systemoptions;
21
22 import java.io.*;
23 import java.util.*;
24 import org.openide.util.NotImplementedException;
25
26 /* The following may be useful to Emacs users:
27
28 (defun comma-sep-decimal-encode ()
29   (interactive)
30   (while
31       (let ((p (point)))
32         (and (re-search-forward "\\(-?[0-9][0-9]?[0-9]?\\),?" nil t)
33              (= p (match-beginning 0))))
34     (replace-match (char-to-string
35                     (let ((x (string-to-int (match-string 1))))
36                       (when (< x 0) (setq x (+ x 256)))
37                       x))
38                    t t)))
39
40 After evaluating this, go into an old cpanel.xml or similar
41 (M-x find-file-literally, by the way) and type
42 M-x comma-sep-decimal-encode right after the opening quote
43 of the value. The contents will be converted to raw binary and
44 may be saved as a .ser file parsable by this class.
45
46 (defun hex-encode ()
47   (interactive)
48   (while
49       (let ((p (point)))
50         (and (re-search-forward "\\s-*\\([a-fA-F0-9][a-fA-F0-9]\\)" nil t)
51              (= p (match-beginning 0))))
52     (replace-match (char-to-string
53                     (string-to-int (match-string 1) 16))
54                    t t)))
55
56 Same for hexadecimal serialized data. For .settings files, it is
57 easier to select Customize Bean... in the IDE and save as *.ser.
58 */

59
60 /** Parser for Java serialization files.
61  * Does no classloading or per-class semantics, simply parses the
62  * raw serialization structure.
63  * @author Jesse Glick
64  */

65 public final class SerParser implements ObjectStreamConstants {
66     
67     private static final boolean DEBUG = Boolean.getBoolean("org.netbeans.modules.clazz.SerParser.DEBUG"); // NOI18N
68

69     private final InputStream is;
70     private int seq = 0;
71     private final List<Object JavaDoc> refs = new ArrayList<Object JavaDoc>(100);
72     
73     public SerParser(InputStream is) {
74         this.is = is;
75     }
76     
77     private int makeRef(Object JavaDoc o) {
78         refs.add(o);
79         int i = seq;
80         seq++;
81         if (DEBUG) System.err.println("makeRef[" + i + "]=" + o); // NOI18N
82
return i;
83     }
84     
85     private Object JavaDoc getRef(int i) throws CorruptException {
86         int idx = i - baseWireHandle;
87         if (idx < 0 || idx >= seq) throw new CorruptException("Invalid reference: " + i); // NOI18N
88
Object JavaDoc o = refs.get(idx);
89         if (o == null) throw new CorruptException("Invalid reference: " + i); // NOI18N
90
return o;
91     }
92     
93     public Stream parse() throws IOException, CorruptException {
94         Stream s = new Stream();
95         s.magic = readShort();
96         s.version = readShort();
97         if (s.magic != STREAM_MAGIC || s.version != STREAM_VERSION) {
98            throw new CorruptException("stream version mismatch: " + hexify(s.magic) + " != " + hexify(STREAM_MAGIC) + " or " + hexify(s.version) + " != " + hexify(STREAM_VERSION)); // NOI18N
99
}
100         s.contents = new ArrayList<Object JavaDoc>(10);
101         while (peek() != -1) {
102             s.contents.add(readContent());
103         }
104         if (DEBUG) System.err.println("parsed: " + s); // NOI18N
105
return s;
106     }
107     
108     public static final class CorruptException extends IOException {
109         public CorruptException() {
110         }
111         public CorruptException(String JavaDoc m) {
112             super(m);
113         }
114     }
115     
116     private int pushback = -1;
117     private int rb() throws IOException {
118         if (pushback != -1) {
119             int c = pushback;
120             pushback = -1;
121             return c;
122         }
123         int c = is.read();
124         if (DEBUG) System.err.println("read: " + Integer.toHexString(c)); // NOI18N
125
if (c == -1) {
126             throw new EOFException();
127         } else {
128             return c;
129         }
130     }
131     private int peek() throws IOException {
132         if (pushback != -1) throw new IllegalStateException JavaDoc("can only peek once"); // NOI18N
133
pushback = is.read();
134         if (DEBUG) System.err.println("read: " + Integer.toHexString(pushback)); // NOI18N
135
return pushback;
136     }
137     
138     static String JavaDoc hexify(byte b) {
139         int i = b;
140         if (i < 0) i += 256;
141         String JavaDoc s = Integer.toHexString(i).toUpperCase(Locale.US);
142         return "0x" + pad(s, 2); // NOI18N
143
}
144     static String JavaDoc hexify(short s) {
145         int i = s;
146         if (i < 0) i += 65536;
147         String JavaDoc st = Integer.toHexString(i).toUpperCase(Locale.US);
148         return "0x" + pad(st, 4); // NOI18N
149
}
150     static String JavaDoc hexify(int i) {
151         String JavaDoc s = Integer.toHexString(i).toUpperCase(Locale.US);
152         return "0x" + pad(s, 4); // NOI18N
153
}
154     static String JavaDoc hexify(long l) {
155         String JavaDoc s1 = Integer.toHexString((int)((l & 0xFFFFFFFF00000000L) << 32)).toUpperCase(Locale.US);
156         String JavaDoc s2 = Integer.toHexString((int)(l & 0x00000000FFFFFFFFL)).toUpperCase(Locale.US);
157         return "0x" + pad(s1, 4) + pad(s2, 4); // NOI18N
158
}
159     static String JavaDoc hexify(byte[] b) {
160         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(2 + b.length * 2);
161         buf.append("0x"); // NOI18N
162
for (int i = 0; i < b.length; i++) {
163             int x = b[i];
164             if (x < 0) x += 256;
165             buf.append(pad(Integer.toHexString(x).toUpperCase(Locale.US), 2));
166         }
167         return buf.toString();
168     }
169     private static String JavaDoc pad(String JavaDoc s, int size) {
170         int i = s.length();
171         if (i == size) {
172             return s;
173         } else {
174             StringBuffer JavaDoc b = new StringBuffer JavaDoc(size);
175             for (int k = 0; k < size - i; k++) {
176                 b.append('0'); // NOI18N
177
}
178             b.append(s);
179             return b.toString();
180         }
181     }
182     
183     private long readLong() throws IOException {
184         long x1 = rb();
185         long x2 = rb();
186         long x3 = rb();
187         long x4 = rb();
188         long x5 = rb();
189         long x6 = rb();
190         long x7 = rb();
191         long x8 = rb();
192         long l = (x1 << 56) + (x2 << 48) + (x3 << 40) + (x4 << 32) + (x5 << 24) + (x6 << 16) + (x7 << 8) + x8;
193         if (DEBUG) System.err.println("readLong: " + l); // NOI18N
194
return l;
195     }
196     
197     private int readInt() throws IOException {
198         int x1 = rb();
199         int x2 = rb();
200         int x3 = rb();
201         int x4 = rb();
202         int i = (x1 << 24) + (x2 << 16) + (x3 << 8) + x4;
203         if (DEBUG) System.err.println("readInt: " + i); // NOI18N
204
return i;
205     }
206     
207     private short readShort() throws IOException {
208         int x1 = rb();
209         int x2 = rb();
210         short s = (short)((x1 << 8) + x2);
211         //System.err.println("x1=" + hexify(x1) + " x2=" + hexify(x2) + " s=" + hexify(s));
212
//if (DEBUG) System.err.println("x1=" + x1 + " x2=" + x2 + " s=" + s);
213
if (DEBUG) System.err.println("readShort: " + s); // NOI18N
214
return s;
215     }
216     
217     private byte readByte() throws IOException {
218         return (byte)rb();
219     }
220     
221     private String JavaDoc readUTF() throws IOException {
222         short len = readShort();
223         if (len < 0) throw new NotImplementedException();//XXX
224
byte[] buf = new byte[len];
225         for (int i = 0; i < len; i++) {
226             buf[i] = readByte();
227         }
228         String JavaDoc s = new String JavaDoc(buf, "UTF-8"); // NOI18N
229
if (DEBUG) System.err.println("readUTF: " + s); // NOI18N
230
return s;
231     }
232     
233     /*
234     private String readLongUTF() throws IOException {
235         long len = readLong();
236         if (len < 0) throw new NotImplementedException();//XXX
237         if (len > Integer.MAX_VALUE) throw new NotImplementedException();// XXX
238         int ilen = (int)len;
239         byte[] buf = new byte[ilen];
240         for (int i = 0; i < ilen; i++) {
241             buf[i] = readByte();
242         }
243         String s = new String(buf, "UTF-8"); // NOI18N
244         if (DEBUG) System.err.println("readUTF: " + s); // NOI18N
245         return s;
246     }
247      */

248     
249     // See "Rules of the Grammar" in Java Object Serialization Specification
250
// for explanation of all these objects.
251

252     public static final class Stream /*extends Thing*/ {
253         public short magic;
254         public short version;
255         public List<Object JavaDoc> contents;
256         public String JavaDoc toString() {
257             return "Stream[contents=" + contents + "]"; // NOI18N
258
}
259     }
260     
261     public static final Object JavaDoc NULL = "null"; // NOI18N
262

263     private Object JavaDoc readContent() throws IOException {
264         byte tc = readByte();
265         switch (tc) {
266         case TC_OBJECT:
267             return readNewObject();
268         case TC_CLASS:
269             return readNewClass();
270         case TC_ARRAY:
271             return readNewArray();
272         case TC_CLASSDESC:
273             return readNewClassDesc();
274         case TC_PROXYCLASSDESC:
275             // XXX too complicated:
276
throw new NotImplementedException("TC_PROXYCLASSDESC"); // NOI18N
277
//return readNewProxyClassDesc();
278
case TC_STRING:
279             return readNewString();
280         case TC_LONGSTRING:
281             // XXX later
282
throw new NotImplementedException("TC_LONGSTRING"); // NOI18N
283
//return readNewLongString();
284
case TC_REFERENCE:
285             return readReference();
286         case TC_NULL:
287             return NULL;
288         case TC_EXCEPTION:
289             // XXX what is this??
290
throw new NotImplementedException("TC_EXCEPTION"); // NOI18N
291
case TC_RESET:
292             // XXX what is this??
293
throw new NotImplementedException("TC_RESET"); // NOI18N
294
case TC_BLOCKDATA:
295             return readBlockData();
296         case TC_BLOCKDATALONG:
297             return readBlockDataLong();
298         default:
299             throw new CorruptException("Unknown typecode: " + hexify(tc)); // NOI18N
300
}
301     }
302     
303     public static final class ObjectWrapper {
304         public ClassDesc classdesc;
305         public List<Object JavaDoc> data; // <Union2<NameValue,Object>>
306
public String JavaDoc toString() {
307             return "Object[class=" + classdesc.name + ",data=<omitted>]"; // NOI18N
308
}
309     }
310     
311     public static final class NameValue {
312         public NameValue(FieldDesc name, Object JavaDoc value) {
313             this.name = name;
314             this.value = value;
315         }
316         public final FieldDesc name;
317         public final Object JavaDoc value;
318         public String JavaDoc toString() {
319             return name.toString() + "=" + value.toString(); // NOI18N
320
}
321     }
322     
323     public static final class ClassDesc {
324         public String JavaDoc name;
325         public long svuid;
326         public boolean writeMethod;
327         public boolean blockData;
328         public boolean serializable;
329         public boolean externalizable;
330         public List<FieldDesc> fields;
331         public List annotation; // List<Object>
332
public ClassDesc superclass;
333         public String JavaDoc toString() {
334             return "Class[name=" + name + "]"; // NOI18N
335
}
336     }
337     
338     private ObjectWrapper readNewObject() throws IOException {
339         ObjectWrapper ow = new ObjectWrapper();
340         ow.classdesc = readClassDesc();
341         makeRef(ow);
342         ow.data = new ArrayList<Object JavaDoc> (10);
343         LinkedList<ClassDesc> hier = new LinkedList<ClassDesc>();
344         for (ClassDesc cd = ow.classdesc; cd != null; cd = cd.superclass) {
345             hier.addFirst(cd);
346         }
347         for (ClassDesc cd: hier) {
348             if (cd.serializable) {
349                 ow.data.addAll(readNoWrClass(cd));
350                 if (cd.writeMethod) {
351                     ow.data.addAll(readContents());
352                 }
353             } else {
354                 if (cd.blockData) {
355                     ow.data.addAll(readContents());
356                 } else {
357                     // Old externalization. If this is not object content,
358
// the stream could now become corrupted. Oh well.
359
ow.data.add(readContent());
360                 }
361             }
362         }
363         if (DEBUG) System.err.println("readNewObject: " + ow); // NOI18N
364
return ow;
365     }
366     
367     private ClassDesc readClassDesc() throws IOException {
368         Object JavaDoc o = readContent();
369         if (o instanceof ClassDesc) {
370             return (ClassDesc)o;
371         } else if (o == NULL) {
372             return null;
373         } else {
374             throw new CorruptException("Expected class desc, got: " + o); // NOI18N
375
}
376     }
377     
378     private ClassDesc readNewClass() throws IOException {
379         ClassDesc cd = readClassDesc();
380         makeRef(cd);
381         return cd;
382     }
383     
384     private ClassDesc readNewClassDesc() throws IOException {
385         ClassDesc cd = new ClassDesc();
386         cd.name = readUTF();
387         if (! cd.name.startsWith("[") && // NOI18N
388
! (cd.name.length() == 1 && "BSIJFDCZ".indexOf(cd.name) != -1) && // NOI18N
389
! cd.name.endsWith(";")) { // NOI18N
390
// Canonicalize. It seems class names read normally need this; those
391
// read as part of an array do not. ??
392
cd.name = "L" + cd.name + ";"; // NOI18N
393
}
394         cd.svuid = readLong();
395         makeRef(cd);
396         byte cdf = readByte();
397         cd.writeMethod = (cdf & SC_WRITE_METHOD) != 0;
398         cd.blockData = (cdf & SC_BLOCK_DATA) != 0;
399         cd.serializable = (cdf & SC_SERIALIZABLE) != 0;
400         cd.externalizable = (cdf & SC_EXTERNALIZABLE) != 0;
401         short count = readShort();
402         cd.fields = new ArrayList<FieldDesc>(count);
403         for (int i = 0; i < count; i++) {
404             cd.fields.add(readFieldDesc());
405         }
406         cd.annotation = readContents();
407         cd.superclass = readClassDesc();
408         if (DEBUG) System.err.println("readNewClassDesc: " + cd); // NOI18N
409
return cd;
410     }
411     
412     public static class FieldDesc {
413         public String JavaDoc name;
414         public String JavaDoc type;
415         public String JavaDoc toString() {
416             return "Field[name=" + name + ",type=" + type + "]"; // NOI18N
417
}
418     }
419     public static final class ObjFieldDesc extends FieldDesc {
420         public boolean array;
421         public String JavaDoc toString() {
422             return "Field[name=" + name + ",type=" + type + (array ? "[]" : "") + "]"; // NOI18N
423
}
424     }
425     
426     private FieldDesc readFieldDesc() throws IOException {
427         char tc = (char)readByte();
428         FieldDesc fd;
429         switch (tc) {
430         case 'B':
431         case 'C':
432         case 'D':
433         case 'F':
434         case 'I':
435         case 'J':
436         case 'S':
437         case 'Z':
438             fd = new FieldDesc();
439             fd.type = new String JavaDoc(new char[] {tc});
440             break;
441         case '[':
442             fd = new ObjFieldDesc();
443             ((ObjFieldDesc)fd).array = true;
444             break;
445         case 'L':
446             fd = new ObjFieldDesc();
447             ((ObjFieldDesc)fd).array = false;
448             break;
449         default:
450             throw new CorruptException("Strange field type: " + tc); // NOI18N
451
}
452         fd.name = readUTF();
453         if (fd instanceof ObjFieldDesc) {
454             String JavaDoc clazz = (String JavaDoc)readContent();
455             /*
456             if (((ObjFieldDesc)fd).array) {
457                 if (! clazz.startsWith("[")) throw new CorruptException("Field type: " + clazz); // NOI18N
458                 clazz = clazz.substring(1, clazz.length());
459             }
460             if (! (clazz.startsWith("L") && clazz.endsWith(";"))) throw new CorruptException("Field type: " + clazz); // NOI18N
461             fd.type = clazz.substring(1, clazz.length() - 1).replace('/', '.'); // NOI18N
462              */

463             fd.type = clazz;
464         }
465         if (DEBUG) System.err.println("readFieldDesc: " + fd); // NOI18N
466
return fd;
467     }
468     
469     private List<Object JavaDoc> readContents() throws IOException {
470         List<Object JavaDoc> l = new ArrayList<Object JavaDoc>(10);
471         while (peek() != TC_ENDBLOCKDATA) {
472             l.add(readContent());
473         }
474         if (readByte() != TC_ENDBLOCKDATA) throw new IllegalStateException JavaDoc();
475         if (DEBUG) System.err.println("readContents: " + l); // NOI18N
476
return l;
477     }
478     
479     public static final class ArrayWrapper {
480         public ClassDesc classdesc;
481         public List<Object JavaDoc> values;
482         public String JavaDoc toString() {
483             return classdesc.name + "{" + values + "}"; // NOI18N
484
}
485     }
486     
487     private ArrayWrapper readNewArray() throws IOException {
488         ArrayWrapper aw = new ArrayWrapper();
489         aw.classdesc = readClassDesc();
490         makeRef(aw);
491         int size = readInt();
492         if (size < 0) throw new NotImplementedException();
493         aw.values = new ArrayList<Object JavaDoc>(size);
494         for (int i = 0; i < size; i++) {
495             if (aw.classdesc.name.equals("[B")) { // NOI18N
496
aw.values.add(new Byte JavaDoc(readByte()));
497             } else if (aw.classdesc.name.equals("[S")) { // NOI18N
498
aw.values.add(new Short JavaDoc(readShort()));
499             } else if (aw.classdesc.name.equals("[I")) { // NOI18N
500
aw.values.add(new Integer JavaDoc(readInt()));
501             } else if (aw.classdesc.name.equals("[J")) { // NOI18N
502
aw.values.add(new Long JavaDoc(readLong()));
503             } else if (aw.classdesc.name.equals("[F")) { // NOI18N
504
aw.values.add(new Float JavaDoc(Float.intBitsToFloat(readInt())));
505             } else if (aw.classdesc.name.equals("[D")) { // NOI18N
506
aw.values.add(new Double JavaDoc(Double.longBitsToDouble(readLong())));
507             } else if (aw.classdesc.name.equals("[C")) { // NOI18N
508
aw.values.add(new Character JavaDoc((char)readShort()));
509             } else if (aw.classdesc.name.equals("[Z")) { // NOI18N
510
aw.values.add(readByte() == 1 ? Boolean.TRUE : Boolean.FALSE);
511             } else {
512                 aw.values.add(readContent());
513             }
514         }
515         if (DEBUG) System.err.println("readNewArray: " + aw); // NOI18N
516
return aw;
517     }
518     
519     private String JavaDoc readNewString() throws IOException {
520         String JavaDoc s = readUTF();
521         makeRef(s);
522         return s;
523     }
524     
525     private Object JavaDoc readReference() throws IOException {
526         int i = readInt();
527         Object JavaDoc r = getRef(i);
528         if (DEBUG) System.err.println("readReference: " + r); // NOI18N
529
return r;
530     }
531     
532     private byte[] readBlockData() throws IOException {
533         int size = readByte();
534         if (size < 0) size += 256;
535         byte[] b = new byte[size];
536         for (int i = 0; i < size; i++) {
537             b[i] = readByte();
538         }
539         if (DEBUG) System.err.println("readBlockData: " + size + " bytes"); // NOI18N
540
return b;
541     }
542     
543     private byte[] readBlockDataLong() throws IOException {
544         int size = readInt();
545         if (size < 0) throw new NotImplementedException();
546         byte[] b = new byte[size];
547         for (int i = 0; i < size; i++) {
548             b[i] = readByte();
549         }
550         if (DEBUG) System.err.println("readBlockDataLong: " + size + " bytes"); // NOI18N
551
return b;
552     }
553     
554     private List<NameValue> readNoWrClass(ClassDesc cd) throws IOException {
555         List<FieldDesc> fields = cd.fields;
556         List<NameValue> values = new ArrayList<NameValue>(fields.size());
557         for (int i = 0; i < fields.size(); i++) {
558             FieldDesc fd = (FieldDesc)fields.get(i);
559             if (fd.type.equals("B")) { // NOI18N
560
values.add(new NameValue(fd, new Byte JavaDoc(readByte())));
561             } else if (fd.type.equals("S")) { // NOI18N
562
values.add(new NameValue(fd, new Short JavaDoc(readShort())));
563             } else if (fd.type.equals("I")) { // NOI18N
564
values.add(new NameValue(fd, new Integer JavaDoc(readInt())));
565             } else if (fd.type.equals("J")) { // NOI18N
566
values.add(new NameValue(fd, new Long JavaDoc(readLong())));
567             } else if (fd.type.equals("F")) { // NOI18N
568
values.add(new NameValue(fd, new Float JavaDoc(Float.intBitsToFloat(readInt()))));
569             } else if (fd.type.equals("D")) { // NOI18N
570
values.add(new NameValue(fd, new Double JavaDoc(Double.longBitsToDouble(readLong()))));
571             } else if (fd.type.equals("C")) { // NOI18N
572
values.add(new NameValue(fd, new Character JavaDoc((char)readShort())));
573             } else if (fd.type.equals("Z")) { // NOI18N
574
values.add(new NameValue(fd, readByte() == 1 ? Boolean.TRUE : Boolean.FALSE));
575             } else {
576                 values.add(new NameValue(fd, readContent()));
577             }
578         }
579         if (DEBUG) System.err.println("readNoWrClass: " + values); // NOI18N
580
return values;
581     }
582
583 }
584
Popular Tags