Source Code Cross Referenced for ObjectStreamClass.java in  » 6.0-JDK-Modules » j2me » 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 » 6.0 JDK Modules » j2me » java.io 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * @(#)ObjectStreamClass.java	1.116 06/10/10
0003:         *
0004:         * Copyright  1990-2006 Sun Microsystems, Inc. All Rights Reserved.  
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER  
0006:         *   
0007:         * This program is free software; you can redistribute it and/or  
0008:         * modify it under the terms of the GNU General Public License version  
0009:         * 2 only, as published by the Free Software Foundation.   
0010:         *   
0011:         * This program is distributed in the hope that it will be useful, but  
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of  
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
0014:         * General Public License version 2 for more details (a copy is  
0015:         * included at /legal/license.txt).   
0016:         *   
0017:         * You should have received a copy of the GNU General Public License  
0018:         * version 2 along with this work; if not, write to the Free Software  
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
0020:         * 02110-1301 USA   
0021:         *   
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa  
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional  
0024:         * information or have any questions. 
0025:         *
0026:         */
0027:
0028:        package java.io;
0029:
0030:        import java.lang.reflect.Constructor;
0031:        import java.lang.reflect.Field;
0032:        import java.lang.reflect.InvocationTargetException;
0033:        import java.lang.reflect.Member;
0034:        import java.lang.reflect.Method;
0035:        import java.lang.reflect.Modifier;
0036:        import java.lang.reflect.Proxy;
0037:        import java.security.AccessController;
0038:        import java.security.MessageDigest;
0039:        import java.security.NoSuchAlgorithmException;
0040:        import java.security.PrivilegedAction;
0041:        import java.util.ArrayList;
0042:        import java.util.Arrays;
0043:        import java.util.Collections;
0044:        import java.util.Comparator;
0045:        import sun.misc.SoftCache;
0046:
0047:        // import sun.misc.Unsafe;  // - Back-ported from JDK 1.4
0048:        // import sun.reflect.ReflectionFactory;  // - Back-ported from JDK 1.4 
0049:
0050:        /* Back-ported JDK 1.4 implementation  */
0051:
0052:        /**
0053:         * Serialization's descriptor for classes.
0054:         * It contains the name and serialVersionUID of the class.
0055:         * <br>
0056:         * The ObjectStreamClass for a specific class loaded in this Java VM can
0057:         * be found/created using the lookup method.<p>
0058:         * The algorithm to compute the SerialVersionUID is described in 
0059:         * <a href="../../../guide/serialization/spec/class.doc4.html"> Object Serialization Specification, Section 4.4, Stream Unique Identifiers</a>.
0060:         *
0061:         * @author	Mike Warres
0062:         * @author	Roger Riggs
0063:         * @version 1.98 02/02/00
0064:         * @see ObjectStreamField
0065:         * @see <a href="../../../guide/serialization/spec/class.doc.html"> Object Serialization Specification, Section 4, Class Descriptors</a>
0066:         * @since   JDK1.1
0067:         */
0068:        public class ObjectStreamClass implements  Serializable {
0069:
0070:            /** serialPersistentFields value indicating no serializable fields */
0071:            public static final ObjectStreamField[] NO_FIELDS = new ObjectStreamField[0];
0072:
0073:            private static final long serialVersionUID = -6120832682080437368L;
0074:            private static final ObjectStreamField[] serialPersistentFields = NO_FIELDS;
0075:
0076:            /** reflection factory for obtaining serialization constructors */
0077:            /* // - Back-ported from JDK 1.4 
0078:            private static final ReflectionFactory reflFactory = (ReflectionFactory)
0079:            AccessController.doPrivileged(
0080:                new ReflectionFactory.GetReflectionFactoryAction());
0081:             */
0082:
0083:            /** cache mapping local classes -> descriptors */
0084:            private static final SoftCache localDescs = new SoftCache(10);
0085:            /** cache mapping field group/local desc pairs -> field reflectors */
0086:            private static final SoftCache reflectors = new SoftCache(10);
0087:
0088:            /** class associated with this descriptor (if any) */
0089:            private Class cl;
0090:            /** name of class represented by this descriptor */
0091:            private String name;
0092:            /** serialVersionUID of represented class (null if not computed yet) */
0093:            private volatile Long suid;
0094:
0095:            /** true if represents dynamic proxy class */
0096:            private boolean isProxy;
0097:            /** true if represented class implements Serializable */
0098:            private boolean serializable;
0099:            /** true if represented class implements Externalizable */
0100:            private boolean externalizable;
0101:            /** true if desc has data written by class-defined writeObject method */
0102:            private boolean hasWriteObjectData;
0103:            /** 
0104:             * true if desc has externalizable data written in block data format; this
0105:             * must be true by default to accomodate ObjectInputStream subclasses which
0106:             * override readClassDescriptor() to return class descriptors obtained from
0107:             * ObjectStreamClass.lookup() (see 4461737)
0108:             */
0109:            private boolean hasBlockExternalData = true;
0110:
0111:            /** exception (if any) thrown while attempting to resolve class */
0112:            private ClassNotFoundException resolveEx;
0113:            /** exception (if any) to be thrown if deserialization attempted */
0114:            private InvalidClassException deserializeEx;
0115:            /** exception (if any) to be thrown if default serialization attempted */
0116:            private InvalidClassException defaultSerializeEx;
0117:
0118:            /** serializable fields */
0119:            private ObjectStreamField[] fields;
0120:            /** aggregate marshalled size of primitive fields */
0121:            private int primDataSize;
0122:            /** number of non-primitive fields */
0123:            private int numObjFields;
0124:            /** reflector for setting/getting serializable field values */
0125:            private FieldReflector fieldRefl;
0126:            /** data layout of serialized objects described by this class desc */
0127:            private volatile ClassDataSlot[] dataLayout;
0128:
0129:            /** serialization-appropriate constructor, or null if none */
0130:            // private Constructor cons; // - Back-ported from JDK 1.4 
0131:            /** class-defined writeObject method, or null if none */
0132:            private Method writeObjectMethod;
0133:            /** class-defined readObject method, or null if none */
0134:            private Method readObjectMethod;
0135:            /** class-defined readObjectNoData method, or null if none */
0136:            private Method readObjectNoDataMethod;
0137:            /** class-defined writeReplace method, or null if none */
0138:            private Method writeReplaceMethod;
0139:            /** class-defined readResolve method, or null if none */
0140:            private Method readResolveMethod;
0141:
0142:            /** local class descriptor for represented class (may point to self) */
0143:            private ObjectStreamClass localDesc;
0144:            /** superclass descriptor appearing in stream */
0145:            private ObjectStreamClass super Desc;
0146:
0147:            /** Class to be initialized -- for back-port to J2ME Foundation */
0148:            private Class initClass; // - Back-ported from JDK 1.4 
0149:
0150:            /**
0151:             * Initializes native code.
0152:             */
0153:            private static native void initNative();
0154:
0155:            static {
0156:                initNative();
0157:            }
0158:
0159:            /*
0160:             * Get the field IDs associated with the given fields.  The field IDs are
0161:             * later passed as arguments to the various ObjectInputStream and
0162:             * ObjectOutputStream native methods for setting and getting field values.
0163:             */
0164:            private static native void getFieldIDs(ObjectStreamField[] fields,
0165:                    long[] primFieldIDs, long[] objFieldIDs);
0166:
0167:            /** 
0168:             * Find the descriptor for a class that can be serialized. 
0169:             * Creates an ObjectStreamClass instance if one does not exist 
0170:             * yet for class. Null is returned if the specified class does not 
0171:             * implement java.io.Serializable or java.io.Externalizable.
0172:             *
0173:             * @param cl class for which to get the descriptor
0174:             * @return the class descriptor for the specified class
0175:             */
0176:            public static ObjectStreamClass lookup(Class cl) {
0177:                return lookup(cl, false);
0178:            }
0179:
0180:            /**
0181:             * The name of the class described by this descriptor.
0182:             *
0183:             * @return a <code>String</code> representing the fully qualified name of
0184:             * the class
0185:             */
0186:            public String getName() {
0187:                return name;
0188:            }
0189:
0190:            /**
0191:             * Return the serialVersionUID for this class.
0192:             * The serialVersionUID defines a set of classes all with the same name
0193:             * that have evolved from a common root class and agree to be serialized
0194:             * and deserialized using a common format.
0195:             * NonSerializable classes have a serialVersionUID of 0L.
0196:             *
0197:             * @return the SUID of the class described by this descriptor
0198:             */
0199:            public long getSerialVersionUID() {
0200:                // TODO: synchronize instead of relying on volatile?
0201:                if (suid == null) {
0202:                    suid = (Long) AccessController
0203:                            .doPrivileged(new PrivilegedAction() {
0204:                                public Object run() {
0205:                                    return new Long(computeDefaultSUID(cl));
0206:                                }
0207:                            });
0208:                }
0209:                return suid.longValue();
0210:            }
0211:
0212:            /**
0213:             * Return the class in the local VM that this version is mapped to.
0214:             * Null is returned if there is no corresponding local class.
0215:             *
0216:             * @return the <code>Class</code> instance that this descriptor represents
0217:             */
0218:            public Class forClass() {
0219:                return cl;
0220:            }
0221:
0222:            /**
0223:             * Return an array of the fields of this serializable class.
0224:             *
0225:             * @return an array containing an element for each persistent
0226:             * field of this class. Returns an array of length zero if
0227:             * there are no fields.
0228:             * @since 1.2
0229:             */
0230:            public ObjectStreamField[] getFields() {
0231:                return getFields(true);
0232:            }
0233:
0234:            /**
0235:             * Get the field of this class by name.
0236:             *
0237:             * @param name the name of the data field to look for
0238:             * @return The ObjectStreamField object of the named field or null if there
0239:             * is no such named field.
0240:             */
0241:            public ObjectStreamField getField(String name) {
0242:                return getField(name, null);
0243:            }
0244:
0245:            /**
0246:             * Return a string describing this ObjectStreamClass.
0247:             */
0248:            public String toString() {
0249:                return name + ": static final long serialVersionUID = "
0250:                        + getSerialVersionUID() + "L;";
0251:            }
0252:
0253:            /**
0254:             * Looks up and returns class descriptor for given class, or null if class
0255:             * is non-serializable and "all" is set to false.
0256:             * 
0257:             * @param	cl class to look up
0258:             * @param	all if true, return descriptors for all classes; if false, only
0259:             * 		return descriptors for serializable classes
0260:             */
0261:            static ObjectStreamClass lookup(Class cl, boolean all) {
0262:                if (!(all || Serializable.class.isAssignableFrom(cl))) {
0263:                    return null;
0264:                }
0265:                /*
0266:                 * Note: using the class directly as the key for storing entries does
0267:                 * not pin the class indefinitely, since SoftCache removes strong refs
0268:                 * to keys when the corresponding values are gc'ed.
0269:                 */
0270:                Object entry;
0271:                EntryFuture future = null;
0272:                synchronized (localDescs) {
0273:                    if ((entry = localDescs.get(cl)) == null) {
0274:                        localDescs.put(cl, future = new EntryFuture());
0275:                    }
0276:                }
0277:
0278:                if (entry instanceof  ObjectStreamClass) { // check common case first
0279:                    return (ObjectStreamClass) entry;
0280:                } else if (entry instanceof  EntryFuture) {
0281:                    entry = ((EntryFuture) entry).get();
0282:                } else if (entry == null) {
0283:                    try {
0284:                        entry = new ObjectStreamClass(cl);
0285:                    } catch (Throwable th) {
0286:                        entry = th;
0287:                    }
0288:                    future.set(entry);
0289:                    synchronized (localDescs) {
0290:                        localDescs.put(cl, entry);
0291:                    }
0292:                }
0293:
0294:                if (entry instanceof  ObjectStreamClass) {
0295:                    return (ObjectStreamClass) entry;
0296:                } else if (entry instanceof  RuntimeException) {
0297:                    throw (RuntimeException) entry;
0298:                } else if (entry instanceof  Error) {
0299:                    throw (Error) entry;
0300:                } else {
0301:                    throw new InternalError("unexpected entry: " + entry);
0302:                }
0303:            }
0304:
0305:            /**
0306:             * Placeholder used in class descriptor and field reflector lookup tables
0307:             * for an entry in the process of being initialized.  (Internal) callers
0308:             * which receive an EntryFuture as the result of a lookup should call the
0309:             * get() method of the EntryFuture; this will return the actual entry once
0310:             * it is ready for use and has been set().  To conserve objects,
0311:             * EntryFutures synchronize on themselves.
0312:             */
0313:            private static class EntryFuture {
0314:
0315:                private static final Object unset = new Object();
0316:                private Object entry = unset;
0317:
0318:                synchronized void set(Object entry) {
0319:                    if (this .entry != unset) {
0320:                        throw new IllegalStateException();
0321:                    }
0322:                    this .entry = entry;
0323:                    notifyAll();
0324:                }
0325:
0326:                synchronized Object get() {
0327:                    boolean interrupted = false;
0328:                    while (entry == unset) {
0329:                        try {
0330:                            wait();
0331:                        } catch (InterruptedException ex) {
0332:                            interrupted = true;
0333:                        }
0334:                    }
0335:                    if (interrupted) {
0336:                        AccessController.doPrivileged(new PrivilegedAction() {
0337:                            public Object run() {
0338:                                Thread.currentThread().interrupt();
0339:                                return null;
0340:                            }
0341:                        });
0342:                    }
0343:                    return entry;
0344:                }
0345:            }
0346:
0347:            /**
0348:             * Creates local class descriptor representing given class.
0349:             */
0350:            private ObjectStreamClass(final Class cl) {
0351:                this .cl = cl;
0352:                name = cl.getName();
0353:                isProxy = Proxy.isProxyClass(cl);
0354:                serializable = Serializable.class.isAssignableFrom(cl);
0355:                externalizable = Externalizable.class.isAssignableFrom(cl);
0356:
0357:                Class super Cl = cl.getSuperclass();
0358:                super Desc = (super Cl != null) ? lookup(super Cl, false) : null;
0359:                localDesc = this ;
0360:
0361:                if (serializable) {
0362:                    AccessController.doPrivileged(new PrivilegedAction() {
0363:                        public Object run() {
0364:                            suid = getDeclaredSUID(cl);
0365:                            fields = getSerialFields(cl);
0366:                            computeFieldOffsets();
0367:
0368:                            if (externalizable) {
0369:                                // Back-ported from JDK 1.4
0370:                                // cons = getExternalizableConstructor(cl);
0371:                                initClass = cl;
0372:                            } else {
0373:                                // Back-ported from JDK 1.4
0374:                                // cons = getSerializableConstructor(cl);
0375:                                initClass = getSerializableInitClass(cl);
0376:
0377:                                writeObjectMethod = getPrivateMethod(
0378:                                        cl,
0379:                                        "writeObject",
0380:                                        new Class[] { ObjectOutputStream.class },
0381:                                        Void.TYPE);
0382:                                readObjectMethod = getPrivateMethod(
0383:                                        cl,
0384:                                        "readObject",
0385:                                        new Class[] { ObjectInputStream.class },
0386:                                        Void.TYPE);
0387:                                readObjectNoDataMethod = getPrivateMethod(cl,
0388:                                        "readObjectNoData", new Class[0],
0389:                                        Void.TYPE);
0390:                                hasWriteObjectData = (writeObjectMethod != null);
0391:                            }
0392:                            writeReplaceMethod = getInheritableMethod(cl,
0393:                                    "writeReplace", new Class[0], Object.class);
0394:                            readResolveMethod = getInheritableMethod(cl,
0395:                                    "readResolve", new Class[0], Object.class);
0396:                            return null;
0397:                        }
0398:                    });
0399:                } else {
0400:                    suid = new Long(0);
0401:                    fields = NO_FIELDS;
0402:                }
0403:
0404:                try {
0405:                    fieldRefl = getReflector(fields, this );
0406:                } catch (InvalidClassException ex) {
0407:                    // field mismatches impossible when matching local fields vs. self
0408:                    throw new InternalError();
0409:                }
0410:
0411:                //	if (cons == null) { // - Back-ported from JDK 1.4 
0412:                if (initClass == null) {
0413:                    deserializeEx = new InvalidClassException(name,
0414:                            "no valid constructor");
0415:                }
0416:                for (int i = 0; i < fields.length; i++) {
0417:                    if (fields[i].getField() == null) {
0418:                        defaultSerializeEx = new InvalidClassException(name,
0419:                                "unmatched serializable field(s) declared");
0420:                    }
0421:                }
0422:            }
0423:
0424:            /**
0425:             * Creates blank class descriptor which should be initialized via a
0426:             * subsequent call to initProxy(), initNonProxy() or readNonProxy().
0427:             */
0428:            ObjectStreamClass() {
0429:            }
0430:
0431:            /**
0432:             * Initializes class descriptor representing a proxy class.
0433:             */
0434:            void initProxy(Class cl, ClassNotFoundException resolveEx,
0435:                    ObjectStreamClass super Desc) throws InvalidClassException {
0436:                this .cl = cl;
0437:                this .resolveEx = resolveEx;
0438:                this .super Desc = super Desc;
0439:                isProxy = true;
0440:                serializable = true;
0441:                suid = new Long(0);
0442:                fields = NO_FIELDS;
0443:
0444:                if (cl != null) {
0445:                    localDesc = lookup(cl, true);
0446:                    if (!localDesc.isProxy) {
0447:                        throw new InvalidClassException(
0448:                                "cannot bind proxy descriptor to a non-proxy class");
0449:                    }
0450:                    name = localDesc.name;
0451:                    externalizable = localDesc.externalizable;
0452:
0453:                    // cons = localDesc.cons; // - Back-ported from JDK 1.4 
0454:                    initClass = localDesc.initClass;
0455:
0456:                    writeReplaceMethod = localDesc.writeReplaceMethod;
0457:                    readResolveMethod = localDesc.readResolveMethod;
0458:                    deserializeEx = localDesc.deserializeEx;
0459:                }
0460:                fieldRefl = getReflector(fields, localDesc);
0461:            }
0462:
0463:            /**
0464:             * Initializes class descriptor representing a non-proxy class.
0465:             */
0466:            void initNonProxy(ObjectStreamClass model, Class cl,
0467:                    ClassNotFoundException resolveEx,
0468:                    ObjectStreamClass super Desc) throws InvalidClassException {
0469:                this .cl = cl;
0470:                this .resolveEx = resolveEx;
0471:                this .super Desc = super Desc;
0472:                name = model.name;
0473:                suid = new Long(model.getSerialVersionUID());
0474:                isProxy = false;
0475:                serializable = model.serializable;
0476:                externalizable = model.externalizable;
0477:                hasBlockExternalData = model.hasBlockExternalData;
0478:                hasWriteObjectData = model.hasWriteObjectData;
0479:                fields = model.fields;
0480:                primDataSize = model.primDataSize;
0481:                numObjFields = model.numObjFields;
0482:
0483:                if (cl != null) {
0484:                    localDesc = lookup(cl, true);
0485:                    if (localDesc.isProxy) {
0486:                        throw new InvalidClassException(
0487:                                "cannot bind non-proxy descriptor to a proxy class");
0488:                    }
0489:
0490:                    if (serializable == localDesc.serializable
0491:                            && !cl.isArray()
0492:                            && suid.longValue() != localDesc
0493:                                    .getSerialVersionUID()) {
0494:                        throw new InvalidClassException(
0495:                                localDesc.name,
0496:                                "local class incompatible: "
0497:                                        + "stream classdesc serialVersionUID = "
0498:                                        + suid
0499:                                        + ", local class serialVersionUID = "
0500:                                        + localDesc.getSerialVersionUID());
0501:                    }
0502:
0503:                    if (!classNamesEqual(name, localDesc.name)) {
0504:                        throw new InvalidClassException(localDesc.name,
0505:                                "local class name incompatible with stream class "
0506:                                        + "name \"" + name + "\"");
0507:                    }
0508:
0509:                    if ((serializable == localDesc.serializable)
0510:                            && (externalizable != localDesc.externalizable)) {
0511:                        throw new InvalidClassException(localDesc.name,
0512:                                "Serializable incompatible with Externalizable");
0513:                    }
0514:
0515:                    if ((serializable != localDesc.serializable)
0516:                            || (externalizable != localDesc.externalizable)
0517:                            || !(serializable || externalizable)) {
0518:                        deserializeEx = new InvalidClassException(
0519:                                localDesc.name,
0520:                                "class invalid for deserialization");
0521:                    }
0522:
0523:                    // cons = localDesc.cons;  // - Back-ported from JDK 1.4 
0524:                    initClass = localDesc.initClass;
0525:
0526:                    writeObjectMethod = localDesc.writeObjectMethod;
0527:                    readObjectMethod = localDesc.readObjectMethod;
0528:                    readObjectNoDataMethod = localDesc.readObjectNoDataMethod;
0529:                    writeReplaceMethod = localDesc.writeReplaceMethod;
0530:                    readResolveMethod = localDesc.readResolveMethod;
0531:                    if (deserializeEx == null) {
0532:                        deserializeEx = localDesc.deserializeEx;
0533:                    }
0534:                }
0535:                fieldRefl = getReflector(fields, localDesc);
0536:                // reassign to matched fields so as to reflect local unshared settings
0537:                fields = fieldRefl.getFields();
0538:            }
0539:
0540:            /**
0541:             * Reads non-proxy class descriptor information from given input stream.
0542:             * The resulting class descriptor is not fully functional; it can only be
0543:             * used as input to the ObjectInputStream.resolveClass() and
0544:             * ObjectStreamClass.initNonProxy() methods.
0545:             */
0546:            void readNonProxy(ObjectInputStream in) throws IOException,
0547:                    ClassNotFoundException {
0548:                name = in.readUTF();
0549:                suid = new Long(in.readLong());
0550:                isProxy = false;
0551:
0552:                byte flags = in.readByte();
0553:                externalizable = ((flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0);
0554:                serializable = (externalizable || ((flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0));
0555:                hasWriteObjectData = ((flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0);
0556:                hasBlockExternalData = ((flags & ObjectStreamConstants.SC_BLOCK_DATA) != 0);
0557:
0558:                int numFields = in.readShort();
0559:                fields = (numFields > 0) ? new ObjectStreamField[numFields]
0560:                        : NO_FIELDS;
0561:                for (int i = 0; i < numFields; i++) {
0562:                    char tcode = (char) in.readByte();
0563:                    String name = in.readUTF();
0564:                    String signature = ((tcode == 'L') || (tcode == '[')) ? in
0565:                            .readTypeString()
0566:                            : new String(new char[] { tcode });
0567:                    fields[i] = new ObjectStreamField(name, signature, false);
0568:                }
0569:                computeFieldOffsets();
0570:            }
0571:
0572:            /**
0573:             * Writes non-proxy class descriptor information to given output stream.
0574:             */
0575:            void writeNonProxy(ObjectOutputStream out) throws IOException {
0576:                out.writeUTF(name);
0577:                out.writeLong(getSerialVersionUID());
0578:
0579:                byte flags = 0;
0580:                if (externalizable) {
0581:                    flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
0582:                    int protocol = out.getProtocolVersion();
0583:                    if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {
0584:                        flags |= ObjectStreamConstants.SC_BLOCK_DATA;
0585:                    }
0586:                } else if (serializable) {
0587:                    flags |= ObjectStreamConstants.SC_SERIALIZABLE;
0588:                }
0589:                if (hasWriteObjectData) {
0590:                    flags |= ObjectStreamConstants.SC_WRITE_METHOD;
0591:                }
0592:                out.writeByte(flags);
0593:
0594:                out.writeShort(fields.length);
0595:                for (int i = 0; i < fields.length; i++) {
0596:                    ObjectStreamField f = fields[i];
0597:                    out.writeByte(f.getTypeCode());
0598:                    out.writeUTF(f.getName());
0599:                    if (!f.isPrimitive()) {
0600:                        out.writeTypeString(f.getTypeString());
0601:                    }
0602:                }
0603:            }
0604:
0605:            /**
0606:             * Returns ClassNotFoundException (if any) thrown while attempting to
0607:             * resolve local class corresponding to this class descriptor.
0608:             */
0609:            ClassNotFoundException getResolveException() {
0610:                return resolveEx;
0611:            }
0612:
0613:            /**
0614:             * Throws an InvalidClassException if object instances referencing this
0615:             * class descriptor should not be allowed to deserialize.
0616:             */
0617:            void checkDeserialize() throws InvalidClassException {
0618:                if (deserializeEx != null) {
0619:                    throw deserializeEx;
0620:                }
0621:            }
0622:
0623:            /**
0624:             * Throws an InvalidClassException if objects whose class is represented by
0625:             * this descriptor should not be permitted to use default serialization
0626:             * (e.g., if the class declares serializable fields that do not correspond
0627:             * to actual fields, and hence must use the GetField API).
0628:             */
0629:            void checkDefaultSerialize() throws InvalidClassException {
0630:                if (defaultSerializeEx != null) {
0631:                    throw defaultSerializeEx;
0632:                }
0633:            }
0634:
0635:            /**
0636:             * Returns superclass descriptor.  Note that on the receiving side, the
0637:             * superclass descriptor may be bound to a class that is not a superclass
0638:             * of the subclass descriptor's bound class.
0639:             */
0640:            ObjectStreamClass getSuperDesc() {
0641:                return super Desc;
0642:            }
0643:
0644:            /**
0645:             * Returns the "local" class descriptor for the class associated with this
0646:             * class descriptor (i.e., the result of
0647:             * ObjectStreamClass.lookup(this.forClass())) or null if there is no class
0648:             * associated with this descriptor.
0649:             */
0650:            ObjectStreamClass getLocalDesc() {
0651:                return localDesc;
0652:            }
0653:
0654:            /**
0655:             * Returns arrays of ObjectStreamFields representing the serializable
0656:             * fields of the represented class.  If copy is true, a clone of this class
0657:             * descriptor's field array is returned, otherwise the array itself is
0658:             * returned.
0659:             */
0660:            ObjectStreamField[] getFields(boolean copy) {
0661:                return copy ? (ObjectStreamField[]) fields.clone() : fields;
0662:            }
0663:
0664:            /**
0665:             * Looks up a serializable field of the represented class by name and type.
0666:             * A specified type of null matches all types, Object.class matches all
0667:             * non-primitive types, and any other non-null type matches assignable
0668:             * types only.  Returns matching field, or null if no match found.
0669:             */
0670:            ObjectStreamField getField(String name, Class type) {
0671:                for (int i = 0; i < fields.length; i++) {
0672:                    ObjectStreamField f = fields[i];
0673:                    if (f.getName().equals(name)) {
0674:                        if (type == null) {
0675:                            return f;
0676:                        } else if (type == Object.class) {
0677:                            if (!f.isPrimitive()) {
0678:                                return f;
0679:                            }
0680:                        } else {
0681:                            Class ftype = f.getType();
0682:                            if (ftype != null && type.isAssignableFrom(ftype)) {
0683:                                return f;
0684:                            }
0685:                        }
0686:                    }
0687:                }
0688:                return null;
0689:            }
0690:
0691:            /**
0692:             * Returns true if class descriptor represents a dynamic proxy class, false
0693:             * otherwise.
0694:             */
0695:            boolean isProxy() {
0696:                return isProxy;
0697:            }
0698:
0699:            /**
0700:             * Returns true if represented class implements Externalizable, false
0701:             * otherwise.
0702:             */
0703:            boolean isExternalizable() {
0704:                return externalizable;
0705:            }
0706:
0707:            /**
0708:             * Returns true if represented class implements Serializable, false
0709:             * otherwise.
0710:             */
0711:            boolean isSerializable() {
0712:                return serializable;
0713:            }
0714:
0715:            /**
0716:             * Returns true if class descriptor represents externalizable class that
0717:             * has written its data in 1.2 (block data) format, false otherwise.
0718:             */
0719:            boolean hasBlockExternalData() {
0720:                return hasBlockExternalData;
0721:            }
0722:
0723:            /**
0724:             * Returns true if class descriptor represents serializable (but not
0725:             * externalizable) class which has written its data via a custom
0726:             * writeObject() method, false otherwise.
0727:             */
0728:            boolean hasWriteObjectData() {
0729:                return hasWriteObjectData;
0730:            }
0731:
0732:            /**
0733:             * Returns true if represented class is serializable/externalizable and can
0734:             * be instantiated by the serialization runtime--i.e., if it is
0735:             * externalizable and defines a public no-arg constructor, or if it is
0736:             * non-externalizable and its first non-serializable superclass defines an
0737:             * accessible no-arg constructor.  Otherwise, returns false.
0738:             */
0739:            boolean isInstantiable() {
0740:                // return (cons != null); // - Back-ported from JDK 1.4 
0741:                return (initClass != null);
0742:            }
0743:
0744:            /**
0745:             * Returns true if represented class is serializable (but not
0746:             * externalizable) and defines a conformant writeObject method.  Otherwise,
0747:             * returns false.
0748:             */
0749:            boolean hasWriteObjectMethod() {
0750:                return (writeObjectMethod != null);
0751:            }
0752:
0753:            /**
0754:             * Returns true if represented class is serializable (but not
0755:             * externalizable) and defines a conformant readObject method.  Otherwise,
0756:             * returns false.
0757:             */
0758:            boolean hasReadObjectMethod() {
0759:                return (readObjectMethod != null);
0760:            }
0761:
0762:            /**
0763:             * Returns true if represented class is serializable (but not
0764:             * externalizable) and defines a conformant readObjectNoData method.
0765:             * Otherwise, returns false.
0766:             */
0767:            boolean hasReadObjectNoDataMethod() {
0768:                return (readObjectNoDataMethod != null);
0769:            }
0770:
0771:            /**
0772:             * Returns true if represented class is serializable or externalizable and
0773:             * defines a conformant writeReplace method.  Otherwise, returns false.
0774:             */
0775:            boolean hasWriteReplaceMethod() {
0776:                return (writeReplaceMethod != null);
0777:            }
0778:
0779:            /**
0780:             * Returns true if represented class is serializable or externalizable and
0781:             * defines a conformant readResolve method.  Otherwise, returns false.
0782:             */
0783:            boolean hasReadResolveMethod() {
0784:                return (readResolveMethod != null);
0785:            }
0786:
0787:            /**
0788:             * Creates a new instance of the represented class.  If the class is
0789:             * externalizable, invokes its public no-arg constructor; otherwise, if the
0790:             * class is serializable, invokes the no-arg constructor of the first
0791:             * non-serializable superclass.  Throws UnsupportedOperationException if
0792:             * this class descriptor is not associated with a class, if the associated
0793:             * class is non-serializable or if the appropriate no-arg constructor is
0794:             * inaccessible/unavailable.
0795:             */
0796:            Object newInstance() throws InstantiationException,
0797:                    InvocationTargetException, UnsupportedOperationException,
0798:                    IllegalAccessException {
0799:                /* // - Back-ported from JDK 1.4 
0800:                if (cons != null) {
0801:                  try {
0802:                return cons.newInstance(new Object[0]);
0803:                  } catch (IllegalAccessException ex) {
0804:                // should not occur, as access checks have been suppressed
0805:                throw new InternalError();
0806:                  }
0807:                } else {
0808:                  throw new UnsupportedOperationException();
0809:                }
0810:                 */
0811:                if (initClass != null) {
0812:                    return ObjectInputStream.allocateNewObject(cl, initClass);
0813:                } else {
0814:                    throw new UnsupportedOperationException();
0815:                }
0816:            }
0817:
0818:            /**
0819:             * Invokes the writeObject method of the represented serializable class.
0820:             * Throws UnsupportedOperationException if this class descriptor is not
0821:             * associated with a class, or if the class is externalizable,
0822:             * non-serializable or does not define writeObject.
0823:             */
0824:            void invokeWriteObject(Object obj, ObjectOutputStream out)
0825:                    throws IOException, UnsupportedOperationException {
0826:                if (writeObjectMethod != null) {
0827:                    try {
0828:                        writeObjectMethod.invoke(obj, new Object[] { out });
0829:                    } catch (InvocationTargetException ex) {
0830:                        Throwable th = ex.getTargetException();
0831:                        if (th instanceof  IOException) {
0832:                            throw (IOException) th;
0833:                        } else {
0834:                            throwMiscException(th);
0835:                        }
0836:                    } catch (IllegalAccessException ex) {
0837:                        // should not occur, as access checks have been suppressed
0838:                        throw new InternalError();
0839:                    }
0840:                } else {
0841:                    throw new UnsupportedOperationException();
0842:                }
0843:            }
0844:
0845:            /**
0846:             * Invokes the readObject method of the represented serializable class.
0847:             * Throws UnsupportedOperationException if this class descriptor is not
0848:             * associated with a class, or if the class is externalizable,
0849:             * non-serializable or does not define readObject.
0850:             */
0851:            void invokeReadObject(Object obj, ObjectInputStream in)
0852:                    throws ClassNotFoundException, IOException,
0853:                    UnsupportedOperationException {
0854:                if (readObjectMethod != null) {
0855:                    try {
0856:                        readObjectMethod.invoke(obj, new Object[] { in });
0857:                    } catch (InvocationTargetException ex) {
0858:                        Throwable th = ex.getTargetException();
0859:                        if (th instanceof  ClassNotFoundException) {
0860:                            throw (ClassNotFoundException) th;
0861:                        } else if (th instanceof  IOException) {
0862:                            throw (IOException) th;
0863:                        } else {
0864:                            throwMiscException(th);
0865:                        }
0866:                    } catch (IllegalAccessException ex) {
0867:                        // should not occur, as access checks have been suppressed
0868:                        throw new InternalError();
0869:                    }
0870:                } else {
0871:                    throw new UnsupportedOperationException();
0872:                }
0873:            }
0874:
0875:            /**
0876:             * Invokes the readObjectNoData method of the represented serializable
0877:             * class.  Throws UnsupportedOperationException if this class descriptor is
0878:             * not associated with a class, or if the class is externalizable,
0879:             * non-serializable or does not define readObjectNoData.
0880:             */
0881:            void invokeReadObjectNoData(Object obj) throws IOException,
0882:                    UnsupportedOperationException {
0883:                if (readObjectNoDataMethod != null) {
0884:                    try {
0885:                        readObjectNoDataMethod.invoke(obj, new Object[0]);
0886:                    } catch (InvocationTargetException ex) {
0887:                        Throwable th = ex.getTargetException();
0888:                        if (th instanceof  ObjectStreamException) {
0889:                            throw (ObjectStreamException) th;
0890:                        } else {
0891:                            throwMiscException(th);
0892:                        }
0893:                    } catch (IllegalAccessException ex) {
0894:                        // should not occur, as access checks have been suppressed
0895:                        throw new InternalError();
0896:                    }
0897:                } else {
0898:                    throw new UnsupportedOperationException();
0899:                }
0900:            }
0901:
0902:            /**
0903:             * Invokes the writeReplace method of the represented serializable class and
0904:             * returns the result.  Throws UnsupportedOperationException if this class
0905:             * descriptor is not associated with a class, or if the class is
0906:             * non-serializable or does not define writeReplace.
0907:             */
0908:            Object invokeWriteReplace(Object obj) throws IOException,
0909:                    UnsupportedOperationException {
0910:                if (writeReplaceMethod != null) {
0911:                    try {
0912:                        return writeReplaceMethod.invoke(obj, new Object[0]);
0913:                    } catch (InvocationTargetException ex) {
0914:                        Throwable th = ex.getTargetException();
0915:                        if (th instanceof  ObjectStreamException) {
0916:                            throw (ObjectStreamException) th;
0917:                        } else {
0918:                            throwMiscException(th);
0919:                            throw new InternalError(); // never reached
0920:                        }
0921:                    } catch (IllegalAccessException ex) {
0922:                        // should not occur, as access checks have been suppressed
0923:                        throw new InternalError();
0924:                    }
0925:                } else {
0926:                    throw new UnsupportedOperationException();
0927:                }
0928:            }
0929:
0930:            /**
0931:             * Invokes the readResolve method of the represented serializable class and
0932:             * returns the result.  Throws UnsupportedOperationException if this class
0933:             * descriptor is not associated with a class, or if the class is
0934:             * non-serializable or does not define readResolve.
0935:             */
0936:            Object invokeReadResolve(Object obj) throws IOException,
0937:                    UnsupportedOperationException {
0938:                if (readResolveMethod != null) {
0939:                    try {
0940:                        return readResolveMethod.invoke(obj, new Object[0]);
0941:                    } catch (InvocationTargetException ex) {
0942:                        Throwable th = ex.getTargetException();
0943:                        if (th instanceof  ObjectStreamException) {
0944:                            throw (ObjectStreamException) th;
0945:                        } else {
0946:                            throwMiscException(th);
0947:                            throw new InternalError(); // never reached
0948:                        }
0949:                    } catch (IllegalAccessException ex) {
0950:                        // should not occur, as access checks have been suppressed
0951:                        throw new InternalError();
0952:                    }
0953:                } else {
0954:                    throw new UnsupportedOperationException();
0955:                }
0956:            }
0957:
0958:            /**
0959:             * Class representing the portion of an object's serialized form allotted
0960:             * to data described by a given class descriptor.  If "hasDesc" is false,
0961:             * the object's serialized form does not contain data associated with the
0962:             * class descriptor.
0963:             */
0964:            static class ClassDataSlot {
0965:
0966:                /** class descriptor "occupying" this slot */
0967:                final ObjectStreamClass desc;
0968:                /** true if serialized form includes data for this slot's descriptor */
0969:                final boolean hasData;
0970:
0971:                ClassDataSlot(ObjectStreamClass desc, boolean hasData) {
0972:                    this .desc = desc;
0973:                    this .hasData = hasData;
0974:                }
0975:            }
0976:
0977:            /**
0978:             * Returns array of ClassDataSlot instances representing the data layout
0979:             * (including superclass data) for serialized objects described by this
0980:             * class descriptor.  ClassDataSlots are ordered by inheritance with those
0981:             * containing "higher" superclasses appearing first.  The final
0982:             * ClassDataSlot contains a reference to this descriptor.
0983:             */
0984:            ClassDataSlot[] getClassDataLayout() throws InvalidClassException {
0985:                // TODO: synchronize instead of relying on volatile?
0986:                if (dataLayout == null) {
0987:                    dataLayout = getClassDataLayout0();
0988:                }
0989:                return dataLayout;
0990:            }
0991:
0992:            private ClassDataSlot[] getClassDataLayout0()
0993:                    throws InvalidClassException {
0994:                ArrayList slots = new ArrayList();
0995:                Class start = cl, end = cl;
0996:
0997:                // locate closest non-serializable superclass
0998:                while (end != null && Serializable.class.isAssignableFrom(end)) {
0999:                    end = end.getSuperclass();
1000:                }
1001:
1002:                for (ObjectStreamClass d = this ; d != null; d = d.super Desc) {
1003:
1004:                    // search up inheritance heirarchy for class with matching name
1005:                    String searchName = (d.cl != null) ? d.cl.getName()
1006:                            : d.name;
1007:                    Class match = null;
1008:                    for (Class c = start; c != end; c = c.getSuperclass()) {
1009:                        if (searchName.equals(c.getName())) {
1010:                            match = c;
1011:                            break;
1012:                        }
1013:                    }
1014:
1015:                    // add "no data" slot for each unmatched class below match
1016:                    if (match != null) {
1017:                        for (Class c = start; c != match; c = c.getSuperclass()) {
1018:                            slots.add(new ClassDataSlot(ObjectStreamClass
1019:                                    .lookup(c, true), false));
1020:                        }
1021:                        start = match.getSuperclass();
1022:                    }
1023:
1024:                    // record descriptor/class pairing
1025:                    slots.add(new ClassDataSlot(d.getVariantFor(match), true));
1026:                }
1027:
1028:                // add "no data" slot for any leftover unmatched classes
1029:                for (Class c = start; c != end; c = c.getSuperclass()) {
1030:                    slots.add(new ClassDataSlot(ObjectStreamClass.lookup(c,
1031:                            true), false));
1032:                }
1033:
1034:                // order slots from superclass -> subclass
1035:                Collections.reverse(slots);
1036:                return (ClassDataSlot[]) slots.toArray(new ClassDataSlot[slots
1037:                        .size()]);
1038:            }
1039:
1040:            /**
1041:             * Returns aggregate size (in bytes) of marshalled primitive field values
1042:             * for represented class.
1043:             */
1044:            int getPrimDataSize() {
1045:                return primDataSize;
1046:            }
1047:
1048:            /**
1049:             * Returns number of non-primitive serializable fields of represented
1050:             * class.
1051:             */
1052:            int getNumObjFields() {
1053:                return numObjFields;
1054:            }
1055:
1056:            /**
1057:             * Fetches the serializable primitive field values of object obj and
1058:             * marshals them into byte array buf starting at offset 0.  It is the
1059:             * responsibility of the caller to ensure that obj is of the proper type if
1060:             * non-null.
1061:             */
1062:            void getPrimFieldValues(Object obj, byte[] buf) {
1063:                fieldRefl.getPrimFieldValues(obj, buf);
1064:            }
1065:
1066:            /**
1067:             * Sets the serializable primitive fields of object obj using values
1068:             * unmarshalled from byte array buf starting at offset 0.  It is the
1069:             * responsibility of the caller to ensure that obj is of the proper type if
1070:             * non-null.
1071:             */
1072:            void setPrimFieldValues(Object obj, byte[] buf) {
1073:                fieldRefl.setPrimFieldValues(obj, buf);
1074:            }
1075:
1076:            /**
1077:             * Fetches the serializable object field values of object obj and stores
1078:             * them in array vals starting at offset 0.  It is the responsibility of
1079:             * the caller to ensure that obj is of the proper type if non-null.
1080:             */
1081:            void getObjFieldValues(Object obj, Object[] vals) {
1082:                fieldRefl.getObjFieldValues(obj, vals);
1083:            }
1084:
1085:            /**
1086:             * Sets the serializable object fields of object obj using values from
1087:             * array vals starting at offset 0.  It is the responsibility of the caller
1088:             * to ensure that obj is of the proper type if non-null.
1089:             */
1090:            void setObjFieldValues(Object obj, Object[] vals) {
1091:                fieldRefl.setObjFieldValues(obj, vals);
1092:            }
1093:
1094:            /**
1095:             * Calculates and sets serializable field offsets, as well as primitive
1096:             * data size and object field count totals.
1097:             */
1098:            private void computeFieldOffsets() {
1099:                primDataSize = 0;
1100:                numObjFields = 0;
1101:                for (int i = 0; i < fields.length; i++) {
1102:                    ObjectStreamField f = fields[i];
1103:                    switch (f.getTypeCode()) {
1104:                    case 'Z':
1105:                    case 'B':
1106:                        f.setOffset(primDataSize++);
1107:                        break;
1108:
1109:                    case 'C':
1110:                    case 'S':
1111:                        f.setOffset(primDataSize);
1112:                        primDataSize += 2;
1113:                        break;
1114:
1115:                    case 'I':
1116:                    case 'F':
1117:                        f.setOffset(primDataSize);
1118:                        primDataSize += 4;
1119:                        break;
1120:
1121:                    case 'J':
1122:                    case 'D':
1123:                        f.setOffset(primDataSize);
1124:                        primDataSize += 8;
1125:                        break;
1126:
1127:                    case '[':
1128:                    case 'L':
1129:                        f.setOffset(numObjFields++);
1130:                        break;
1131:
1132:                    default:
1133:                        throw new InternalError();
1134:                    }
1135:                }
1136:            }
1137:
1138:            /**
1139:             * If given class is the same as the class associated with this class
1140:             * descriptor, returns reference to this class descriptor.  Otherwise,
1141:             * returns variant of this class descriptor bound to given class.
1142:             */
1143:            private ObjectStreamClass getVariantFor(Class cl)
1144:                    throws InvalidClassException {
1145:                if (this .cl == cl) {
1146:                    return this ;
1147:                }
1148:                ObjectStreamClass desc = new ObjectStreamClass();
1149:                if (isProxy) {
1150:                    desc.initProxy(cl, null, super Desc);
1151:                } else {
1152:                    desc.initNonProxy(this , cl, null, super Desc);
1153:                }
1154:                return desc;
1155:            }
1156:
1157:            /**
1158:             * Returns public no-arg constructor of given class, or null if none found.
1159:             * Access checks are disabled on the returned constructor (if any), since
1160:             * the defining class may still be non-public.
1161:             *
1162:            private static Constructor getExternalizableConstructor(Class cl) {
1163:                try {
1164:                    Constructor cons = cl.getDeclaredConstructor(new Class[0]);
1165:                    cons.setAccessible(true);
1166:                    return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
1167:                        cons : null;
1168:                } catch (NoSuchMethodException ex) {
1169:                    return null;
1170:                }
1171:            }
1172:             */
1173:            // - Back-ported from JDK 1.4
1174:            /**
1175:             * Returns subclass-accessible no-arg constructor of first non-serializable
1176:             * superclass, or null if none found.  Access checks are disabled on the
1177:             * returned constructor (if any).
1178:             *
1179:            private static Constructor getSerializableConstructor(Class cl) {
1180:                Class initCl = cl;
1181:                while (Serializable.class.isAssignableFrom(initCl)) {
1182:                    if ((initCl = initCl.getSuperclass()) == null) {
1183:                        return null;
1184:                    }
1185:                }
1186:                try {
1187:                    Constructor cons = initCl.getDeclaredConstructor(new Class[0]);
1188:                    int mods = cons.getModifiers();
1189:                    if ((mods & Modifier.PRIVATE) != 0 ||
1190:                        ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
1191:                         !packageEquals(cl, initCl)))
1192:                    {
1193:                        return null;
1194:                    }
1195:                    cons = reflFactory.newConstructorForSerialization(cl, cons);
1196:                    cons.setAccessible(true);
1197:                    return cons;
1198:                } catch (NoSuchMethodException ex) {
1199:                    return null;
1200:                }
1201:            }
1202:             */
1203:            // - Back-ported from JDK 1.4
1204:            /**
1205:             * Returns first non-serializable superclass, or null if none is found.
1206:             * 
1207:             * Added for JDK 1.4 back-port
1208:             */
1209:            private static Class getSerializableInitClass(Class cl) {
1210:                Class initCl = cl;
1211:
1212:                while (Serializable.class.isAssignableFrom(initCl)) {
1213:                    if ((initCl = initCl.getSuperclass()) == null) {
1214:                        return null;
1215:                    }
1216:                }
1217:
1218:                return initCl;
1219:            }
1220:
1221:            /**
1222:             * Returns non-static, non-abstract method with given signature provided it
1223:             * is defined by or accessible (via inheritance) by the given class, or
1224:             * null if no match found.  Access checks are disabled on the returned
1225:             * method (if any).
1226:             */
1227:            private static Method getInheritableMethod(Class cl, String name,
1228:                    Class[] argTypes, Class returnType) {
1229:                Method meth = null;
1230:                Class defCl = cl;
1231:                while (defCl != null) {
1232:                    try {
1233:                        meth = defCl.getDeclaredMethod(name, argTypes);
1234:                        break;
1235:                    } catch (NoSuchMethodException ex) {
1236:                        defCl = defCl.getSuperclass();
1237:                    }
1238:                }
1239:
1240:                if ((meth == null) || (meth.getReturnType() != returnType)) {
1241:                    return null;
1242:                }
1243:                meth.setAccessible(true);
1244:                int mods = meth.getModifiers();
1245:                if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) {
1246:                    return null;
1247:                } else if ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) {
1248:                    return meth;
1249:                } else if ((mods & Modifier.PRIVATE) != 0) {
1250:                    return (cl == defCl) ? meth : null;
1251:                } else {
1252:                    return packageEquals(cl, defCl) ? meth : null;
1253:                }
1254:            }
1255:
1256:            /**
1257:             * Returns non-static private method with given signature defined by given
1258:             * class, or null if none found.  Access checks are disabled on the
1259:             * returned method (if any).
1260:             */
1261:            private static Method getPrivateMethod(Class cl, String name,
1262:                    Class[] argTypes, Class returnType) {
1263:                try {
1264:                    Method meth = cl.getDeclaredMethod(name, argTypes);
1265:                    meth.setAccessible(true);
1266:                    int mods = meth.getModifiers();
1267:                    return ((meth.getReturnType() == returnType)
1268:                            && ((mods & Modifier.STATIC) == 0) && ((mods & Modifier.PRIVATE) != 0)) ? meth
1269:                            : null;
1270:                } catch (NoSuchMethodException ex) {
1271:                    return null;
1272:                }
1273:            }
1274:
1275:            /**
1276:             * Returns true if classes are defined in the same package, false
1277:             * otherwise.
1278:             */
1279:            private static boolean packageEquals(Class cl1, Class cl2) {
1280:                Package pkg1 = cl1.getPackage(), pkg2 = cl2.getPackage();
1281:                return ((pkg1 == pkg2) || ((pkg1 != null) && (pkg1.equals(pkg2))));
1282:            }
1283:
1284:            /**
1285:             * Compares class names for equality, ignoring package names.  Returns true
1286:             * if class names equal, false otherwise.
1287:             */
1288:            private static boolean classNamesEqual(String name1, String name2) {
1289:                name1 = name1.substring(name1.lastIndexOf('.') + 1);
1290:                name2 = name2.substring(name2.lastIndexOf('.') + 1);
1291:                return name1.equals(name2);
1292:            }
1293:
1294:            /**
1295:             * Returns JVM type signature for given class.
1296:             */
1297:            static String getClassSignature(Class cl) {
1298:                StringBuffer sbuf = new StringBuffer();
1299:                while (cl.isArray()) {
1300:                    sbuf.append('[');
1301:                    cl = cl.getComponentType();
1302:                }
1303:                if (cl.isPrimitive()) {
1304:                    if (cl == Integer.TYPE) {
1305:                        sbuf.append('I');
1306:                    } else if (cl == Byte.TYPE) {
1307:                        sbuf.append('B');
1308:                    } else if (cl == Long.TYPE) {
1309:                        sbuf.append('J');
1310:                    } else if (cl == Float.TYPE) {
1311:                        sbuf.append('F');
1312:                    } else if (cl == Double.TYPE) {
1313:                        sbuf.append('D');
1314:                    } else if (cl == Short.TYPE) {
1315:                        sbuf.append('S');
1316:                    } else if (cl == Character.TYPE) {
1317:                        sbuf.append('C');
1318:                    } else if (cl == Boolean.TYPE) {
1319:                        sbuf.append('Z');
1320:                    } else if (cl == Void.TYPE) {
1321:                        sbuf.append('V');
1322:                    } else {
1323:                        throw new InternalError();
1324:                    }
1325:                } else {
1326:                    sbuf.append('L' + cl.getName().replace('.', '/') + ';');
1327:                }
1328:                return sbuf.toString();
1329:            }
1330:
1331:            /**
1332:             * Returns JVM type signature for given list of parameters and return type.
1333:             */
1334:            private static String getMethodSignature(Class[] paramTypes,
1335:                    Class retType) {
1336:                StringBuffer sbuf = new StringBuffer();
1337:                sbuf.append('(');
1338:                for (int i = 0; i < paramTypes.length; i++) {
1339:                    sbuf.append(getClassSignature(paramTypes[i]));
1340:                }
1341:                sbuf.append(')');
1342:                sbuf.append(getClassSignature(retType));
1343:                return sbuf.toString();
1344:            }
1345:
1346:            /**
1347:             * Convenience method for throwing an exception that is either a
1348:             * RuntimeException, Error, or of some unexpected type (in which case it is
1349:             * wrapped inside an IOException).
1350:             */
1351:            private static void throwMiscException(Throwable th)
1352:                    throws IOException {
1353:                if (th instanceof  RuntimeException) {
1354:                    throw (RuntimeException) th;
1355:                } else if (th instanceof  Error) {
1356:                    throw (Error) th;
1357:                } else {
1358:                    IOException ex = new IOException(
1359:                            "unexpected exception type : " + th);
1360:                    // ex.initCause(th); // - Back-ported from JDK 1.4 
1361:                    throw ex;
1362:                }
1363:            }
1364:
1365:            /**
1366:             * Returns ObjectStreamField array describing the serializable fields of
1367:             * the given class.  Serializable fields backed by an actual field of the
1368:             * class are represented by ObjectStreamFields with corresponding non-null
1369:             * Field objects.
1370:             */
1371:            private static ObjectStreamField[] getSerialFields(Class cl) {
1372:                ObjectStreamField[] fields;
1373:                if (Serializable.class.isAssignableFrom(cl)
1374:                        && !Externalizable.class.isAssignableFrom(cl)
1375:                        && !Proxy.isProxyClass(cl) && !cl.isInterface()) {
1376:                    if ((fields = getDeclaredSerialFields(cl)) == null) {
1377:                        fields = getDefaultSerialFields(cl);
1378:                    }
1379:                    Arrays.sort(fields);
1380:                } else {
1381:                    fields = NO_FIELDS;
1382:                }
1383:                return fields;
1384:            }
1385:
1386:            /**
1387:             * Returns serializable fields of given class as defined explicitly by a
1388:             * "serialPersistentFields" field, or null if no appropriate
1389:             * "serialPersistendFields" field is defined.  Serializable fields backed
1390:             * by an actual field of the class are represented by ObjectStreamFields
1391:             * with corresponding non-null Field objects.  For compatibility with past
1392:             * releases, a "serialPersistentFields" field with a null value is
1393:             * considered equivalent to not declaring "serialPersistentFields".
1394:             */
1395:            private static ObjectStreamField[] getDeclaredSerialFields(Class cl) {
1396:                ObjectStreamField[] serialPersistentFields = null;
1397:                try {
1398:                    Field f = cl.getDeclaredField("serialPersistentFields");
1399:                    int mask = Modifier.PRIVATE | Modifier.STATIC
1400:                            | Modifier.FINAL;
1401:                    if ((f.getModifiers() & mask) == mask) {
1402:                        f.setAccessible(true);
1403:                        serialPersistentFields = (ObjectStreamField[]) f
1404:                                .get(null);
1405:                    }
1406:                } catch (Exception ex) {
1407:                }
1408:                if (serialPersistentFields == null) {
1409:                    return null;
1410:                } else if (serialPersistentFields.length == 0) {
1411:                    return NO_FIELDS;
1412:                }
1413:
1414:                ObjectStreamField[] boundFields = new ObjectStreamField[serialPersistentFields.length];
1415:                for (int i = 0; i < serialPersistentFields.length; i++) {
1416:                    ObjectStreamField spf = serialPersistentFields[i];
1417:                    try {
1418:                        Field f = cl.getDeclaredField(spf.getName());
1419:                        if ((f.getType() == spf.getType())
1420:                                && ((f.getModifiers() & Modifier.STATIC) == 0)) {
1421:                            boundFields[i] = new ObjectStreamField(f, spf
1422:                                    .isUnshared(), true);
1423:                        }
1424:                    } catch (NoSuchFieldException ex) {
1425:                    }
1426:                    if (boundFields[i] == null) {
1427:                        boundFields[i] = new ObjectStreamField(spf.getName(),
1428:                                spf.getType(), spf.isUnshared());
1429:                    }
1430:                }
1431:                return boundFields;
1432:            }
1433:
1434:            /**
1435:             * Returns array of ObjectStreamFields corresponding to all non-static
1436:             * non-transient fields declared by given class.  Each ObjectStreamField
1437:             * contains a Field object for the field it represents.  If no default
1438:             * serializable fields exist, NO_FIELDS is returned.
1439:             */
1440:            private static ObjectStreamField[] getDefaultSerialFields(Class cl) {
1441:                Field[] clFields = cl.getDeclaredFields();
1442:                ArrayList list = new ArrayList();
1443:                int mask = Modifier.STATIC | Modifier.TRANSIENT;
1444:
1445:                for (int i = 0; i < clFields.length; i++) {
1446:                    if ((clFields[i].getModifiers() & mask) == 0) {
1447:                        list
1448:                                .add(new ObjectStreamField(clFields[i], false,
1449:                                        true));
1450:                    }
1451:                }
1452:                int size = list.size();
1453:                return (size == 0) ? NO_FIELDS : (ObjectStreamField[]) list
1454:                        .toArray(new ObjectStreamField[size]);
1455:            }
1456:
1457:            /**
1458:             * Returns explicit serial version UID value declared by given class, or
1459:             * null if none.
1460:             */
1461:            private static Long getDeclaredSUID(Class cl) {
1462:                try {
1463:                    Field f = cl.getDeclaredField("serialVersionUID");
1464:                    int mask = Modifier.STATIC | Modifier.FINAL;
1465:                    if ((f.getModifiers() & mask) == mask) {
1466:                        f.setAccessible(true);
1467:                        return new Long(f.getLong(null));
1468:                    }
1469:                } catch (Exception ex) {
1470:                }
1471:                return null;
1472:            }
1473:
1474:            /**
1475:             * Computes the default serial version UID value for the given class.
1476:             */
1477:            private static long computeDefaultSUID(Class cl) {
1478:                if (!Serializable.class.isAssignableFrom(cl)
1479:                        || Proxy.isProxyClass(cl)) {
1480:                    return 0L;
1481:                }
1482:
1483:                try {
1484:                    ByteArrayOutputStream bout = new ByteArrayOutputStream();
1485:                    DataOutputStream dout = new DataOutputStream(bout);
1486:
1487:                    dout.writeUTF(cl.getName());
1488:
1489:                    int classMods = cl.getModifiers()
1490:                            & (Modifier.PUBLIC | Modifier.FINAL
1491:                                    | Modifier.INTERFACE | Modifier.ABSTRACT);
1492:
1493:                    /*
1494:                     * compensate for javac bug in which ABSTRACT bit was set for an
1495:                     * interface only if the interface declared methods
1496:                     */
1497:                    Method[] methods = cl.getDeclaredMethods();
1498:                    if ((classMods & Modifier.INTERFACE) != 0) {
1499:                        classMods = (methods.length > 0) ? (classMods | Modifier.ABSTRACT)
1500:                                : (classMods & ~Modifier.ABSTRACT);
1501:                    }
1502:                    dout.writeInt(classMods);
1503:
1504:                    if (!cl.isArray()) {
1505:                        /*
1506:                         * compensate for change in 1.2  in which
1507:                         * Class.getInterfaces() was modified to return Cloneable and
1508:                         * Serializable for array classes.
1509:                         */
1510:                        Class[] interfaces = cl.getInterfaces();
1511:                        String[] ifaceNames = new String[interfaces.length];
1512:                        for (int i = 0; i < interfaces.length; i++) {
1513:                            ifaceNames[i] = interfaces[i].getName();
1514:                        }
1515:                        Arrays.sort(ifaceNames);
1516:                        for (int i = 0; i < ifaceNames.length; i++) {
1517:                            dout.writeUTF(ifaceNames[i]);
1518:                        }
1519:                    }
1520:
1521:                    Field[] fields = cl.getDeclaredFields();
1522:                    MemberSignature[] fieldSigs = new MemberSignature[fields.length];
1523:                    for (int i = 0; i < fields.length; i++) {
1524:                        fieldSigs[i] = new MemberSignature(fields[i]);
1525:                    }
1526:                    Arrays.sort(fieldSigs, new Comparator() {
1527:                        public int compare(Object o1, Object o2) {
1528:                            String name1 = ((MemberSignature) o1).name;
1529:                            String name2 = ((MemberSignature) o2).name;
1530:                            return name1.compareTo(name2);
1531:                        }
1532:                    });
1533:                    for (int i = 0; i < fieldSigs.length; i++) {
1534:                        MemberSignature sig = fieldSigs[i];
1535:                        int mods = sig.member.getModifiers();
1536:                        if (((mods & Modifier.PRIVATE) == 0)
1537:                                || ((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0)) {
1538:                            dout.writeUTF(sig.name);
1539:                            dout.writeInt(mods);
1540:                            dout.writeUTF(sig.signature);
1541:                        }
1542:                    }
1543:
1544:                    if (hasStaticInitializer(cl)) {
1545:                        dout.writeUTF("<clinit>");
1546:                        dout.writeInt(Modifier.STATIC);
1547:                        dout.writeUTF("()V");
1548:                    }
1549:
1550:                    Constructor[] cons = cl.getDeclaredConstructors();
1551:                    MemberSignature[] consSigs = new MemberSignature[cons.length];
1552:                    for (int i = 0; i < cons.length; i++) {
1553:                        consSigs[i] = new MemberSignature(cons[i]);
1554:                    }
1555:                    Arrays.sort(consSigs, new Comparator() {
1556:                        public int compare(Object o1, Object o2) {
1557:                            String sig1 = ((MemberSignature) o1).signature;
1558:                            String sig2 = ((MemberSignature) o2).signature;
1559:                            return sig1.compareTo(sig2);
1560:                        }
1561:                    });
1562:                    for (int i = 0; i < consSigs.length; i++) {
1563:                        MemberSignature sig = consSigs[i];
1564:                        int mods = sig.member.getModifiers();
1565:                        if ((mods & Modifier.PRIVATE) == 0) {
1566:                            dout.writeUTF("<init>");
1567:                            dout.writeInt(mods);
1568:                            dout.writeUTF(sig.signature.replace('/', '.'));
1569:                        }
1570:                    }
1571:
1572:                    MemberSignature[] methSigs = new MemberSignature[methods.length];
1573:                    for (int i = 0; i < methods.length; i++) {
1574:                        methSigs[i] = new MemberSignature(methods[i]);
1575:                    }
1576:                    Arrays.sort(methSigs, new Comparator() {
1577:                        public int compare(Object o1, Object o2) {
1578:                            MemberSignature ms1 = (MemberSignature) o1;
1579:                            MemberSignature ms2 = (MemberSignature) o2;
1580:                            int comp = ms1.name.compareTo(ms2.name);
1581:                            if (comp == 0) {
1582:                                comp = ms1.signature.compareTo(ms2.signature);
1583:                            }
1584:                            return comp;
1585:                        }
1586:                    });
1587:                    for (int i = 0; i < methSigs.length; i++) {
1588:                        MemberSignature sig = methSigs[i];
1589:                        int mods = sig.member.getModifiers();
1590:                        if ((mods & Modifier.PRIVATE) == 0) {
1591:                            dout.writeUTF(sig.name);
1592:                            dout.writeInt(mods);
1593:                            dout.writeUTF(sig.signature.replace('/', '.'));
1594:                        }
1595:                    }
1596:
1597:                    dout.flush();
1598:
1599:                    MessageDigest md = MessageDigest.getInstance("SHA");
1600:                    byte[] hashBytes = md.digest(bout.toByteArray());
1601:                    long hash = 0;
1602:                    for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
1603:                        hash = (hash << 8) | (hashBytes[i] & 0xFF);
1604:                    }
1605:                    return hash;
1606:                } catch (IOException ex) {
1607:                    throw new InternalError();
1608:                } catch (NoSuchAlgorithmException ex) {
1609:                    throw new SecurityException(ex.getMessage());
1610:                }
1611:            }
1612:
1613:            /**
1614:             * Returns true if the given class defines a static initializer method,
1615:             * false otherwise.
1616:             */
1617:            private native static boolean hasStaticInitializer(Class cl);
1618:
1619:            /**
1620:             * Class for computing and caching field/constructor/method signatures
1621:             * during serialVersionUID calculation.
1622:             */
1623:            private static class MemberSignature {
1624:
1625:                public final Member member;
1626:                public final String name;
1627:                public final String signature;
1628:
1629:                public MemberSignature(Field field) {
1630:                    member = field;
1631:                    name = field.getName();
1632:                    signature = getClassSignature(field.getType());
1633:                }
1634:
1635:                public MemberSignature(Constructor cons) {
1636:                    member = cons;
1637:                    name = cons.getName();
1638:                    signature = getMethodSignature(cons.getParameterTypes(),
1639:                            Void.TYPE);
1640:                }
1641:
1642:                public MemberSignature(Method meth) {
1643:                    member = meth;
1644:                    name = meth.getName();
1645:                    signature = getMethodSignature(meth.getParameterTypes(),
1646:                            meth.getReturnType());
1647:                }
1648:            }
1649:
1650:            /**
1651:             * Class for setting and retrieving serializable field values in batch.
1652:             */
1653:            // TODO: dynamically generate these?
1654:            private static class FieldReflector {
1655:
1656:                /** handle for performing unsafe operations */
1657:                /* // - Back-ported from JDK 1.4 
1658:                private static final Unsafe unsafe = (Unsafe) 
1659:                  AccessController.doPrivileged(new Unsafe.GetUnsafeAction());
1660:                 */
1661:
1662:                /** fields to operate on */
1663:                private final ObjectStreamField[] fields;
1664:                /** number of primitive fields */
1665:                private final int numPrimFields;
1666:
1667:                /** unsafe field keys */
1668:                // private final int[] keys; // - Back-ported from JDK 1.4 
1669:                /** Field IDs for back-port. */
1670:                // - Back-ported from JDK 1.4
1671:                private long[] primFieldIDs;
1672:                private long[] objFieldIDs;
1673:
1674:                /** field data offsets */
1675:                private final int[] offsets;
1676:                /** field type codes */
1677:                private final char[] typeCodes;
1678:                /** field types */
1679:                private final Class[] types;
1680:
1681:                /**
1682:                 * Constructs FieldReflector capable of setting/getting values from the
1683:                 * subset of fields whose ObjectStreamFields contain non-null
1684:                 * reflective Field objects.  ObjectStreamFields with null Fields are
1685:                 * treated as filler, for which get operations return default values
1686:                 * and set operations discard given values.
1687:                 */
1688:                FieldReflector(ObjectStreamField[] fields) {
1689:                    this .fields = fields;
1690:                    int nfields = fields.length;
1691:                    //	    keys = new int[nfields];  // - Back-ported from JDK 1.4 
1692:
1693:                    offsets = new int[nfields];
1694:                    typeCodes = new char[nfields];
1695:                    ArrayList typeList = new ArrayList();
1696:
1697:                    /*
1698:                      There is an assumption here that the fields
1699:                      are already ordered such that all the primitive fields are
1700:                      first, followed by all the object fields. 
1701:                          // - Back-ported from JDK 1.4
1702:                     */
1703:                    for (int i = 0; i < nfields; i++) {
1704:                        ObjectStreamField f = fields[i];
1705:                        Field rf = f.getField();
1706:
1707:                        /* // - Back-ported from JDK 1.4 
1708:                        keys[i] = (rf != null) ? 
1709:                            unsafe.fieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET;
1710:                         */
1711:
1712:                        offsets[i] = f.getOffset();
1713:                        typeCodes[i] = f.getTypeCode();
1714:                        if (!f.isPrimitive()) {
1715:                            typeList.add((rf != null) ? rf.getType() : null);
1716:                        }
1717:                    }
1718:
1719:                    types = (Class[]) typeList.toArray(new Class[typeList
1720:                            .size()]);
1721:                    numPrimFields = nfields - types.length;
1722:
1723:                    // For JDK 1.4 back-port  
1724:
1725:                    primFieldIDs = new long[numPrimFields];
1726:                    objFieldIDs = new long[types.length];
1727:
1728:                    getFieldIDs(fields, primFieldIDs, objFieldIDs);
1729:                }
1730:
1731:                /**
1732:                 * Returns list of ObjectStreamFields representing fields operated on
1733:                 * by this reflector.  The shared/unshared values and Field objects
1734:                 * contained by ObjectStreamFields in the list reflect their bindings
1735:                 * to locally defined serializable fields.
1736:                 */
1737:                ObjectStreamField[] getFields() {
1738:                    return fields;
1739:                }
1740:
1741:                /**
1742:                 * Fetches the serializable primitive field values of object obj and
1743:                 * marshals them into byte array buf starting at offset 0.  The caller
1744:                 * is responsible for ensuring that obj is of the proper type.
1745:                 */
1746:                void getPrimFieldValues(Object obj, byte[] buf) {
1747:                    if (obj == null) {
1748:                        throw new NullPointerException();
1749:                    }
1750:
1751:                    // For JDK 1.4 back-port 
1752:                    ObjectOutputStream.getPrimitiveFieldValues(obj,
1753:                            primFieldIDs, typeCodes, buf);
1754:                }
1755:
1756:                /**
1757:                 * Sets the serializable primitive fields of object obj using values
1758:                 * unmarshalled from byte array buf starting at offset 0.  The caller
1759:                 * is responsible for ensuring that obj is of the proper type.
1760:                 */
1761:                void setPrimFieldValues(Object obj, byte[] buf) {
1762:                    if (obj == null) {
1763:                        throw new NullPointerException();
1764:                    }
1765:
1766:                    // For JDK 1.4 back-port 
1767:                    ObjectInputStream.setPrimitiveFieldValues(obj,
1768:                            primFieldIDs, typeCodes, buf);
1769:                }
1770:
1771:                /**
1772:                 * Fetches the serializable object field values of object obj and
1773:                 * stores them in array vals starting at offset 0.  The caller is
1774:                 * responsible for ensuring that obj is of the proper type.
1775:                 */
1776:                void getObjFieldValues(Object obj, Object[] vals) {
1777:                    if (obj == null) {
1778:                        throw new NullPointerException();
1779:                    }
1780:                    /* assuming checkDefaultSerialize() has been called on the class
1781:                     * descriptor this FieldReflector was obtained from, no field keys
1782:                     * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
1783:                     */
1784:                    for (int i = numPrimFields; i < fields.length; i++) {
1785:                        switch (typeCodes[i]) {
1786:                        case 'L':
1787:                        case '[':
1788:                            // Back-ported from JDK 1.4 
1789:                            // vals[offsets[i]] = unsafe.getObject(obj, keys[i]);
1790:                            vals[offsets[i]] = ObjectOutputStream
1791:                                    .getObjectFieldValue(obj, objFieldIDs[i
1792:                                            - numPrimFields]);
1793:                            break;
1794:
1795:                        default:
1796:                            throw new InternalError();
1797:                        }
1798:                    }
1799:                }
1800:
1801:                /**
1802:                 * Sets the serializable object fields of object obj using values from
1803:                 * array vals starting at offset 0.  The caller is responsible for
1804:                 * ensuring that obj is of the proper type; however, attempts to set a
1805:                 * field with a value of the wrong type will trigger an appropriate
1806:                 * ClassCastException.
1807:                 */
1808:                void setObjFieldValues(Object obj, Object[] vals) {
1809:                    if (obj == null) {
1810:                        throw new NullPointerException();
1811:                    }
1812:
1813:                    for (int i = numPrimFields; i < fields.length; i++) {
1814:                        /* // - Back-ported from JDK 1.4 
1815:                        int key = keys[i];
1816:                        if (key == Unsafe.INVALID_FIELD_OFFSET) {
1817:                            continue;		// discard value
1818:                        }
1819:                         */
1820:                        // Skip if no reflective field - Back-ported from JDK 1.4 
1821:                        if (objFieldIDs[i - numPrimFields] == 0L)
1822:                            continue;
1823:
1824:                        switch (typeCodes[i]) {
1825:                        case 'L':
1826:                        case '[':
1827:                            Object val = vals[offsets[i]];
1828:                            if (val != null
1829:                                    && !types[i - numPrimFields]
1830:                                            .isInstance(val)) {
1831:                                Field f = fields[i].getField();
1832:                                throw new ClassCastException(
1833:                                        "cannot assign instance of "
1834:                                                + val.getClass().getName()
1835:                                                + " to field "
1836:                                                + f.getDeclaringClass()
1837:                                                        .getName() + "."
1838:                                                + f.getName() + " of type "
1839:                                                + f.getType().getName()
1840:                                                + " in instance of "
1841:                                                + obj.getClass().getName());
1842:                            }
1843:                            // Back-ported from JDK 1.4
1844:                            // unsafe.putObject(obj, key, val);
1845:                            ObjectInputStream.setObjectFieldValue(obj,
1846:                                    objFieldIDs[i - numPrimFields], types[i
1847:                                            - numPrimFields], val);
1848:                            break;
1849:
1850:                        default:
1851:                            throw new InternalError();
1852:                        }
1853:                    }
1854:                }
1855:            }
1856:
1857:            /**
1858:             * Matches given set of serializable fields with serializable fields
1859:             * described by the given local class descriptor, and returns a
1860:             * FieldReflector instance capable of setting/getting values from the
1861:             * subset of fields that match (non-matching fields are treated as filler,
1862:             * for which get operations return default values and set operations
1863:             * discard given values).  Throws InvalidClassException if unresolvable
1864:             * type conflicts exist between the two sets of fields.
1865:             */
1866:            private static FieldReflector getReflector(
1867:                    ObjectStreamField[] fields, ObjectStreamClass localDesc)
1868:                    throws InvalidClassException {
1869:                // class irrelevant if no fields
1870:                Class cl = (localDesc != null && fields.length > 0) ? localDesc.cl
1871:                        : null;
1872:                Object key = new FieldReflectorKey(cl, fields);
1873:                Object entry;
1874:                EntryFuture future = null;
1875:
1876:                synchronized (reflectors) {
1877:                    if ((entry = reflectors.get(key)) == null) {
1878:                        reflectors.put(key, future = new EntryFuture());
1879:                    }
1880:                }
1881:
1882:                if (entry instanceof  FieldReflector) { // check common case first
1883:                    return (FieldReflector) entry;
1884:                } else if (entry instanceof  EntryFuture) {
1885:                    entry = ((EntryFuture) entry).get();
1886:                } else if (entry == null) {
1887:                    try {
1888:                        entry = new FieldReflector(matchFields(fields,
1889:                                localDesc));
1890:                    } catch (Throwable th) {
1891:                        entry = th;
1892:                    }
1893:                    future.set(entry);
1894:                    synchronized (reflectors) {
1895:                        reflectors.put(key, entry);
1896:                    }
1897:                }
1898:
1899:                if (entry instanceof  FieldReflector) {
1900:                    return (FieldReflector) entry;
1901:                } else if (entry instanceof  InvalidClassException) {
1902:                    throw (InvalidClassException) entry;
1903:                } else if (entry instanceof  RuntimeException) {
1904:                    throw (RuntimeException) entry;
1905:                } else if (entry instanceof  Error) {
1906:                    throw (Error) entry;
1907:                } else {
1908:                    throw new InternalError("unexpected entry: " + entry);
1909:                }
1910:            }
1911:
1912:            /**
1913:             * FieldReflector cache lookup key.  Keys are considered equal if they
1914:             * refer to the same class and equivalent field formats.
1915:             */
1916:            private static class FieldReflectorKey {
1917:
1918:                private final Class cl;
1919:                private final String sigs;
1920:                private final int hash;
1921:
1922:                FieldReflectorKey(Class cl, ObjectStreamField[] fields) {
1923:                    /*
1924:                     * Note: maintaining a direct reference to the class does not pin
1925:                     * it indefinitely, since SoftCache removes strong refs to keys
1926:                     * when the corresponding values are gc'ed.
1927:                     */
1928:                    this .cl = cl;
1929:
1930:                    StringBuffer sbuf = new StringBuffer();
1931:                    for (int i = 0; i < fields.length; i++) {
1932:                        ObjectStreamField f = fields[i];
1933:                        sbuf.append(f.getName()).append(f.getSignature());
1934:                    }
1935:                    sigs = sbuf.toString();
1936:                    hash = System.identityHashCode(cl) + sigs.hashCode();
1937:                }
1938:
1939:                public int hashCode() {
1940:                    return hash;
1941:                }
1942:
1943:                public boolean equals(Object obj) {
1944:                    if (!(obj instanceof  FieldReflectorKey)) {
1945:                        return false;
1946:                    }
1947:                    FieldReflectorKey key = (FieldReflectorKey) obj;
1948:                    return (cl == key.cl && sigs.equals(key.sigs));
1949:                }
1950:            }
1951:
1952:            /**
1953:             * Matches given set of serializable fields with serializable fields
1954:             * obtained from the given local class descriptor (which contain bindings
1955:             * to reflective Field objects).  Returns list of ObjectStreamFields in
1956:             * which each ObjectStreamField whose signature matches that of a local
1957:             * field contains a Field object for that field; unmatched
1958:             * ObjectStreamFields contain null Field objects.  Shared/unshared settings
1959:             * of the returned ObjectStreamFields also reflect those of matched local
1960:             * ObjectStreamFields.  Throws InvalidClassException if unresolvable type
1961:             * conflicts exist between the two sets of fields.
1962:             */
1963:            private static ObjectStreamField[] matchFields(
1964:                    ObjectStreamField[] fields, ObjectStreamClass localDesc)
1965:                    throws InvalidClassException {
1966:                ObjectStreamField[] localFields = (localDesc != null) ? localDesc.fields
1967:                        : NO_FIELDS;
1968:
1969:                /*
1970:                 * Even if fields == localFields, we cannot simply return localFields
1971:                 * here.  In previous implementations of serialization,
1972:                 * ObjectStreamField.getType() returned Object.class if the
1973:                 * ObjectStreamField represented a non-primitive field and belonged to
1974:                 * a non-local class descriptor.  To preserve this (questionable)
1975:                 * behavior, the ObjectStreamField instances returned by matchFields
1976:                 * cannot report non-primitive types other than Object.class; hence
1977:                 * localFields cannot be returned directly.
1978:                 */
1979:
1980:                ObjectStreamField[] matches = new ObjectStreamField[fields.length];
1981:                for (int i = 0; i < fields.length; i++) {
1982:                    ObjectStreamField f = fields[i], m = null;
1983:                    for (int j = 0; j < localFields.length; j++) {
1984:                        ObjectStreamField lf = localFields[j];
1985:                        if (f.getName().equals(lf.getName())) {
1986:                            if ((f.isPrimitive() || lf.isPrimitive())
1987:                                    && f.getTypeCode() != lf.getTypeCode()) {
1988:                                throw new InvalidClassException(localDesc.name,
1989:                                        "incompatible types for field "
1990:                                                + f.getName());
1991:                            }
1992:                            if (lf.getField() != null) {
1993:                                m = new ObjectStreamField(lf.getField(), lf
1994:                                        .isUnshared(), false);
1995:                            } else {
1996:                                m = new ObjectStreamField(lf.getName(), lf
1997:                                        .getSignature(), lf.isUnshared());
1998:                            }
1999:                        }
2000:                    }
2001:                    if (m == null) {
2002:                        m = new ObjectStreamField(f.getName(),
2003:                                f.getSignature(), false);
2004:                    }
2005:                    m.setOffset(f.getOffset());
2006:                    matches[i] = m;
2007:                }
2008:                return matches;
2009:            }
2010:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.