Projekt

Obecné

Profil

Stáhnout (10.6 KB) Statistiky
| Větev: | Tag: | Revize:
1
package jdeserialize;
2

    
3
import java.io.*;
4
import java.util.*;
5

    
6
/**
7
 * <p>
8
 * Represents the entire serialized prototype of the class, including all
9
 * fields, inner classes, class annotations, and inheritance hierarchy. This
10
 * includes proxy class descriptions.
11
 * </p>
12
 *
13
 * <p>
14
 * Generally, this class is used to represent the type of an instance written to
15
 * an ObjectOutputStream with its writeObject() method, or of a related array or
16
 * field type. However, there's a notable exception: when instances of type
17
 * java.io.ObjectStreamClass are written with writeObject(), only their class
18
 * description is written (cf. Object Serialization Specification, 4.3). They
19
 * will be represented with an instance of classdesc as well.
20
 * </p>
21
 */
22
public class classdesc extends contentbase {
23
    /**
24
     * Type of the class being represented; either a normal class or a proxy class.
25
     */
26
    public classdesctype classtype;
27

    
28
    /**
29
     * Class name.
30
     */
31
    public String name;
32

    
33
    /**
34
     * Serial version UID, as recorded in the stream.
35
     */
36
    public long serialVersionUID;
37

    
38
    /**
39
     * Description flags byte; this should be a mask of values from the
40
     * ObjectStreamContants class. Refer to chapter 6 of the Object Stream
41
     * Serialization Protocol for details.
42
     */
43
    public byte descflags;
44

    
45
    /**
46
     * Array of fields in the class, in the order serialized by the stream writer.
47
     */
48
    public field[] fields;
49

    
50
    /**
51
     * List of inner classes, in the order serialized by the stream writer.
52
     */
53
    public List<classdesc> innerclasses;
54

    
55
    /**
56
     * List of annotation objects; these are *not* Java annotations, but data
57
     * written by the
58
     * 
59
     * <pre>
60
     * annotateClass(Class<?>)<pre> and <pre>annotateProxyClass(Class<?>)
61
     * </pre>
62
     * 
63
     * methods of an ObjectOutputStream.
64
     */
65
    public List<content> annotations;
66

    
67
    /**
68
     * The superclass of the object, if available.
69
     */
70
    public classdesc superclass;
71

    
72
    /**
73
     * Array of serialized interfaces, in the order serialized by the stream writer.
74
     */
75
    public String[] interfaces;
76

    
77
    /**
78
     * Set of enum constants, for enum classes.
79
     */
80
    public Set<String> enumconstants;
81

    
82
    private boolean isInnerClass = false;
83

    
84
    /**
85
     * True if this class has been determined to be an inner class; this
86
     * determination is generally made by connectMemberClasses().
87
     * 
88
     * @return true if the class is an inner class
89
     */
90
    public boolean isInnerClass() {
91
        return isInnerClass;
92
    }
93

    
94
    /**
95
     * Sets the value that denotes that the class is an inner class.
96
     *
97
     * @param nis the value to set
98
     */
99
    public void setIsInnerClass(boolean nis) {
100
        this.isInnerClass = nis;
101
    }
102

    
103
    private boolean isLocalInnerClass = false;
104

    
105
    /**
106
     * True if this class has been determined to be a local inner class; this
107
     * determination is generally made by connectMemberClasses().
108
     *
109
     * @return true if the class is a local inner class
110
     */
111
    public boolean isLocalInnerClass() {
112
        return isLocalInnerClass;
113
    }
114

    
115
    /**
116
     * Sets the flag that denotes whether this class is a local inner class.
117
     * 
118
     * @param nis the value to set
119
     */
120
    public void setIsLocalInnerClass(boolean nis) {
121
        this.isLocalInnerClass = nis;
122
    }
123

    
124
    private boolean isStaticMemberClass = false;
125

    
126
    /**
127
     * <p>
128
     * True if this class has been determined to be a static member class; this
129
     * determination is generally made by connectMemberClasses().
130
     * </p>
131
     *
132
     * <p>
133
     * Note that in some cases, static member classes' descriptions will be
134
     * serialized even though their enclosing class is not. In these cases, this may
135
     * return false. See connectMemberClasses() for details.
136
     * </p>
137
     *
138
     * @return true if this is a static member class
139
     */
140
    public boolean isStaticMemberClass() {
141
        return isStaticMemberClass;
142
    }
143

    
144
    /**
145
     * Sets the flag that denotes whether this class is a static member class.
146
     *
147
     * @param nis the value to set
148
     */
149
    public void setIsStaticMemberClass(boolean nis) {
150
        this.isStaticMemberClass = nis;
151
    }
152

    
153
    /**
154
     * Constructor.
155
     *
156
     * @param classtype the type of the class
157
     */
158
    public classdesc(classdesctype classtype) {
159
        super(contenttype.CLASSDESC);
160
        this.classtype = classtype;
161
        this.enumconstants = new HashSet<String>();
162
        this.innerclasses = new ArrayList<classdesc>();
163
    }
164

    
165
    /**
166
     * Add an inner class to the description's list.
167
     * 
168
     * @param cd inner class to add
169
     */
170
    public void addInnerClass(classdesc cd) {
171
        innerclasses.add(cd);
172
    }
173

    
174
    /**
175
     * Add an enum constant to the description's set.
176
     *
177
     * @param constval enum constant string
178
     */
179
    public void addEnum(String constval) {
180
        this.enumconstants.add(constval);
181
    }
182

    
183
    /**
184
     * Determines whether this is an array type.
185
     * 
186
     * @return true if this is an array type.
187
     */
188
    public boolean isArrayClass() {
189
        if (name != null && name.length() > 1 && name.charAt(0) == '[') {
190
            return true;
191
        } else {
192
            return false;
193
        }
194
    }
195

    
196
    public String toString() {
197
        StringBuffer sb = new StringBuffer();
198
        sb.append("[cd ").append(jdeserialize.hex(handle)).append(": name ").append(name);
199
        sb.append(" uid ").append(serialVersionUID);
200
        sb.append("]");
201
        return sb.toString();
202
    }
203

    
204
    /**
205
     * Generates a list of all class descriptions in this class's hierarchy, in the
206
     * order described by the Object Stream Serialization Protocol. This is the
207
     * order in which fields are read from the stream.
208
     * 
209
     * @param classes a list to be filled in with the hierarchy
210
     */
211
    public void getHierarchy(ArrayList<classdesc> classes) {
212
        if (superclass != null) {
213
            if (superclass.classtype == classdesctype.PROXYCLASS) {
214
                jdeserialize.debugerr("warning: hit a proxy class in superclass hierarchy");
215
            } else {
216
                superclass.getHierarchy(classes);
217
            }
218
        }
219
        classes.add(this);
220
    }
221

    
222
    public void validate() throws ValidityException {
223
        // If neither SC_SERIALIZABLE nor SC_EXTERNALIZABLE is set, then the number of
224
        // fields is always zero. (spec section 4.3)
225
        if ((descflags & (ObjectStreamConstants.SC_SERIALIZABLE | ObjectStreamConstants.SC_EXTERNALIZABLE)) == 0
226
                && fields != null && fields.length > 0) {
227
            throw new ValidityException("non-serializable, non-externalizable class has fields!");
228
        }
229
        if ((descflags & (ObjectStreamConstants.SC_SERIALIZABLE
230
                | ObjectStreamConstants.SC_EXTERNALIZABLE)) == (ObjectStreamConstants.SC_SERIALIZABLE
231
                        | ObjectStreamConstants.SC_EXTERNALIZABLE)) {
232
            throw new ValidityException("both Serializable and Externalizable are set!");
233
        }
234
        if ((descflags & ObjectStreamConstants.SC_ENUM) != 0) {
235
            // we're an enum; shouldn't have any fields/superinterfaces
236
            if ((fields != null && fields.length > 0) || interfaces != null) {
237
                throw new ValidityException("enums shouldn't implement interfaces or have non-constant fields!");
238
            }
239
        } else {
240
            // non-enums shouldn't have enum constant fields.
241
            if (enumconstants != null && enumconstants.size() > 0) {
242
                throw new ValidityException("non-enum classes shouldn't have enum constants!");
243
            }
244
        }
245
    }
246

    
247
    public @Override String toJson(String indentation, Map<classdesc, Map<field, Object>> fielddata, boolean child) {
248
        StringBuffer sb = new StringBuffer();
249
        String fieldJsonValue = "";
250

    
251
        if (!child) {
252
            sb.append(indentation);
253
        }
254

    
255
        sb.append("{\n");
256
        indentation += "\t";
257

    
258
        sb.append(indentation).append("class ").append(this.name);
259

    
260
        this.extendsToJson(sb, this.superclass);
261
        this.interfacesToJson(sb, this.interfaces);
262

    
263
        sb.append(" : {"); // ending of first line
264
        indentation += "\t";
265

    
266
        //iterating through fields and converts them into json string
267
        for (field locField : this.fields) {
268
            Object locVal = fielddata.get(this).get(locField);
269

    
270
            // field could be null, but then, nothing to show
271
            if (locVal == null)
272
                continue;
273

    
274
            if (locVal instanceof content) {
275
                fieldJsonValue = ((content) locVal).toJson(indentation, fielddata, true);
276
            } else {
277
                fieldJsonValue = locVal.toString();
278
            }
279

    
280
            String locString = "\n" + indentation + "\"" + locField.name + "\"" + " : " + fieldJsonValue;
281
            sb.append(locString);
282

    
283
            if (!locField.equals(this.fields[this.fields.length - 1])) {
284
                sb.append(", ");
285
            }
286
        }
287

    
288
        indentation = indentation.replaceFirst("\t", "");
289
        sb.append("\n").append(indentation).append("}");
290

    
291
        //recursively call toJson for superclass if presented
292
        if (this.superclass != null) {
293
            indentation = indentation.replaceFirst("\t", "");
294
            sb.append("\n").append(indentation).append("}");
295
            sb.append("," + "\n");
296
            sb.append(this.superclass.toJson(indentation, fielddata, false));
297
        } else {
298
            indentation = indentation.replaceFirst("\t", "");
299
            sb.append("\n").append(indentation).append("}");
300
        }
301

    
302
        return sb.toString();
303
    }
304

    
305
    /**
306
     * Appends the extends clausule to the input StringBuffer.
307
     * Only if superclass presented
308
     * 
309
     * @param sb            StringBuffer to append the string to
310
     * @param superclass    superclass instance which name will be appended
311
     */
312
    private void extendsToJson(StringBuffer sb, classdesc superclass) {
313
        if (this.superclass != null) {
314
            sb.append(" extends ");
315
            sb.append(this.superclass.name);
316
        }
317
    }
318

    
319
    /**
320
     * Appends the implements clausule to the input StringBuffer.
321
     * Only if any interface implementation presented
322
     * 
323
     * @param sb            StringBuffer to append the string to
324
     * @param interfaces    Array of implemented interface names
325
     */
326
    private void interfacesToJson(StringBuffer sb, String[] interfaces) {
327
        if (interfaces != null) {
328
            sb.append(" implements ");
329
            for (String str : this.interfaces) {
330
                sb.append(str);
331
                if (this.interfaces[this.interfaces.length - 1] != str) {
332
                    sb.append(", ");
333
                }
334
            }
335
        }
336
    }
337
}
(8-8/20)