Revize 0286c04b
Přidáno uživatelem Michal Horký před více než 4 roky(ů)
demo_mh/Deserializer/src/deserialize/Grammar.java | ||
---|---|---|
1 | 1 |
package deserialize; |
2 | 2 |
|
3 |
import java.io.ByteArrayInputStream; |
|
4 |
import java.io.DataInputStream; |
|
5 |
import java.nio.ByteBuffer; |
|
6 |
import java.util.ArrayList; |
|
3 | 7 |
import java.util.HashMap; |
8 |
import java.util.List; |
|
4 | 9 |
|
5 | 10 |
/** |
6 | 11 |
* https://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html |
... | ... | |
9 | 14 |
|
10 | 15 |
private final static short STREAM_MAGIC = (short) 0xACED; |
11 | 16 |
private final static short STREAM_VERSION = 5; |
12 |
private final static byte TC_NULL = 0x70; |
|
13 |
private final static byte TC_REFERENCE = 0x71; |
|
14 |
private final static byte TC_CLASSDESC = 0x72; |
|
15 |
private final static byte TC_OBJECT = 0x73; |
|
16 |
private final static byte TC_STRING = 0x74; |
|
17 |
private final static byte TC_ARRAY = 0x75; |
|
18 |
private final static byte TC_CLASS = 0x76; |
|
19 |
private final static byte TC_BLOCKDATA = 0x77; |
|
20 |
private final static byte TC_ENDBLOCKDATA = 0x78; |
|
21 |
private final static byte TC_RESET = 0x79; |
|
22 |
private final static byte TC_BLOCKDATALONG = 0x7A; |
|
23 |
private final static byte TC_EXCEPTION = 0x7B; |
|
24 |
private final static byte TC_LONGSTRING = 0x7C; |
|
25 |
private final static byte TC_PROXYCLASSDESC = 0x7D; |
|
26 |
private final static byte TC_ENUM = 0x7E; |
|
27 |
private final static int baseWireHandle = 0x7E0000; |
|
28 |
|
|
29 |
final static byte SC_WRITE_METHOD = 0x01; // if SC_SERIALIZABLE |
|
30 |
final static byte SC_BLOCK_DATA = 0x08; // if SC_EXTERNALIZABLE |
|
31 |
final static byte SC_SERIALIZABLE = 0x02; |
|
32 |
final static byte SC_EXTERNALIZABLE = 0x04; |
|
33 |
final static byte SC_ENUM = 0x10; |
|
17 |
private final static byte TC_NULL = (byte) 0x70;
|
|
18 |
private final static byte TC_REFERENCE = (byte) 0x71;
|
|
19 |
private final static byte TC_CLASSDESC = (byte) 0x72;
|
|
20 |
private final static byte TC_OBJECT = (byte) 0x73;
|
|
21 |
private final static byte TC_STRING = (byte) 0x74;
|
|
22 |
private final static byte TC_ARRAY = (byte) 0x75;
|
|
23 |
private final static byte TC_CLASS = (byte) 0x76;
|
|
24 |
private final static byte TC_BLOCKDATA = (byte) 0x77;
|
|
25 |
private final static byte TC_ENDBLOCKDATA = (byte) 0x78;
|
|
26 |
private final static byte TC_RESET = (byte) 0x79;
|
|
27 |
private final static byte TC_BLOCKDATALONG = (byte) 0x7A;
|
|
28 |
private final static byte TC_EXCEPTION = (byte) 0x7B;
|
|
29 |
private final static byte TC_LONGSTRING = (byte) 0x7C;
|
|
30 |
private final static byte TC_PROXYCLASSDESC = (byte) 0x7D;
|
|
31 |
private final static byte TC_ENUM = (byte) 0x7E;
|
|
32 |
private final static int baseWireHandle = (int) 0x7E0000;
|
|
33 |
|
|
34 |
final static byte SC_WRITE_METHOD = (byte) 0x01; // if SC_SERIALIZABLE
|
|
35 |
final static byte SC_BLOCK_DATA = (byte) 0x08; // if SC_EXTERNALIZABLE
|
|
36 |
final static byte SC_SERIALIZABLE = (byte) 0x02;
|
|
37 |
final static byte SC_EXTERNALIZABLE = (byte) 0x04;
|
|
38 |
final static byte SC_ENUM = (byte) 0x10;
|
|
34 | 39 |
|
35 | 40 |
HashMap<Character, String> primTypeCodes; |
36 | 41 |
HashMap<Character, String> objTypeCodes; |
... | ... | |
39 | 44 |
// Note. (XXX) This token has the XXX type specified |
40 | 45 |
|
41 | 46 |
|
42 |
public Grammar() { |
|
47 |
private List<Byte> buffer; |
|
48 |
public Grammar(List<Byte> buffer) { |
|
49 |
this.buffer = buffer; |
|
50 |
|
|
43 | 51 |
primTypeCodes = new HashMap<Character, String>(); |
44 | 52 |
primTypeCodes.put('B', "byte"); |
45 | 53 |
primTypeCodes.put('C', "char"); |
... | ... | |
49 | 57 |
primTypeCodes.put('J', "long"); |
50 | 58 |
primTypeCodes.put('S', "short"); |
51 | 59 |
primTypeCodes.put('Z', "boolean"); |
60 |
|
|
52 | 61 |
objTypeCodes = new HashMap<Character, String>(); |
53 | 62 |
objTypeCodes.put('[', "array"); |
54 | 63 |
objTypeCodes.put('L', "object"); |
55 | 64 |
} |
56 | 65 |
|
57 | 66 |
|
58 |
|
|
59 |
|
|
60 |
public void stream() { |
|
61 |
short x = STREAM_MAGIC; x = STREAM_VERSION; contents(); |
|
67 |
private byte takeFirst() { |
|
68 |
return buffer.remove(0); |
|
62 | 69 |
} |
63 | 70 |
|
64 |
public void contents() { |
|
65 |
content(); |
|
66 |
// OR |
|
67 |
contents(); content(); |
|
71 |
public byte readByte() { |
|
72 |
return takeFirst(); |
|
68 | 73 |
} |
69 | 74 |
|
70 |
public void content() {
|
|
71 |
object();
|
|
72 |
// OR
|
|
73 |
byte x = TC_BLOCKDATA; // TODO (unsigned byte)<size> (byte)[size];
|
|
74 |
// OR
|
|
75 |
x = TC_BLOCKDATALONG; // TODO (int)<size> (byte)[size];
|
|
75 |
private long readNumber(int bytes) {
|
|
76 |
long result = 0;
|
|
77 |
for (int i = (bytes - 1) * Byte.SIZE; i >= 0; i -= Byte.SIZE) {
|
|
78 |
result = result | ((takeFirst() & 0xFF) << i);
|
|
79 |
}
|
|
80 |
return result;
|
|
76 | 81 |
} |
77 | 82 |
|
78 |
public void object() { |
|
79 |
byte x = TC_OBJECT; classDesc(); newHandle(); classdata()/* TODO []*/; // data for each class |
|
80 |
// OR |
|
81 |
x = TC_CLASS; classDesc(); newHandle(); |
|
82 |
// OR |
|
83 |
x = TC_ARRAY; classDesc(); newHandle(); /* TODO (int)<size>*/ values()/*[size]*/; |
|
84 |
// OR |
|
85 |
x = TC_STRING; newHandle(); // TODO (utf) read 16-bit integer (string length) |
|
86 |
// OR |
|
87 |
x = TC_LONGSTRING; newHandle(); // TODO (long-utf) read 64-bit integer (string length) |
|
88 |
// OR |
|
89 |
x = TC_ENUM; classDesc(); newHandle(); /* TODO (String)*/ object(); |
|
90 |
// OR |
|
91 |
newClassDesc(); |
|
92 |
// OR |
|
93 |
x = TC_REFERENCE; // TODO (int) handle ?!?; |
|
94 |
// OR |
|
95 |
x = TC_NULL; |
|
96 |
// OR |
|
97 |
x = TC_EXCEPTION; reset(); /* TODO (Throwable)*/object(); reset(); |
|
98 |
// OR |
|
99 |
x = TC_RESET; |
|
83 |
public char readUnsignedByte() { |
|
84 |
return (char) readNumber(Byte.BYTES); |
|
100 | 85 |
} |
101 | 86 |
|
102 |
public void classDesc() { |
|
103 |
newClassDesc(); |
|
104 |
// OR |
|
105 |
byte x = TC_NULL; |
|
106 |
// OR |
|
107 |
/* TODO (ClassDesc)*/ x = TC_REFERENCE; // TODO (int) handle ?!?; |
|
87 |
public short readShort() { |
|
88 |
return (short) readNumber(Short.BYTES); |
|
108 | 89 |
} |
109 | 90 |
|
110 |
public void newClassDesc() { |
|
111 |
byte x = TC_CLASSDESC; /* TODO (utf) read 16-bit integer (string length); (long)*/; newHandle(); classDescFlags(); fields(); classAnnotation(); classDesc(); |
|
112 |
// OR |
|
113 |
x = TC_PROXYCLASSDESC; newHandle(); /* TODO (int)<count> => read int as count /(utf) read 16-bit integer (string length)/ [count]*/; classAnnotation(); classDesc(); |
|
91 |
public int readInt() { |
|
92 |
return (int) readNumber(Integer.BYTES); |
|
114 | 93 |
} |
115 | 94 |
|
116 |
public void classDescFlags() {
|
|
117 |
// TODO (byte)
|
|
95 |
public long readLong() {
|
|
96 |
return readNumber(Long.BYTES);
|
|
118 | 97 |
} |
119 | 98 |
|
120 |
public void fields() { |
|
121 |
/* TODO (short)<count> => read short as count */ fieldDesc() /*[count]*/; |
|
99 |
public String readString(long length) { |
|
100 |
String str = ""; |
|
101 |
for (int i = 0; i < length; i++) { |
|
102 |
str += (char) readByte(); |
|
103 |
} |
|
104 |
return str; |
|
122 | 105 |
} |
123 | 106 |
|
124 |
public void fieldDesc() { |
|
125 |
// TODO primTypeCodes.get(key); (utf) read 16-bit integer (string length); |
|
126 |
// OR |
|
127 |
/* TODO objTypeCodes.get(key) - array or object; (utf) read 16-bit integer (string length);*/ /*(String)*/object(); // String containing the field's type, |
|
128 |
// in field descriptor format |
|
129 |
} |
|
130 | 107 |
|
131 |
public void classAnnotation() { |
|
132 |
byte x = TC_ENDBLOCKDATA; |
|
133 |
// OR |
|
134 |
contents(); x = TC_ENDBLOCKDATA; // contents written by annotateClass |
|
135 |
} |
|
136 | 108 |
|
137 |
public void classdata() { |
|
138 |
values(); // fields in order of class descriptor // SC_SERIALIZABLE & classDescFlag && |
|
139 |
// !(SC_WRITE_METHOD & classDescFlags) |
|
140 |
// OR |
|
141 |
values() /* fields in order of class descriptor*/; objectAnnotation(); // SC_SERIALIZABLE & classDescFlag && |
|
142 |
// SC_WRITE_METHOD & classDescFlags |
|
143 |
// OR |
|
144 |
externalContents(); // SC_EXTERNALIZABLE & classDescFlag && |
|
145 |
// !(SC_BLOCKDATA & classDescFlags |
|
146 |
// OR |
|
147 |
objectAnnotation(); // SC_EXTERNALIZABLE & classDescFlag&& |
|
148 |
// SC_BLOCKDATA & classDescFlags |
|
149 |
} |
|
150 | 109 |
|
151 |
public void objectAnnotation() { |
|
152 |
byte x = TC_ENDBLOCKDATA; |
|
153 |
// OR |
|
154 |
contents(); x = TC_ENDBLOCKDATA; // contents written by writeObject |
|
155 |
// or writeExternal PROTOCOL_VERSION_2. |
|
156 |
} |
|
157 | 110 |
|
158 |
public void externalContent() { // Only parseable by readExternal |
|
159 |
// TODO ( bytes) // primitive data |
|
160 |
// OR |
|
161 |
object(); |
|
111 |
public String readUtf() { |
|
112 |
short length = readShort(); |
|
113 |
return readString(length); |
|
162 | 114 |
} |
163 | 115 |
|
164 |
public void externalContents() {// externalContent written by |
|
165 |
externalContent(); // writeExternal in PROTOCOL_VERSION_1. |
|
166 |
// OR |
|
167 |
externalContents(); externalContent(); |
|
116 |
public String readLongUtf() { |
|
117 |
long length = readLong(); |
|
118 |
return readString(length); |
|
168 | 119 |
} |
169 | 120 |
|
170 |
public void values() { |
|
171 |
// The size and types are described by the |
|
172 |
// classDesc for the current object |
|
121 |
|
|
122 |
|
|
123 |
|
|
124 |
|
|
125 |
|
|
126 |
|
|
127 |
|
|
128 |
public void start() { |
|
129 |
System.out.println("Kontrola hlavicky souboru: " + (readShort() == STREAM_MAGIC && readShort() == STREAM_VERSION)); |
|
130 |
while (!buffer.isEmpty()) { |
|
131 |
object(); |
|
132 |
} |
|
173 | 133 |
} |
174 | 134 |
|
175 |
public void newHandle() { |
|
176 |
// The next number in sequence is assigned |
|
177 |
// to the object being serialized or deserialized |
|
135 |
// FOR VALUES : |
|
136 |
// The size and types are described by the |
|
137 |
// classDesc for the current object |
|
138 |
public Object object() { |
|
139 |
Object retValue; |
|
140 |
byte b = readByte(); |
|
141 |
switch (b) { |
|
142 |
case TC_OBJECT: { |
|
143 |
System.out.println("X1"); |
|
144 |
|
|
145 |
// Note. TC_OBJECT; classDesc(); classdata()[]; // data for each class |
|
146 |
// Note. classDescFlags = (byte) |
|
147 |
|
|
148 |
ClassDescription desc = (ClassDescription) object(); |
|
149 |
retValue = desc; |
|
150 |
|
|
151 |
/*byte flags = readByte(); |
|
152 |
System.out.println("DEF: " + String.format("%02X", flags)); |
|
153 |
boolean xxx = SC_SERIALIZABLE == desc2.flags && SC_WRITE_METHOD != flags; |
|
154 |
boolean xxx2 = SC_SERIALIZABLE == desc2.flags && SC_WRITE_METHOD == flags; |
|
155 |
boolean xxx3 = SC_EXTERNALIZABLE == desc2.flags && SC_BLOCK_DATA != flags; |
|
156 |
boolean xxx4 = SC_EXTERNALIZABLE == desc2.flags && SC_BLOCK_DATA == flags; |
|
157 |
System.out.println(xxx); |
|
158 |
System.out.println(xxx2); |
|
159 |
System.out.println(xxx3); |
|
160 |
System.out.println(xxx4);*/ |
|
161 |
|
|
162 |
/* TODO |
|
163 |
classDesc(); // && ( |
|
164 |
|
|
165 |
//values() // fields in order of class descriptor // SC_SERIALIZABLE & classDescFlag && |
|
166 |
// !(SC_WRITE_METHOD & classDescFlags) |
|
167 |
// OR |
|
168 |
//values() fields in order of class descriptor; object(); // SC_SERIALIZABLE & classDescFlag && |
|
169 |
// SC_WRITE_METHOD & classDescFlags |
|
170 |
// OR |
|
171 |
//object(); // SC_EXTERNALIZABLE & classDescFlag && |
|
172 |
// !(SC_BLOCKDATA & classDescFlags |
|
173 |
// OR |
|
174 |
//object(); // SC_EXTERNALIZABLE & classDescFlag&& |
|
175 |
// SC_BLOCKDATA & classDescFlags |
|
176 |
// );*/ |
|
177 |
} |
|
178 |
break; |
|
179 |
case TC_CLASS: { |
|
180 |
System.out.println("X2"); |
|
181 |
ClassDescription desc = (ClassDescription) object(); |
|
182 |
retValue = desc; |
|
183 |
} |
|
184 |
break; |
|
185 |
case TC_ARRAY: { |
|
186 |
System.out.println("X3"); |
|
187 |
ClassDescription desc = (ClassDescription) object(); |
|
188 |
int size = readInt(); |
|
189 |
retValue = desc.className + "[" + size + "]"; |
|
190 |
} |
|
191 |
break; |
|
192 |
case TC_STRING: { |
|
193 |
String str = readUtf(); |
|
194 |
System.out.println("X4 " + str); |
|
195 |
retValue = str; |
|
196 |
} |
|
197 |
break; |
|
198 |
case TC_LONGSTRING: { |
|
199 |
System.out.println("X5"); |
|
200 |
String str = readLongUtf(); |
|
201 |
retValue = str; |
|
202 |
} |
|
203 |
break; |
|
204 |
case TC_ENUM: { |
|
205 |
System.out.println("X6"); |
|
206 |
ClassDescription desc = (ClassDescription) object(); |
|
207 |
desc.isClass = false; |
|
208 |
retValue = desc; |
|
209 |
System.out.println("enumConstName: " + (String) object()); |
|
210 |
} |
|
211 |
break; |
|
212 |
|
|
213 |
|
|
214 |
case TC_CLASSDESC: { |
|
215 |
System.out.println("X7"); |
|
216 |
ClassDescription desc = new ClassDescription(); |
|
217 |
desc.className = readUtf(); |
|
218 |
desc.serialVersionUID = readLong(); |
|
219 |
desc.flags = readByte(); |
|
220 |
desc.isClass = true; |
|
221 |
desc.variables = fields(); |
|
222 |
// TODO object(null); classDesc(); |
|
223 |
System.out.println(desc.toString()); |
|
224 |
retValue = desc; |
|
225 |
} |
|
226 |
break; |
|
227 |
case TC_PROXYCLASSDESC: { |
|
228 |
System.out.println("X8"); |
|
229 |
int count = readInt(); |
|
230 |
String name = readUtf(); |
|
231 |
retValue = name + "[" + +count + "]"; |
|
232 |
// TODO object(null); classDesc(); |
|
233 |
|
|
234 |
} |
|
235 |
break; |
|
236 |
case TC_NULL: { |
|
237 |
// TODO |
|
238 |
System.out.println("---NULL---"); |
|
239 |
retValue = null; |
|
240 |
} |
|
241 |
break; |
|
242 |
case TC_REFERENCE: { |
|
243 |
System.out.println("---REFERENCE---"); |
|
244 |
// TODO (ClassDesc) TC_REFERENCE (int)handle ?!? |
|
245 |
retValue = null; |
|
246 |
} |
|
247 |
break; |
|
248 |
|
|
249 |
|
|
250 |
case TC_EXCEPTION: { |
|
251 |
// TODO (Throwable)object(null); |
|
252 |
retValue = "(Throwable)"; |
|
253 |
} |
|
254 |
break; |
|
255 |
case TC_RESET: { |
|
256 |
// TODO |
|
257 |
System.out.println("---RESET---"); |
|
258 |
retValue = null; |
|
259 |
} |
|
260 |
break; |
|
261 |
case TC_BLOCKDATA: { |
|
262 |
System.out.println("X13"); |
|
263 |
char size = readUnsignedByte(); |
|
264 |
// (unsigned byte)<size> (byte)[size]; |
|
265 |
retValue = "byte [" + (int) size + "]"; |
|
266 |
} |
|
267 |
break; |
|
268 |
case TC_BLOCKDATALONG: { |
|
269 |
System.out.println("X14"); |
|
270 |
int size = readInt(); |
|
271 |
// (int)<size> (byte)[size]; |
|
272 |
retValue = "byte [" + size + "]"; |
|
273 |
} |
|
274 |
break; |
|
275 |
case TC_ENDBLOCKDATA: { |
|
276 |
// TODO |
|
277 |
System.out.println("---ENDBLOCKDATA---"); |
|
278 |
retValue = null; |
|
279 |
} |
|
280 |
break; |
|
281 |
default: |
|
282 |
System.out.println("DEF: " + String.format("%02X", b) + " " + (char) b); |
|
283 |
retValue = null; |
|
284 |
} |
|
285 |
|
|
286 |
return retValue; |
|
178 | 287 |
} |
179 | 288 |
|
180 |
public void reset() { |
|
181 |
// The set of known objects is discarded |
|
182 |
// so the objects of the exception do not |
|
183 |
// overlap with the previously sent objects |
|
184 |
// or with objects that may be sent after |
|
185 |
// the exception |
|
289 |
public List<String> fields() { |
|
290 |
List<String> rows = new ArrayList<String>(); |
|
291 |
|
|
292 |
short count = readShort(); |
|
293 |
for (int i = 0; i < count; i++) { |
|
294 |
char type = (char) readByte(); |
|
295 |
|
|
296 |
String row; |
|
297 |
if (primTypeCodes.containsKey(type)) { |
|
298 |
row = primTypeCodes.get(type) + " " + readUtf(); |
|
299 |
} else { |
|
300 |
String variable = readUtf(); |
|
301 |
String dataType = (String) object(); |
|
302 |
dataType = dataType.substring(1); |
|
303 |
|
|
304 |
if (primTypeCodes.containsKey(dataType.charAt(0))) |
|
305 |
dataType = primTypeCodes.get(dataType.charAt(0)); // remove type |
|
306 |
|
|
307 |
row = dataType + " " + variable; |
|
308 |
if (objTypeCodes.get(type) == "array") |
|
309 |
row += "[]"; |
|
310 |
} |
|
311 |
|
|
312 |
rows.add(row); |
|
313 |
} |
|
314 |
|
|
315 |
return rows; |
|
186 | 316 |
} |
317 |
|
|
187 | 318 |
} |
Také k dispozici: Unified diff
#7767
Zjednodušení gramatiky, částečné zprovoznění s exportem do konzole.