1
|
package deserialize;
|
2
|
|
3
|
import java.util.ArrayList;
|
4
|
import java.util.Arrays;
|
5
|
import java.util.List;
|
6
|
|
7
|
import org.codehaus.jackson.JsonNode;
|
8
|
|
9
|
/**
|
10
|
* https://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html
|
11
|
*/
|
12
|
public class Grammar {
|
13
|
|
14
|
private final static short STREAM_MAGIC = (short) 0xACED;
|
15
|
private final static short STREAM_VERSION = 5;
|
16
|
private final static byte TC_NULL = 0x70;
|
17
|
private final static byte TC_REFERENCE = 0x71;
|
18
|
private final static byte TC_CLASSDESC = 0x72;
|
19
|
private final static byte TC_OBJECT = 0x73;
|
20
|
private final static byte TC_STRING = 0x74;
|
21
|
private final static byte TC_ARRAY = 0x75;
|
22
|
private final static byte TC_CLASS = 0x76;
|
23
|
private final static byte TC_BLOCKDATA = 0x77;
|
24
|
private final static byte TC_ENDBLOCKDATA = 0x78;
|
25
|
private final static byte TC_RESET = 0x79;
|
26
|
private final static byte TC_BLOCKDATALONG = 0x7A;
|
27
|
private final static byte TC_EXCEPTION = 0x7B;
|
28
|
private final static byte TC_LONGSTRING = 0x7C;
|
29
|
private final static byte TC_PROXYCLASSDESC = 0x7D;
|
30
|
private final static byte TC_ENUM = 0x7E;
|
31
|
private final static int baseWireHandle = (int) 0x7E0000;
|
32
|
|
33
|
final static byte SC_WRITE_METHOD = 0x01; // if SC_SERIALIZABLE
|
34
|
final static byte SC_BLOCK_DATA = 0x08; // if SC_EXTERNALIZABLE
|
35
|
final static byte SC_SERIALIZABLE = 0x02;
|
36
|
final static byte SC_EXTERNALIZABLE = 0x04;
|
37
|
final static byte SC_ENUM = 0x10;
|
38
|
|
39
|
private ByteReader reader;
|
40
|
|
41
|
public Grammar(byte buffer[]) {
|
42
|
reader = new ByteReader(buffer);
|
43
|
}
|
44
|
|
45
|
|
46
|
List<ClassDescription> classes = new ArrayList<ClassDescription>();
|
47
|
ClassDescription actClass = null;
|
48
|
|
49
|
public JsonNode process() {
|
50
|
System.out.println("Kontrola hlavicky souboru: " + (reader.readShort() == STREAM_MAGIC && reader.readShort() == STREAM_VERSION));
|
51
|
|
52
|
while (!reader.end()) {
|
53
|
try {
|
54
|
object();
|
55
|
} catch (Exception e) {
|
56
|
e.printStackTrace();
|
57
|
break;
|
58
|
}
|
59
|
}
|
60
|
|
61
|
return classes.get(0).getJsonNode();
|
62
|
// System.out.println(classes.get(0).toString());
|
63
|
}
|
64
|
|
65
|
// FOR VALUES :
|
66
|
// The size and types are described by the
|
67
|
// classDesc for the current object
|
68
|
public Object object() {
|
69
|
Object retValue;
|
70
|
byte b = reader.readByte();
|
71
|
switch (b) {
|
72
|
case TC_OBJECT: {
|
73
|
System.out.println("X1");
|
74
|
|
75
|
// Note. TC_OBJECT; classDesc(); classdata()[]; // data for each class
|
76
|
// Note. classDescFlags = (byte)
|
77
|
|
78
|
ClassDescription desc = (ClassDescription) object();
|
79
|
retValue = desc;
|
80
|
|
81
|
/*byte flags = readByte();
|
82
|
System.out.println("DEF: " + String.format("%02X", flags));
|
83
|
boolean xxx = SC_SERIALIZABLE == desc2.flags && SC_WRITE_METHOD != flags;
|
84
|
boolean xxx2 = SC_SERIALIZABLE == desc2.flags && SC_WRITE_METHOD == flags;
|
85
|
boolean xxx3 = SC_EXTERNALIZABLE == desc2.flags && SC_BLOCK_DATA != flags;
|
86
|
boolean xxx4 = SC_EXTERNALIZABLE == desc2.flags && SC_BLOCK_DATA == flags;
|
87
|
System.out.println(xxx);
|
88
|
System.out.println(xxx2);
|
89
|
System.out.println(xxx3);
|
90
|
System.out.println(xxx4);*/
|
91
|
|
92
|
/* TODO
|
93
|
classDesc(); // && (
|
94
|
|
95
|
//values() // fields in order of class descriptor // SC_SERIALIZABLE & classDescFlag &&
|
96
|
// !(SC_WRITE_METHOD & classDescFlags)
|
97
|
// OR
|
98
|
//values() fields in order of class descriptor; object(); // SC_SERIALIZABLE & classDescFlag &&
|
99
|
// SC_WRITE_METHOD & classDescFlags
|
100
|
// OR
|
101
|
//object(); // SC_EXTERNALIZABLE & classDescFlag &&
|
102
|
// !(SC_BLOCKDATA & classDescFlags
|
103
|
// OR
|
104
|
//object(); // SC_EXTERNALIZABLE & classDescFlag&&
|
105
|
// SC_BLOCKDATA & classDescFlags
|
106
|
// );*/
|
107
|
}
|
108
|
break;
|
109
|
case TC_CLASS: {
|
110
|
System.out.println("X2");
|
111
|
ClassDescription desc = (ClassDescription) object();
|
112
|
retValue = desc;
|
113
|
}
|
114
|
break;
|
115
|
case TC_ARRAY: {
|
116
|
ClassDescription desc = (ClassDescription) object();
|
117
|
System.out.println("X3 " /*+ desc*/);
|
118
|
// TODO int size = readInt();
|
119
|
retValue = desc; // TODO + "[" + size + "]";
|
120
|
}
|
121
|
break;
|
122
|
case TC_STRING: {
|
123
|
String str = reader.readUtf();
|
124
|
System.out.println("X4 " + str);
|
125
|
retValue = str;
|
126
|
}
|
127
|
break;
|
128
|
case TC_LONGSTRING: {
|
129
|
System.out.println("X5");
|
130
|
String str = reader.readLongUtf();
|
131
|
retValue = str;
|
132
|
}
|
133
|
break;
|
134
|
case TC_ENUM: {
|
135
|
System.out.println("X6");
|
136
|
ClassDescription desc = (ClassDescription) object();
|
137
|
desc.isClass = false;
|
138
|
retValue = desc;
|
139
|
System.out.println("enumConstName: " + (String) object());
|
140
|
}
|
141
|
break;
|
142
|
|
143
|
|
144
|
case TC_CLASSDESC: {
|
145
|
System.out.println("X7");
|
146
|
ClassDescription desc = new ClassDescription();
|
147
|
desc.className = reader.readUtf();
|
148
|
desc.serialVersionUID = reader.readLong();
|
149
|
desc.flags = reader.readByte();
|
150
|
desc.isClass = true;
|
151
|
desc.setVariables(fields());
|
152
|
|
153
|
if (actClass == null) {
|
154
|
actClass = desc;
|
155
|
}
|
156
|
// TODO
|
157
|
actClass.addParent(desc);
|
158
|
|
159
|
// TODO object(null); classDesc();
|
160
|
// TODO System.out.println(desc.toString());
|
161
|
retValue = desc;
|
162
|
}
|
163
|
break;
|
164
|
case TC_PROXYCLASSDESC: {
|
165
|
System.out.println("X8");
|
166
|
int count = reader.readInt();
|
167
|
String name = reader.readUtf();
|
168
|
retValue = name + "[" + count + "]";
|
169
|
// TODO object(null); classDesc();
|
170
|
}
|
171
|
break;
|
172
|
case TC_NULL: {
|
173
|
// TODO
|
174
|
System.out.println("---NULL---");
|
175
|
retValue = null;
|
176
|
|
177
|
classes.add(actClass);
|
178
|
actClass = null;
|
179
|
while (true) {
|
180
|
Variable actVar = classes.get(classes.size() - 1).getActVariable();
|
181
|
if (actVar == null) {
|
182
|
break;
|
183
|
}
|
184
|
|
185
|
switch (actVar.getType()) {
|
186
|
case 'B': actVar.setValue(reader.readByte()); break;
|
187
|
case 'C': actVar.setValue((char) reader.readByte()); break;
|
188
|
case 'D': actVar.setValue(reader.readDouble()); break;
|
189
|
case 'F': actVar.setValue(reader.readFloat()); break;
|
190
|
case 'I': actVar.setValue(reader.readInt()); break;
|
191
|
case 'J': actVar.setValue(reader.readLong()); break;
|
192
|
case 'S': actVar.setValue(reader.readShort()); break;
|
193
|
case 'Z': actVar.setValue(reader.readBoolean()); break;
|
194
|
case '[':
|
195
|
ClassDescription desccc = (ClassDescription) object();
|
196
|
|
197
|
object(); // END BLOK
|
198
|
object(); // NULL
|
199
|
|
200
|
String dataType = desccc.className.substring(1);
|
201
|
|
202
|
Object array[] = new Object[reader.readInt()];
|
203
|
for (int i = 0; i < array.length; i++) {
|
204
|
Object element = null;
|
205
|
switch (dataType.charAt(0)) {
|
206
|
case 'B': element = reader.readByte(); break;
|
207
|
case 'C': element = reader.readChar(); break;
|
208
|
case 'D': element = reader.readDouble(); break;
|
209
|
case 'F': element = reader.readFloat(); break;
|
210
|
case 'I': element = reader.readInt(); break;
|
211
|
case 'J': element = reader.readLong(); break;
|
212
|
case 'S': element = reader.readShort(); break;
|
213
|
case 'Z': element = reader.readBoolean(); break;
|
214
|
case '[': object(); break; // TODO
|
215
|
case 'L': element = object(); break;
|
216
|
}
|
217
|
array[i] = element;
|
218
|
}
|
219
|
|
220
|
System.out.println(Arrays.toString(array));
|
221
|
actVar.setValue(array);
|
222
|
break;
|
223
|
case 'L': actVar.setValue(object()); break;
|
224
|
}
|
225
|
}
|
226
|
}
|
227
|
break;
|
228
|
case TC_REFERENCE: {
|
229
|
System.out.println("---REFERENCE---");
|
230
|
int ref = reader.readInt();
|
231
|
System.out.println(String.format("%X", ref));
|
232
|
int num = reader.readInt();
|
233
|
System.out.println(String.format("%X", num));
|
234
|
// TODO (ClassDesc) TC_REFERENCE (int)handle ?!?
|
235
|
retValue = null;
|
236
|
}
|
237
|
break;
|
238
|
|
239
|
|
240
|
case TC_EXCEPTION: {
|
241
|
// (Throwable)object;
|
242
|
retValue = (Throwable) object();
|
243
|
}
|
244
|
break;
|
245
|
case TC_RESET: {
|
246
|
// TODO
|
247
|
System.out.println("---RESET---");
|
248
|
retValue = null;
|
249
|
}
|
250
|
break;
|
251
|
case TC_BLOCKDATA: {
|
252
|
System.out.println("X13");
|
253
|
char size = reader.readUnsignedByte();
|
254
|
byte[] data = new byte[size];
|
255
|
for (int i = 0; i < size; i++) {
|
256
|
data[i] = reader.readByte();
|
257
|
}
|
258
|
// (unsigned byte)<size> (byte)[size];
|
259
|
retValue = data;
|
260
|
}
|
261
|
break;
|
262
|
case TC_BLOCKDATALONG: {
|
263
|
System.out.println("X14");
|
264
|
int size = reader.readInt();
|
265
|
byte[] data = new byte[size];
|
266
|
for (int i = 0; i < size; i++) {
|
267
|
data[i] = reader.readByte();
|
268
|
}
|
269
|
// (int)<size> (byte)[size];
|
270
|
retValue = data;
|
271
|
}
|
272
|
break;
|
273
|
case TC_ENDBLOCKDATA: {
|
274
|
// TODO
|
275
|
System.out.println("---ENDBLOCKDATA---");
|
276
|
retValue = null;
|
277
|
}
|
278
|
break;
|
279
|
default:
|
280
|
System.out.println("DEF: " + String.format("%02X", b) + " " + (char) b);
|
281
|
retValue = null;
|
282
|
}
|
283
|
|
284
|
return retValue;
|
285
|
}
|
286
|
|
287
|
public List<Variable> fields() {
|
288
|
List<Variable> variables = new ArrayList<Variable>();
|
289
|
|
290
|
short count = reader.readShort();
|
291
|
for (int i = 0; i < count; i++) {
|
292
|
char type = (char) reader.readByte();
|
293
|
String variable = reader.readUtf();
|
294
|
String typeName = null;
|
295
|
if (!DataType.isPrimaryType(type))
|
296
|
typeName = (String) object();
|
297
|
variables.add(new Variable(type, variable, typeName));
|
298
|
}
|
299
|
|
300
|
return variables;
|
301
|
}
|
302
|
|
303
|
}
|