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


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