Source Code Cross Referenced for ObjectStreamClass.java in  » Apache-Harmony-Java-SE » java-package » java » io » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Apache Harmony Java SE » java package » java.io 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:
0018:        package java.io;
0019:
0020:        import java.lang.ref.WeakReference;
0021:        import java.lang.reflect.Constructor;
0022:        import java.lang.reflect.Field;
0023:        import java.lang.reflect.Method;
0024:        import java.lang.reflect.Modifier;
0025:        import java.lang.reflect.Proxy;
0026:        import java.security.AccessController;
0027:        import java.security.MessageDigest;
0028:        import java.security.NoSuchAlgorithmException;
0029:        import java.util.ArrayList;
0030:        import java.util.Arrays;
0031:        import java.util.Comparator;
0032:        import java.util.List;
0033:        import java.util.WeakHashMap;
0034:
0035:        import org.apache.harmony.luni.util.Msg;
0036:        import org.apache.harmony.luni.util.PriviAction;
0037:
0038:        /**
0039:         * Instances of ObjectStreamClass are used to describe classes of objects used
0040:         * by serialization. When objects are saved, information about all its
0041:         * superclasses is also saved by the use of descriptors, instances of
0042:         * ObjectStreamClass.
0043:         * 
0044:         * These descriptors carry information about the class they represent, such as -
0045:         * The name of the class - SUID of the class - Field names and types
0046:         * 
0047:         * @see ObjectOutputStream
0048:         * @see ObjectInputStream
0049:         * @see java.lang.Class
0050:         */
0051:        public class ObjectStreamClass implements  Serializable {
0052:
0053:            // No need to compute the SUID for ObjectStreamClass, just use the value
0054:            // below
0055:            private static final long serialVersionUID = -6120832682080437368L;
0056:
0057:            // Name of the field that contains the SUID value (if present)
0058:            private static final String UID_FIELD_NAME = "serialVersionUID"; //$NON-NLS-1$
0059:
0060:            private static final int CLASS_MODIFIERS_MASK;
0061:
0062:            private static final int FIELD_MODIFIERS_MASK;
0063:
0064:            private static final int METHOD_MODIFIERS_MASK;
0065:
0066:            private static final Class<?>[] READ_PARAM_TYPES;
0067:
0068:            private static final Class<?>[] WRITE_PARAM_TYPES;
0069:
0070:            static final Class<?>[] EMPTY_CONSTRUCTOR_PARAM_TYPES;
0071:
0072:            private static final Class<Void> VOID_CLASS;
0073:
0074:            static final Class<?>[] UNSHARED_PARAM_TYPES;
0075:
0076:            private static native void oneTimeInitialization();
0077:
0078:            static {
0079:                oneTimeInitialization();
0080:
0081:                CLASS_MODIFIERS_MASK = Modifier.PUBLIC | Modifier.FINAL
0082:                        | Modifier.INTERFACE | Modifier.ABSTRACT;
0083:                FIELD_MODIFIERS_MASK = Modifier.PUBLIC | Modifier.PRIVATE
0084:                        | Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL
0085:                        | Modifier.VOLATILE | Modifier.TRANSIENT;
0086:                METHOD_MODIFIERS_MASK = Modifier.PUBLIC | Modifier.PRIVATE
0087:                        | Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL
0088:                        | Modifier.SYNCHRONIZED | Modifier.NATIVE
0089:                        | Modifier.ABSTRACT | Modifier.STRICT;
0090:
0091:                READ_PARAM_TYPES = new Class[1];
0092:                WRITE_PARAM_TYPES = new Class[1];
0093:                READ_PARAM_TYPES[0] = ObjectInputStream.class;
0094:                WRITE_PARAM_TYPES[0] = ObjectOutputStream.class;
0095:                EMPTY_CONSTRUCTOR_PARAM_TYPES = new Class[0];
0096:                VOID_CLASS = Void.TYPE;
0097:                UNSHARED_PARAM_TYPES = new Class[1];
0098:                UNSHARED_PARAM_TYPES[0] = Object.class;
0099:            }
0100:
0101:            /**
0102:             * A value that indicates the class has no Serializable fields
0103:             */
0104:            public static final ObjectStreamField[] NO_FIELDS = new ObjectStreamField[0];
0105:
0106:            /*
0107:             * used to fetch field serialPersistentFields and checking its type
0108:             */
0109:            static final Class<?> ARRAY_OF_FIELDS;
0110:
0111:            static {
0112:                try {
0113:                    ARRAY_OF_FIELDS = Class
0114:                            .forName("[Ljava.io.ObjectStreamField;"); //$NON-NLS-1$
0115:                } catch (ClassNotFoundException e) {
0116:                    // This should not happen
0117:                    throw new AssertionError(e);
0118:                }
0119:            }
0120:
0121:            private static final String CLINIT_NAME = "<clinit>"; //$NON-NLS-1$
0122:
0123:            private static final int CLINIT_MODIFIERS = Modifier.STATIC;
0124:
0125:            private static final String CLINIT_SIGNATURE = "()V"; //$NON-NLS-1$
0126:
0127:            // Used to determine if an object is Serializable or Externalizable
0128:            private static final Class<Serializable> SERIALIZABLE = Serializable.class;
0129:
0130:            private static final Class<Externalizable> EXTERNALIZABLE = Externalizable.class;
0131:
0132:            // Used to test if the object is a String or a class.
0133:            static final Class<String> STRINGCLASS = String.class;
0134:
0135:            static final Class<?> CLASSCLASS = Class.class;
0136:
0137:            static final Class<ObjectStreamClass> OBJECTSTREAMCLASSCLASS = ObjectStreamClass.class;
0138:
0139:            // Table mapping instances of java.lang.Class to to corresponding instances
0140:            // of ObjectStreamClass
0141:            private static final WeakHashMap<Class<?>, ObjectStreamClass> classesAndDescriptors = new WeakHashMap<Class<?>, ObjectStreamClass>();
0142:
0143:            private transient Method methodWriteReplace;
0144:
0145:            private transient Method methodReadResolve;
0146:
0147:            private transient Method methodWriteObject;
0148:
0149:            private transient Method methodReadObject;
0150:
0151:            private transient Method methodReadObjectNoData;
0152:
0153:            // ClassDesc //
0154:
0155:            // Name of the class this descriptor represents
0156:            private transient String className;
0157:
0158:            // Corresponding loaded class with the name above
0159:            private transient WeakReference<Class<?>> resolvedClass;
0160:
0161:            // Serial version UID of the class the descriptor represents
0162:            private transient long svUID;
0163:
0164:            // ClassDescInfo //
0165:
0166:            // Any combination of SC_WRITE_METHOD, SC_SERIALIZABLE and SC_EXTERNALIZABLE
0167:            // (see ObjectStreamConstants)
0168:            private transient byte flags;
0169:
0170:            // Descriptor for the superclass of the class associated with this
0171:            // descriptor
0172:            private transient ObjectStreamClass super class;
0173:
0174:            // Array of ObjectStreamField (see below) describing the fields of this
0175:            // class
0176:            private transient ObjectStreamField[] fields;
0177:
0178:            // Array of ObjectStreamField describing the serialized fields of this class
0179:            private transient ObjectStreamField[] loadFields;
0180:
0181:            /*
0182:             * If an ObjectStreamClass describes an Externalizable class, it (the
0183:             * descriptor) should not have field descriptors (ObjectStreamField) at all.
0184:             * The ObjectStreamClass that gets saved should simply have no field info.
0185:             * This is a footnote in page 1511 (class Serializable) of "The Java Class
0186:             * Libraries, Second Edition, Vol. I".
0187:             */
0188:
0189:            /**
0190:             * Constructs a new instance of this class.
0191:             */
0192:            ObjectStreamClass() {
0193:                super ();
0194:            }
0195:
0196:            /**
0197:             * Compute class descriptor for a given class <code>cl</code>. If
0198:             * <code>computeSUID</code> is true, this method will compute the SUID for
0199:             * this class.
0200:             * 
0201:             * @param cl
0202:             *            a java.langClass for which to compute the corresponding
0203:             *            descriptor
0204:             * @param computeSUID
0205:             *            a boolean indicating if SUID should be computed or not.
0206:             * @return the computer class descriptor
0207:             */
0208:            private static ObjectStreamClass createClassDesc(Class<?> cl,
0209:                    boolean computeSUID) {
0210:
0211:                ObjectStreamClass result = new ObjectStreamClass();
0212:
0213:                boolean isProxy = Proxy.isProxyClass(cl);
0214:                boolean isEnum = Enum.class.isAssignableFrom(cl);
0215:                boolean isArray = cl.isArray();
0216:
0217:                // Now we fill in the values
0218:                result.setName(cl.getName());
0219:                result.setClass(cl);
0220:                Class<?> super class = cl.getSuperclass();
0221:                if (super class != null) {
0222:                    result.setSuperclass(lookup(super class));
0223:                }
0224:
0225:                Field[] declaredFields = null;
0226:                if (computeSUID) {
0227:                    // Lazy computation, to save speed & space
0228:                    if (isEnum || isProxy) {
0229:                        result.setSerialVersionUID(0L);
0230:                    } else {
0231:                        declaredFields = cl.getDeclaredFields();
0232:                        result.setSerialVersionUID(computeSerialVersionUID(cl,
0233:                                declaredFields));
0234:                    }
0235:                }
0236:
0237:                boolean serializable = isSerializable(cl);
0238:                // Serializables need field descriptors
0239:                if (serializable && !isArray) {
0240:                    if (declaredFields == null) {
0241:                        declaredFields = cl.getDeclaredFields();
0242:                    }
0243:                    result.buildFieldDescriptors(declaredFields);
0244:                } else {
0245:                    // Externalizables or arrays do not need FieldDesc info
0246:                    result.setFields(NO_FIELDS);
0247:                }
0248:
0249:                // Copy all fields to loadFields - they should be read by default in
0250:                // ObjectInputStream.defaultReadObject() method
0251:                ObjectStreamField[] fields = result.getFields();
0252:
0253:                if (fields != null) {
0254:                    ObjectStreamField[] loadFields = new ObjectStreamField[fields.length];
0255:
0256:                    for (int i = 0; i < fields.length; ++i) {
0257:                        loadFields[i] = new ObjectStreamField(fields[i]
0258:                                .getName(), fields[i].getType(), fields[i]
0259:                                .isUnshared());
0260:
0261:                        // resolve type string to init typeString field in
0262:                        // ObjectStreamField
0263:                        loadFields[i].getTypeString();
0264:                    }
0265:                    result.setLoadFields(loadFields);
0266:                }
0267:
0268:                byte flags = 0;
0269:                boolean externalizable = isExternalizable(cl);
0270:                if (externalizable) {
0271:                    flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
0272:                    flags |= ObjectStreamConstants.SC_BLOCK_DATA; // use protocol version 2 by default
0273:                } else if (serializable) {
0274:                    flags |= ObjectStreamConstants.SC_SERIALIZABLE;
0275:                }
0276:                result.methodWriteReplace = findMethod(cl, "writeReplace"); //$NON-NLS-1$
0277:                result.methodReadResolve = findMethod(cl, "readResolve"); //$NON-NLS-1$
0278:                result.methodWriteObject = findPrivateMethod(cl, "writeObject", //$NON-NLS-1$
0279:                        WRITE_PARAM_TYPES);
0280:                result.methodReadObject = findPrivateMethod(cl, "readObject", //$NON-NLS-1$
0281:                        READ_PARAM_TYPES);
0282:                result.methodReadObjectNoData = findPrivateMethod(cl,
0283:                        "readObjectNoData", EMPTY_CONSTRUCTOR_PARAM_TYPES); //$NON-NLS-1$
0284:                if (result.hasMethodWriteObject()) {
0285:                    flags |= ObjectStreamConstants.SC_WRITE_METHOD;
0286:                }
0287:                result.setFlags(flags);
0288:
0289:                return result;
0290:            }
0291:
0292:            /**
0293:             * Builds the collection of field descriptors for the receiver
0294:             * 
0295:             * @param declaredFields
0296:             *            collection of java.lang.reflect.Field for which to compute
0297:             *            field descriptors
0298:             */
0299:            void buildFieldDescriptors(Field[] declaredFields) {
0300:                // We could find the field ourselves in the collection, but calling
0301:                // reflect is easier. Optimize if needed.
0302:                final Field f = ObjectStreamClass
0303:                        .fieldSerialPersistentFields(this .forClass());
0304:                // If we could not find the emulated fields, we'll have to compute
0305:                // dumpable fields from reflect fields
0306:                boolean useReflectFields = f == null; // Assume we will compute the
0307:                // fields to dump based on the
0308:                // reflect fields
0309:
0310:                ObjectStreamField[] _fields = null;
0311:                if (!useReflectFields) {
0312:                    // The user declared a collection of emulated fields. Use them.
0313:                    // We have to be able to fetch its value, even if it is private
0314:                    AccessController.doPrivileged(new PriviAction<Object>(f));
0315:                    try {
0316:                        // static field, pass null
0317:                        _fields = (ObjectStreamField[]) f.get(null);
0318:                    } catch (IllegalAccessException ex) {
0319:                        // WARNING - what should we do if we have no access ? This
0320:                        // should not happen.
0321:                        throw new RuntimeException(ex);
0322:                    }
0323:                } else {
0324:                    // Compute collection of dumpable fields based on reflect fields
0325:                    List<ObjectStreamField> serializableFields = new ArrayList<ObjectStreamField>(
0326:                            declaredFields.length);
0327:                    // Filter, we are only interested in fields that are serializable
0328:                    for (int i = 0; i < declaredFields.length; i++) {
0329:                        Field declaredField = declaredFields[i];
0330:                        int modifiers = declaredField.getModifiers();
0331:                        boolean shouldBeSerialized = !(Modifier
0332:                                .isStatic(modifiers) || Modifier
0333:                                .isTransient(modifiers));
0334:                        if (shouldBeSerialized) {
0335:                            ObjectStreamField field = new ObjectStreamField(
0336:                                    declaredField.getName(), declaredField
0337:                                            .getType());
0338:                            serializableFields.add(field);
0339:                        }
0340:                    }
0341:
0342:                    if (serializableFields.size() == 0) {
0343:                        _fields = NO_FIELDS; // If no serializable fields, share the
0344:                        // special value so that users can test
0345:                    } else {
0346:                        // Now convert from Vector to array
0347:                        _fields = new ObjectStreamField[serializableFields
0348:                                .size()];
0349:                        _fields = serializableFields.toArray(_fields);
0350:                    }
0351:                }
0352:                ObjectStreamField.sortFields(_fields);
0353:                // assign offsets
0354:                int primOffset = 0, objectOffset = 0;
0355:                for (int i = 0; i < _fields.length; i++) {
0356:                    Class<?> type = _fields[i].getType();
0357:                    if (type.isPrimitive()) {
0358:                        _fields[i].offset = primOffset;
0359:                        primOffset += primitiveSize(type);
0360:                    } else {
0361:                        _fields[i].offset = objectOffset++;
0362:                    }
0363:                }
0364:                fields = _fields;
0365:            }
0366:
0367:            /**
0368:             * Compute and return the Serial Version UID of the class <code>cl</code>.
0369:             * The value is computed based on the class name, superclass chain, field
0370:             * names, method names, modifiers, etc.
0371:             * 
0372:             * @param cl
0373:             *            a java.lang.Class for which to compute the SUID
0374:             * @param fields
0375:             *            cl.getDeclaredFields(), pre-computed by the caller
0376:             * @return the value of SUID of this class
0377:             */
0378:            private static long computeSerialVersionUID(Class<?> cl,
0379:                    Field[] fields) {
0380:                /*
0381:                 * First we should try to fetch the static slot 'static final long
0382:                 * serialVersionUID'. If it is defined, return it. If not defined, we
0383:                 * really need to compute SUID using SHAOutputStream
0384:                 */
0385:                for (int i = 0; i < fields.length; i++) {
0386:                    final Field field = fields[i];
0387:                    if (Long.TYPE == field.getType()) {
0388:                        int modifiers = field.getModifiers();
0389:                        if (Modifier.isStatic(modifiers)
0390:                                && Modifier.isFinal(modifiers)) {
0391:                            if (UID_FIELD_NAME.equals(field.getName())) {
0392:                                /*
0393:                                 * We need to be able to see it even if we have no
0394:                                 * visibility. That is why we set accessible first (new
0395:                                 * API in reflect 1.2)
0396:                                 */
0397:                                AccessController
0398:                                        .doPrivileged(new PriviAction<Object>(
0399:                                                field));
0400:                                try {
0401:                                    // Static field, parameter is ignored
0402:                                    return field.getLong(null);
0403:                                } catch (IllegalAccessException iae) {
0404:                                    throw new RuntimeException(Msg.getString(
0405:                                            "K0071", iae)); //$NON-NLS-1$
0406:                                }
0407:                            }
0408:                        }
0409:                    }
0410:                }
0411:
0412:                MessageDigest digest;
0413:                try {
0414:                    digest = MessageDigest.getInstance("SHA"); //$NON-NLS-1$
0415:                } catch (NoSuchAlgorithmException e) {
0416:                    throw new Error(e);
0417:                }
0418:                ByteArrayOutputStream sha = new ByteArrayOutputStream();
0419:                try {
0420:                    DataOutputStream output = new DataOutputStream(sha);
0421:                    output.writeUTF(cl.getName());
0422:                    int classModifiers = CLASS_MODIFIERS_MASK
0423:                            & cl.getModifiers();
0424:                    /*
0425:                     * Workaround for 1F9LOQO. Arrays are ABSTRACT in JDK, but that is
0426:                     * not in the specification. Since we want to be compatible for
0427:                     * X-loading, we have to pretend we have the same shape
0428:                     */
0429:                    boolean isArray = cl.isArray();
0430:                    if (isArray) {
0431:                        classModifiers |= Modifier.ABSTRACT;
0432:                    }
0433:                    // Required for JDK UID compatibility
0434:                    if (cl.isInterface() && !Modifier.isPublic(classModifiers)) {
0435:                        classModifiers &= ~Modifier.ABSTRACT;
0436:                    }
0437:                    output.writeInt(classModifiers);
0438:
0439:                    /*
0440:                     * In JDK1.2 arrays implement Cloneable and Serializable but not in
0441:                     * JDK 1.1.7. So, JDK 1.2 "pretends" arrays have no interfaces when
0442:                     * computing SHA-1 to be compatible.
0443:                     */
0444:                    if (!isArray) {
0445:                        // Interface information
0446:                        Class<?>[] interfaces = cl.getInterfaces();
0447:                        if (interfaces.length > 1) {
0448:                            // Only attempt to sort if really needed (saves object
0449:                            // creation, etc)
0450:                            Comparator<Class<?>> interfaceComparator = new Comparator<Class<?>>() {
0451:                                public int compare(Class<?> itf1, Class<?> itf2) {
0452:                                    return itf1.getName().compareTo(
0453:                                            itf2.getName());
0454:                                }
0455:                            };
0456:                            Arrays.sort(interfaces, interfaceComparator);
0457:                        }
0458:
0459:                        // Dump them
0460:                        for (int i = 0; i < interfaces.length; i++) {
0461:                            output.writeUTF(interfaces[i].getName());
0462:                        }
0463:                    }
0464:
0465:                    // Field information
0466:                    if (fields.length > 1) {
0467:                        // Only attempt to sort if really needed (saves object creation,
0468:                        // etc)
0469:                        Comparator<Field> fieldComparator = new Comparator<Field>() {
0470:                            public int compare(Field field1, Field field2) {
0471:                                return field1.getName().compareTo(
0472:                                        field2.getName());
0473:                            }
0474:                        };
0475:                        Arrays.sort(fields, fieldComparator);
0476:                    }
0477:
0478:                    // Dump them
0479:                    for (int i = 0; i < fields.length; i++) {
0480:                        Field field = fields[i];
0481:                        int modifiers = field.getModifiers()
0482:                                & FIELD_MODIFIERS_MASK;
0483:
0484:                        boolean skip = Modifier.isPrivate(modifiers)
0485:                                && (Modifier.isTransient(modifiers) || Modifier
0486:                                        .isStatic(modifiers));
0487:                        if (!skip) {
0488:                            // write name, modifier & "descriptor" of all but private
0489:                            // static and private transient
0490:                            output.writeUTF(field.getName());
0491:                            output.writeInt(modifiers);
0492:                            output
0493:                                    .writeUTF(descriptorForFieldSignature(getFieldSignature(field)));
0494:                        }
0495:                    }
0496:
0497:                    /*
0498:                     * Normally constructors come before methods (because <init> <
0499:                     * anyMethodName). However, <clinit> is an exception. Besides,
0500:                     * reflect will not let us get to it.
0501:                     */
0502:                    if (hasClinit(cl)) {
0503:                        // write name, modifier & "descriptor"
0504:                        output.writeUTF(CLINIT_NAME);
0505:                        output.writeInt(CLINIT_MODIFIERS);
0506:                        output.writeUTF(CLINIT_SIGNATURE);
0507:                    }
0508:
0509:                    // Constructor information
0510:                    Constructor<?>[] constructors = cl
0511:                            .getDeclaredConstructors();
0512:                    if (constructors.length > 1) {
0513:                        // Only attempt to sort if really needed (saves object creation,
0514:                        // etc)
0515:                        Comparator<Constructor<?>> constructorComparator = new Comparator<Constructor<?>>() {
0516:                            public int compare(Constructor<?> ctr1,
0517:                                    Constructor<?> ctr2) {
0518:                                // All constructors have same name, so we sort based on
0519:                                // signature
0520:                                return (getConstructorSignature(ctr1)
0521:                                        .compareTo(getConstructorSignature(ctr2)));
0522:                            }
0523:                        };
0524:                        Arrays.sort(constructors, constructorComparator);
0525:                    }
0526:
0527:                    // Dump them
0528:                    for (int i = 0; i < constructors.length; i++) {
0529:                        Constructor<?> constructor = constructors[i];
0530:                        int modifiers = constructor.getModifiers()
0531:                                & METHOD_MODIFIERS_MASK;
0532:                        boolean isPrivate = Modifier.isPrivate(modifiers);
0533:                        if (!isPrivate) {
0534:                            /*
0535:                             * write name, modifier & "descriptor" of all but private
0536:                             * ones
0537:                             * 
0538:                             * constructor.getName() returns the constructor name as
0539:                             * typed, not the VM name
0540:                             */
0541:                            output.writeUTF("<init>"); //$NON-NLS-1$
0542:                            output.writeInt(modifiers);
0543:                            output.writeUTF(descriptorForSignature(
0544:                                    getConstructorSignature(constructor))
0545:                                    .replace('/', '.'));
0546:                        }
0547:                    }
0548:
0549:                    // Method information
0550:                    Method[] methods = cl.getDeclaredMethods();
0551:                    if (methods.length > 1) {
0552:                        Comparator<Method> methodComparator = new Comparator<Method>() {
0553:                            public int compare(Method m1, Method m2) {
0554:                                int result = m1.getName().compareTo(
0555:                                        m2.getName());
0556:                                if (result == 0) {
0557:                                    // same name, signature will tell which one comes
0558:                                    // first
0559:                                    return getMethodSignature(m1).compareTo(
0560:                                            getMethodSignature(m2));
0561:                                }
0562:                                return result;
0563:                            }
0564:                        };
0565:                        Arrays.sort(methods, methodComparator);
0566:                    }
0567:
0568:                    // Dump them
0569:                    for (int i = 0; i < methods.length; i++) {
0570:                        Method method = methods[i];
0571:                        int modifiers = method.getModifiers()
0572:                                & METHOD_MODIFIERS_MASK;
0573:                        boolean isPrivate = Modifier.isPrivate(modifiers);
0574:                        if (!isPrivate) {
0575:                            // write name, modifier & "descriptor" of all but private
0576:                            // ones
0577:                            output.writeUTF(method.getName());
0578:                            output.writeInt(modifiers);
0579:                            output.writeUTF(descriptorForSignature(
0580:                                    getMethodSignature(method)).replace('/',
0581:                                    '.'));
0582:                        }
0583:                    }
0584:                } catch (IOException e) {
0585:                    throw new RuntimeException(Msg.getString("K0072", e));//$NON-NLS-1$
0586:                }
0587:
0588:                // now compute the UID based on the SHA
0589:                byte[] hash = digest.digest(sha.toByteArray());
0590:
0591:                return littleEndianLongAt(hash, 0);
0592:            }
0593:
0594:            /**
0595:             * Return what the serializaton specification calls "descriptor" given a
0596:             * field signature. signature.
0597:             * 
0598:             * @param signature
0599:             *            a field signature
0600:             * @return containing the descriptor
0601:             */
0602:            private static String descriptorForFieldSignature(String signature) {
0603:                return signature.replace('.', '/');
0604:            }
0605:
0606:            /**
0607:             * Return what the serializaton specification calls "descriptor" given a
0608:             * method/constructor signature.
0609:             * 
0610:             * @param signature
0611:             *            a method or constructor signature
0612:             * @return containing the descriptor
0613:             */
0614:            private static String descriptorForSignature(String signature) {
0615:                return signature.substring(signature.indexOf("(")); //$NON-NLS-1$
0616:            }
0617:
0618:            /**
0619:             * Return the java.lang.reflect.Field <code>serialPersistentFields</code>
0620:             * if class <code>cl</code> implements it. Return null otherwise.
0621:             * 
0622:             * @param cl
0623:             *            a java.lang.Class which to test
0624:             * @return <code>java.lang.reflect.Field</code> if the class has
0625:             *         serialPersistentFields <code>null</code> if the class does not
0626:             *         have serialPersistentFields
0627:             */
0628:            static Field fieldSerialPersistentFields(Class<?> cl) {
0629:                try {
0630:                    Field f = cl.getDeclaredField("serialPersistentFields"); //$NON-NLS-1$
0631:                    int modifiers = f.getModifiers();
0632:                    if (Modifier.isStatic(modifiers)
0633:                            && Modifier.isPrivate(modifiers)
0634:                            && Modifier.isFinal(modifiers)) {
0635:                        if (f.getType() == ARRAY_OF_FIELDS) {
0636:                            return f;
0637:                        }
0638:                    }
0639:                } catch (NoSuchFieldException nsm) {
0640:                    // Ignored
0641:                }
0642:                return null;
0643:            }
0644:
0645:            /**
0646:             * Return the class (java.lang.Class) that the receiver represents
0647:             * 
0648:             * @return <code>null</code> if there is no corresponding class for the
0649:             *         receiver <code>Class</code> The loaded class corresponding to
0650:             *         the receiver
0651:             */
0652:            public Class<?> forClass() {
0653:                if (resolvedClass != null) {
0654:                    return resolvedClass.get();
0655:                }
0656:                return null;
0657:            }
0658:
0659:            /**
0660:             * Return a String representing the signature for a Constructor
0661:             * <code>c</code>.
0662:             * 
0663:             * @param c
0664:             *            a java.lang.reflect.Constructor for which to compute the
0665:             *            signature
0666:             * @return the constructor's signature
0667:             * 
0668:             */
0669:            static native String getConstructorSignature(Constructor<?> c);
0670:
0671:            /**
0672:             * Answers a given field by name.
0673:             * 
0674:             * @param name
0675:             *            name of the desired field.
0676:             * @return a given field by name.
0677:             */
0678:            public ObjectStreamField getField(String name) {
0679:                ObjectStreamField[] allFields = getFields();
0680:                for (int i = 0; i < allFields.length; i++) {
0681:                    ObjectStreamField f = allFields[i];
0682:                    if (f.getName().equals(name)) {
0683:                        return f;
0684:                    }
0685:                }
0686:                return null;
0687:            }
0688:
0689:            /**
0690:             * Answers the collection of field descriptors for the fields of the
0691:             * corresponding class
0692:             * 
0693:             * @return the receiver's collection of declared fields for the class it
0694:             *         represents
0695:             */
0696:            ObjectStreamField[] fields() {
0697:                if (fields == null) {
0698:                    Class<?> forCl = forClass();
0699:                    if (forCl != null && isSerializable(forCl)
0700:                            && !forCl.isArray()) {
0701:                        buildFieldDescriptors(forCl.getDeclaredFields());
0702:                    } else {
0703:                        // Externalizables or arrays do not need FieldDesc info
0704:                        setFields(NO_FIELDS);
0705:                    }
0706:                }
0707:                return fields;
0708:            }
0709:
0710:            /**
0711:             * Answers the collection of field descriptors for the fields of the
0712:             * corresponding class
0713:             * 
0714:             * @return the receiver's collection of declared fields for the class it
0715:             *         represents
0716:             */
0717:            public ObjectStreamField[] getFields() {
0718:                copyFieldAttributes();
0719:                return loadFields == null ? fields().clone() : loadFields
0720:                        .clone();
0721:            }
0722:
0723:            /**
0724:             * If a Class uses "serialPersistentFields" to define the serialized fields,
0725:             * this.loadFields cannot get the "unshared" information when deserializing
0726:             * fields using current implementation of ObjectInputStream. This method
0727:             * provides a way to copy the "unshared" attribute from this.fields.
0728:             * 
0729:             */
0730:            private void copyFieldAttributes() {
0731:                if ((loadFields == null) || fields == null) {
0732:                    return;
0733:                }
0734:
0735:                for (int i = 0; i < loadFields.length; i++) {
0736:                    ObjectStreamField loadField = loadFields[i];
0737:                    String name = loadField.getName();
0738:                    for (int j = 0; j < fields.length; j++) {
0739:                        ObjectStreamField field = fields[j];
0740:                        if (name.equals(field.getName())) {
0741:                            loadField.setUnshared(field.isUnshared());
0742:                            loadField.setOffset(field.getOffset());
0743:                            break;
0744:                        }
0745:                    }
0746:                }
0747:            }
0748:
0749:            /**
0750:             * Answers the collection of field descriptors for the input fields of the
0751:             * corresponding class
0752:             * 
0753:             * @return the receiver's collection of input fields for the class it
0754:             *         represents
0755:             */
0756:            ObjectStreamField[] getLoadFields() {
0757:                return loadFields;
0758:            }
0759:
0760:            /**
0761:             * Return a String representing the signature for a field <code>f</code>.
0762:             * 
0763:             * @param f
0764:             *            a java.lang.reflect.Field for which to compute the signature
0765:             * @return the field's signature
0766:             */
0767:            private static native String getFieldSignature(Field f);
0768:
0769:            /**
0770:             * Answers the flags for this descriptor, where possible combined values are
0771:             * 
0772:             * ObjectStreamConstants.SC_WRITE_METHOD
0773:             * ObjectStreamConstants.SC_SERIALIZABLE
0774:             * ObjectStreamConstants.SC_EXTERNALIZABLE
0775:             * 
0776:             * @return byte the receiver's flags for the class it represents
0777:             */
0778:            byte getFlags() {
0779:                return flags;
0780:            }
0781:
0782:            /**
0783:             * Return a String representing the signature for a method <code>m</code>.
0784:             * 
0785:             * @param m
0786:             *            a java.lang.reflect.Method for which to compute the signature
0787:             * @return the method's signature
0788:             */
0789:            static native String getMethodSignature(Method m);
0790:
0791:            /**
0792:             * Answers the name of the class represented by the receiver
0793:             * 
0794:             * @return fully qualified name of the class the receiver represents
0795:             */
0796:            public String getName() {
0797:                return className;
0798:            }
0799:
0800:            /**
0801:             * Answers the Serial Version User ID of the class represented by the
0802:             * receiver
0803:             * 
0804:             * @return SUID for the class represented by the receiver
0805:             */
0806:            public long getSerialVersionUID() {
0807:                return svUID;
0808:            }
0809:
0810:            /**
0811:             * Answers the descriptor (ObjectStreamClass) of the superclass of the class
0812:             * represented by the receiver.
0813:             * 
0814:             * @return an ObjectStreamClass representing the superclass of the class
0815:             *         represented by the receiver.
0816:             */
0817:            ObjectStreamClass getSuperclass() {
0818:                return super class;
0819:            }
0820:
0821:            /**
0822:             * Return true if the given class <code>cl</code> has the
0823:             * compiler-generated method <code>clinit</code>. Even though it is
0824:             * compiler-generated, it is used by the serialization code to compute SUID.
0825:             * This is unfortunate, since it may depend on compiler optimizations in
0826:             * some cases.
0827:             * 
0828:             * @param cl
0829:             *            a java.lang.Class which to test
0830:             * @return <code>true</code> if the class has <clinit> <code>false</code>
0831:             *         if the class does not have <clinit>
0832:             */
0833:            private static native boolean hasClinit(Class<?> cl);
0834:
0835:            /**
0836:             * Return true if instances of class <code>cl</code> are Externalizable,
0837:             * false otherwise.
0838:             * 
0839:             * @param cl
0840:             *            a java.lang.Class which to test
0841:             * @return <code>true</code> if instances of the class are Externalizable
0842:             *         <code>false</code> if instances of the class are not
0843:             *         Externalizable
0844:             * 
0845:             * @see Object#hashCode
0846:             */
0847:            static boolean isExternalizable(Class<?> cl) {
0848:                return EXTERNALIZABLE.isAssignableFrom(cl);
0849:            }
0850:
0851:            /**
0852:             * Return true if the type code
0853:             * <code>typecode<code> describes a primitive type
0854:             *
0855:             * @param typecode a char describing the typecode
0856:             * @return <code>true</code> if the typecode represents a primitive type 
0857:             * <code>false</code> if the typecode represents an Object type (including arrays)
0858:             *
0859:             * @see	Object#hashCode
0860:             */
0861:            static boolean isPrimitiveType(char typecode) {
0862:                return !(typecode == '[' || typecode == 'L');
0863:            }
0864:
0865:            /**
0866:             * Return true if instances of class <code>cl</code> are Serializable,
0867:             * false otherwise.
0868:             * 
0869:             * @param cl
0870:             *            a java.lang.Class which to test
0871:             * @return <code>true</code> if instances of the class are Serializable
0872:             *         <code>false</code> if instances of the class are not
0873:             *         Serializable
0874:             * 
0875:             * @see Object#hashCode
0876:             */
0877:            static boolean isSerializable(Class<?> cl) {
0878:                return SERIALIZABLE.isAssignableFrom(cl);
0879:            }
0880:
0881:            /**
0882:             * Return a little endian long stored in a given position of the buffer
0883:             * 
0884:             * @param buffer
0885:             *            a byte array with the byte representation of the number
0886:             * @param position
0887:             *            index where the number starts in the byte array
0888:             * @return the number that was stored in little endian format
0889:             */
0890:            private static long littleEndianLongAt(byte[] buffer, int position) {
0891:                long result = 0;
0892:                for (int i = position + 7; i >= position; i--) {
0893:                    result = (result << 8) + (buffer[i] & 0xff);
0894:                }
0895:                return result;
0896:            }
0897:
0898:            /**
0899:             * Return the descriptor (ObjectStreamClass) corresponding to the class
0900:             * <code>cl</code>. If the class is not Serializable or Externalizable,
0901:             * null is returned.
0902:             * 
0903:             * @param cl
0904:             *            a java.langClass for which to obtain the corresponding
0905:             *            descriptor
0906:             * @return <code>null</code> if instances of the class <code>cl</code>
0907:             *         are not Serializable or Externalizable
0908:             *         <code>ObjectStreamClass</code> The corresponding descriptor if
0909:             *         the class <code>cl</code> is Serializable or Externalizable
0910:             */
0911:            public static ObjectStreamClass lookup(Class<?> cl) {
0912:                boolean serializable = isSerializable(cl);
0913:                boolean externalizable = isExternalizable(cl);
0914:
0915:                // Has to be either Serializable or Externalizable
0916:                if (!serializable && !externalizable) {
0917:                    return null;
0918:                }
0919:
0920:                return lookupStreamClass(cl, true);
0921:            }
0922:
0923:            /**
0924:             * Return the descriptor (ObjectStreamClass) corresponding to the class
0925:             * <code>cl</code>. Returns an ObjectStreamClass even if instances of the
0926:             * class cannot be serialized
0927:             * 
0928:             * @param cl
0929:             *            a java.langClass for which to obtain the corresponding
0930:             *            descriptor
0931:             * @return the corresponding descriptor
0932:             */
0933:            static ObjectStreamClass lookupStreamClass(Class<?> cl) {
0934:                return lookupStreamClass(cl, isSerializable(cl)
0935:                        || isExternalizable(cl));
0936:            }
0937:
0938:            /**
0939:             * Return the descriptor (ObjectStreamClass) corresponding to the class
0940:             * <code>cl</code>. Returns an ObjectStreamClass even if instances of the
0941:             * class cannot be serialized
0942:             * 
0943:             * @param cl
0944:             *            a <code>java.langClass</code> for which to obtain the
0945:             *            corresponding descriptor
0946:             * @param computeSUID
0947:             *            a boolean indicating if SUID should be computed or not.
0948:             * @return the corresponding descriptor
0949:             */
0950:            private static ObjectStreamClass lookupStreamClass(Class<?> cl,
0951:                    boolean computeSUID) {
0952:                // Synchronized because of the lookup table 'classesAndDescriptors'
0953:
0954:                ObjectStreamClass cachedValue;
0955:                synchronized (classesAndDescriptors) {
0956:                    cachedValue = classesAndDescriptors.get(cl);
0957:                    if (cachedValue == null) {
0958:                        cachedValue = createClassDesc(cl, computeSUID);
0959:                        classesAndDescriptors.put(cl, cachedValue);
0960:                    }
0961:                }
0962:                return cachedValue;
0963:
0964:            }
0965:
0966:            /**
0967:             * Return the java.lang.reflect.Method if class <code>cl</code> implements
0968:             * <code>methodName</code> . Return null otherwise.
0969:             * 
0970:             * @param cl
0971:             *            a java.lang.Class which to test
0972:             * @return <code>java.lang.reflect.Method</code> if the class implements
0973:             *         writeReplace <code>null</code> if the class does not implement
0974:             *         writeReplace
0975:             */
0976:            static Method findMethod(Class<?> cl, String methodName) {
0977:                Class<?> search = cl;
0978:                Method method = null;
0979:                while (search != null) {
0980:                    try {
0981:                        method = search.getDeclaredMethod(methodName,
0982:                                (Class[]) null);
0983:                        if (search == cl
0984:                                || (method.getModifiers() & Modifier.PRIVATE) == 0) {
0985:                            method.setAccessible(true);
0986:                            return method;
0987:                        }
0988:                    } catch (NoSuchMethodException nsm) {
0989:                    }
0990:                    search = search.getSuperclass();
0991:                }
0992:                return null;
0993:            }
0994:
0995:            /**
0996:             * Return the java.lang.reflect.Method if class <code>cl</code> implements
0997:             * private <code>methodName</code> . Return null otherwise.
0998:             * 
0999:             * @param cl
1000:             *            a java.lang.Class which to test
1001:             * @return <code>java.lang.reflect.Method</code> if the class implements
1002:             *         writeReplace <code>null</code> if the class does not implement
1003:             *         writeReplace
1004:             */
1005:            static Method findPrivateMethod(Class<?> cl, String methodName,
1006:                    Class<?>[] param) {
1007:                try {
1008:                    Method method = cl.getDeclaredMethod(methodName, param);
1009:                    if (Modifier.isPrivate(method.getModifiers())
1010:                            && method.getReturnType() == VOID_CLASS) {
1011:                        method.setAccessible(true);
1012:                        return method;
1013:                    }
1014:                } catch (NoSuchMethodException nsm) {
1015:                    // Ignored
1016:                }
1017:                return null;
1018:            }
1019:
1020:            boolean hasMethodWriteReplace() {
1021:                return (methodWriteReplace != null);
1022:            }
1023:
1024:            Method getMethodWriteReplace() {
1025:                return methodWriteReplace;
1026:            }
1027:
1028:            boolean hasMethodReadResolve() {
1029:                return (methodReadResolve != null);
1030:            }
1031:
1032:            Method getMethodReadResolve() {
1033:                return methodReadResolve;
1034:            }
1035:
1036:            boolean hasMethodWriteObject() {
1037:                return (methodWriteObject != null);
1038:            }
1039:
1040:            Method getMethodWriteObject() {
1041:                return methodWriteObject;
1042:            }
1043:
1044:            boolean hasMethodReadObject() {
1045:                return (methodReadObject != null);
1046:            }
1047:
1048:            Method getMethodReadObject() {
1049:                return methodReadObject;
1050:            }
1051:
1052:            boolean hasMethodReadObjectNoData() {
1053:                return (methodReadObjectNoData != null);
1054:            }
1055:
1056:            Method getMethodReadObjectNoData() {
1057:                return methodReadObjectNoData;
1058:            }
1059:
1060:            void initPrivateFields(ObjectStreamClass desc) {
1061:                methodWriteReplace = desc.methodWriteReplace;
1062:                methodReadResolve = desc.methodReadResolve;
1063:                methodWriteObject = desc.methodWriteObject;
1064:                methodReadObject = desc.methodReadObject;
1065:                methodReadObjectNoData = desc.methodReadObjectNoData;
1066:            }
1067:
1068:            /**
1069:             * Set the class (java.lang.Class) that the receiver represents
1070:             * 
1071:             * @param c
1072:             *            aClass, the new class that the receiver describes
1073:             */
1074:            void setClass(Class<?> c) {
1075:                resolvedClass = new WeakReference<Class<?>>(c);
1076:            }
1077:
1078:            /**
1079:             * Set the collection of field descriptors for the fields of the
1080:             * corresponding class
1081:             * 
1082:             * @param f
1083:             *            ObjectStreamField[], the receiver's new collection of declared
1084:             *            fields for the class it represents
1085:             */
1086:            void setFields(ObjectStreamField[] f) {
1087:                fields = f;
1088:            }
1089:
1090:            /**
1091:             * Set the collection of field descriptors for the input fields of the
1092:             * corresponding class
1093:             * 
1094:             * @param f
1095:             *            ObjectStreamField[], the receiver's new collection of input
1096:             *            fields for the class it represents
1097:             */
1098:            void setLoadFields(ObjectStreamField[] f) {
1099:                loadFields = f;
1100:            }
1101:
1102:            /**
1103:             * Set the flags for this descriptor, where possible combined values are
1104:             * 
1105:             * ObjectStreamConstants.SC_WRITE_METHOD
1106:             * ObjectStreamConstants.SC_SERIALIZABLE
1107:             * ObjectStreamConstants.SC_EXTERNALIZABLE
1108:             * 
1109:             * @param b
1110:             *            byte, the receiver's new flags for the class it represents
1111:             */
1112:            void setFlags(byte b) {
1113:                flags = b;
1114:            }
1115:
1116:            /**
1117:             * Set the name of the class represented by the receiver
1118:             * 
1119:             * @param newName
1120:             *            a String, the new fully qualified name of the class the
1121:             *            receiver represents
1122:             */
1123:            void setName(String newName) {
1124:                className = newName;
1125:            }
1126:
1127:            /**
1128:             * Set the Serial Version User ID of the class represented by the receiver
1129:             * 
1130:             * @param l
1131:             *            a long, the new SUID for the class represented by the receiver
1132:             */
1133:            void setSerialVersionUID(long l) {
1134:                svUID = l;
1135:            }
1136:
1137:            /**
1138:             * Set the descriptor for the superclass of the class described by the
1139:             * receiver
1140:             * 
1141:             * @param c
1142:             *            an ObjectStreamClass, the new ObjectStreamClass for the
1143:             *            superclass of the class represented by the receiver
1144:             */
1145:            void setSuperclass(ObjectStreamClass c) {
1146:                super class = c;
1147:            }
1148:
1149:            private int primitiveSize(Class<?> type) {
1150:                if (type == Byte.TYPE || type == Boolean.TYPE) {
1151:                    return 1;
1152:                }
1153:                if (type == Short.TYPE || type == Character.TYPE) {
1154:                    return 2;
1155:                }
1156:                if (type == Integer.TYPE || type == Float.TYPE) {
1157:                    return 4;
1158:                }
1159:                if (type == Long.TYPE || type == Double.TYPE) {
1160:                    return 8;
1161:                }
1162:                return 0;
1163:            }
1164:
1165:            /**
1166:             * Answers a string containing a concise, human-readable description of the
1167:             * receiver.
1168:             * 
1169:             * @return a printable representation for the receiver.
1170:             */
1171:            @Override
1172:            public String toString() {
1173:                return getName() + ": static final long serialVersionUID =" //$NON-NLS-1$
1174:                        + getSerialVersionUID() + "L;"; //$NON-NLS-1$
1175:            }
1176:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.