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

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


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:
0018:        package java.io;
0019:
0020:        import java.io.EmulatedFields.ObjectSlot;
0021:        import java.lang.reflect.Array;
0022:        import java.lang.reflect.Constructor;
0023:        import java.lang.reflect.InvocationTargetException;
0024:        import java.lang.reflect.Method;
0025:        import java.lang.reflect.Modifier;
0026:        import java.lang.reflect.Proxy;
0027:        import java.security.AccessController;
0028:        import java.security.PrivilegedAction;
0029:        import java.util.ArrayList;
0030:        import java.util.Hashtable;
0031:        import java.util.Iterator;
0032:
0033:        import org.apache.harmony.kernel.vm.VM;
0034:        import org.apache.harmony.luni.internal.nls.Messages;
0035:        import org.apache.harmony.luni.util.Msg;
0036:        import org.apache.harmony.luni.util.PriviAction;
0037:
0038:        /**
0039:         * An ObjectInputStream can be used to load Java objects from a stream where the
0040:         * objects were saved using an ObjectOutputStream. Primitive data (ints, bytes,
0041:         * chars, etc) can also be loaded if the data was saved as primitive types as
0042:         * well. It is invalid to attempt to read an object as primitive data.
0043:         * 
0044:         * @see ObjectOutputStream
0045:         * @see ObjectInput
0046:         * @see Serializable
0047:         * @see Externalizable
0048:         */
0049:        public class ObjectInputStream extends InputStream implements 
0050:                ObjectInput, ObjectStreamConstants {
0051:
0052:            private static InputStream emptyStream = new ByteArrayInputStream(
0053:                    new byte[0]);
0054:
0055:            // To put into objectsRead when reading unsharedObject
0056:            private static final Object UNSHARED_OBJ = new Object(); // $NON-LOCK-1$
0057:
0058:            // If the receiver has already read & not consumed a TC code
0059:            private boolean hasPushbackTC;
0060:
0061:            // Push back TC code if the variable above is true
0062:            private byte pushbackTC;
0063:
0064:            // How many nested levels to readObject. When we reach 0 we have to validate
0065:            // the graph then reset it
0066:            private int nestedLevels;
0067:
0068:            // All objects are assigned an ID (integer handle)
0069:            private int currentHandle;
0070:
0071:            // Where we read from
0072:            private DataInputStream input;
0073:
0074:            // Where we read primitive types from
0075:            private DataInputStream primitiveTypes;
0076:
0077:            // Where we keep primitive type data
0078:            private InputStream primitiveData = emptyStream;
0079:
0080:            // Resolve object is a mechanism for replacement
0081:            private boolean enableResolve;
0082:
0083:            // Table mapping Integer (handle) -> Object
0084:            private Hashtable<Integer, Object> objectsRead;
0085:
0086:            // Used by defaultReadObject
0087:            private Object currentObject;
0088:
0089:            // Used by defaultReadObject
0090:            private ObjectStreamClass currentClass;
0091:
0092:            // All validations to be executed when the complete graph is read. See inner
0093:            // type below.
0094:            private InputValidationDesc[] validations;
0095:
0096:            // Allows the receiver to decide if it needs to call readObjectOverride
0097:            private boolean subclassOverridingImplementation;
0098:
0099:            // Original caller's class loader, used to perform class lookups
0100:            private ClassLoader callerClassLoader;
0101:
0102:            // false when reading missing fields
0103:            private boolean mustResolve = true;
0104:
0105:            // Handle for the current class descriptor
0106:            private Integer descriptorHandle;
0107:
0108:            private static final Hashtable<String, Class<?>> PRIMITIVE_CLASSES = new Hashtable<String, Class<?>>();
0109:
0110:            static {
0111:                PRIMITIVE_CLASSES.put("byte", byte.class); //$NON-NLS-1$
0112:                PRIMITIVE_CLASSES.put("short", short.class); //$NON-NLS-1$
0113:                PRIMITIVE_CLASSES.put("int", int.class); //$NON-NLS-1$
0114:                PRIMITIVE_CLASSES.put("long", long.class); //$NON-NLS-1$
0115:                PRIMITIVE_CLASSES.put("boolean", boolean.class); //$NON-NLS-1$
0116:                PRIMITIVE_CLASSES.put("char", char.class); //$NON-NLS-1$
0117:                PRIMITIVE_CLASSES.put("float", float.class); //$NON-NLS-1$
0118:                PRIMITIVE_CLASSES.put("double", double.class); //$NON-NLS-1$
0119:            }
0120:
0121:            // Internal type used to keep track of validators & corresponding priority
0122:            static class InputValidationDesc {
0123:                ObjectInputValidation validator;
0124:
0125:                int priority;
0126:            }
0127:
0128:            /**
0129:             * Inner class to provide access to serializable fields
0130:             */
0131:            public abstract static class GetField {
0132:                /**
0133:                 * @return ObjectStreamClass
0134:                 */
0135:                public abstract ObjectStreamClass getObjectStreamClass();
0136:
0137:                /**
0138:                 * @param name
0139:                 * @return <code>true</code> if the default value is set,
0140:                 *         <code>false</code> otherwise
0141:                 * 
0142:                 * @throws IOException
0143:                 * @throws IllegalArgumentException
0144:                 */
0145:                public abstract boolean defaulted(String name)
0146:                        throws IOException, IllegalArgumentException;
0147:
0148:                /**
0149:                 * @param name
0150:                 * @param defaultValue
0151:                 * @return the value
0152:                 * 
0153:                 * @throws IOException
0154:                 * @throws IllegalArgumentException
0155:                 */
0156:                public abstract boolean get(String name, boolean defaultValue)
0157:                        throws IOException, IllegalArgumentException;
0158:
0159:                /**
0160:                 * @param name
0161:                 * @param defaultValue
0162:                 * @return the value
0163:                 * 
0164:                 * @throws IOException
0165:                 * @throws IllegalArgumentException
0166:                 */
0167:                public abstract char get(String name, char defaultValue)
0168:                        throws IOException, IllegalArgumentException;
0169:
0170:                /**
0171:                 * @param name
0172:                 * @param defaultValue
0173:                 * @return the value
0174:                 * 
0175:                 * @throws IOException
0176:                 * @throws IllegalArgumentException
0177:                 */
0178:                public abstract byte get(String name, byte defaultValue)
0179:                        throws IOException, IllegalArgumentException;
0180:
0181:                /**
0182:                 * @param name
0183:                 * @param defaultValue
0184:                 * @return the value
0185:                 * 
0186:                 * @throws IOException
0187:                 * @throws IllegalArgumentException
0188:                 */
0189:                public abstract short get(String name, short defaultValue)
0190:                        throws IOException, IllegalArgumentException;
0191:
0192:                /**
0193:                 * @param name
0194:                 * @param defaultValue
0195:                 * @return the value
0196:                 * 
0197:                 * @throws IOException
0198:                 * @throws IllegalArgumentException
0199:                 */
0200:                public abstract int get(String name, int defaultValue)
0201:                        throws IOException, IllegalArgumentException;
0202:
0203:                /**
0204:                 * @param name
0205:                 * @param defaultValue
0206:                 * @return the value
0207:                 * 
0208:                 * @throws IOException
0209:                 * @throws IllegalArgumentException
0210:                 */
0211:                public abstract long get(String name, long defaultValue)
0212:                        throws IOException, IllegalArgumentException;
0213:
0214:                /**
0215:                 * @param name
0216:                 * @param defaultValue
0217:                 * @return the value
0218:                 * 
0219:                 * @throws IOException
0220:                 * @throws IllegalArgumentException
0221:                 */
0222:                public abstract float get(String name, float defaultValue)
0223:                        throws IOException, IllegalArgumentException;
0224:
0225:                /**
0226:                 * @param name
0227:                 * @param defaultValue
0228:                 * @return the value
0229:                 * 
0230:                 * @throws IOException
0231:                 * @throws IllegalArgumentException
0232:                 */
0233:                public abstract double get(String name, double defaultValue)
0234:                        throws IOException, IllegalArgumentException;
0235:
0236:                /**
0237:                 * @param name
0238:                 * @param defaultValue
0239:                 * @return the value
0240:                 * 
0241:                 * @throws IOException
0242:                 * @throws IllegalArgumentException
0243:                 */
0244:                public abstract Object get(String name, Object defaultValue)
0245:                        throws IOException, IllegalArgumentException;
0246:            }
0247:
0248:            /**
0249:             * Constructs a new ObjectInputStream. The representation and proper
0250:             * initialization is on the hands of subclasses.
0251:             * 
0252:             * @throws IOException
0253:             *             If not called from a subclass
0254:             * @throws SecurityException
0255:             *             If subclasses are not allowed
0256:             * 
0257:             * @see SecurityManager#checkPermission(java.security.Permission)
0258:             */
0259:            protected ObjectInputStream() throws IOException, SecurityException {
0260:                super ();
0261:                SecurityManager currentManager = System.getSecurityManager();
0262:                if (currentManager != null) {
0263:                    currentManager
0264:                            .checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
0265:                }
0266:                // WARNING - we should throw IOException if not called from a subclass
0267:                // according to the JavaDoc. Add the test.
0268:                this .subclassOverridingImplementation = true;
0269:            }
0270:
0271:            /**
0272:             * Constructs a new ObjectInputStream on the InputStream <code>input</code>.
0273:             * All reads are now filtered through this stream.
0274:             * 
0275:             * @param input
0276:             *            The non-null InputStream to filter reads on.
0277:             * 
0278:             * @throws IOException
0279:             *             If an IO exception happened when reading the stream header.
0280:             * @throws StreamCorruptedException
0281:             *             If the underlying stream does not contain serialized objects
0282:             *             that can be read.
0283:             */
0284:            public ObjectInputStream(InputStream input)
0285:                    throws StreamCorruptedException, IOException {
0286:                final Class<?> implementationClass = getClass();
0287:                final Class<?> this Class = ObjectInputStream.class;
0288:                SecurityManager sm = System.getSecurityManager();
0289:                if (sm != null && implementationClass != this Class) {
0290:                    boolean mustCheck = (AccessController
0291:                            .doPrivileged(new PrivilegedAction<Boolean>() {
0292:                                public Boolean run() {
0293:                                    try {
0294:                                        Method method = implementationClass
0295:                                                .getMethod(
0296:                                                        "readFields", //$NON-NLS-1$
0297:                                                        ObjectStreamClass.EMPTY_CONSTRUCTOR_PARAM_TYPES);
0298:                                        if (method.getDeclaringClass() != this Class) {
0299:                                            return Boolean.TRUE;
0300:                                        }
0301:                                    } catch (NoSuchMethodException e) {
0302:                                    }
0303:                                    try {
0304:                                        Method method = implementationClass
0305:                                                .getMethod(
0306:                                                        "readUnshared", //$NON-NLS-1$
0307:                                                        ObjectStreamClass.EMPTY_CONSTRUCTOR_PARAM_TYPES);
0308:                                        if (method.getDeclaringClass() != this Class) {
0309:                                            return Boolean.TRUE;
0310:                                        }
0311:                                    } catch (NoSuchMethodException e) {
0312:                                    }
0313:                                    return Boolean.FALSE;
0314:                                }
0315:                            })).booleanValue();
0316:                    if (mustCheck) {
0317:                        sm
0318:                                .checkPermission(ObjectStreamConstants.SUBCLASS_IMPLEMENTATION_PERMISSION);
0319:                    }
0320:                }
0321:                this .input = (input instanceof  DataInputStream) ? (DataInputStream) input
0322:                        : new DataInputStream(input);
0323:                primitiveTypes = new DataInputStream(this );
0324:                enableResolve = false;
0325:                this .subclassOverridingImplementation = false;
0326:                resetState();
0327:                nestedLevels = 0;
0328:                // So read...() methods can be used by
0329:                // subclasses during readStreamHeader()
0330:                primitiveData = this .input;
0331:                // Has to be done here according to the specification
0332:                readStreamHeader();
0333:                primitiveData = emptyStream;
0334:            }
0335:
0336:            /**
0337:             * Returns the number of bytes of primitive data available from the
0338:             * receiver. It should not be used at any arbitrary position; just when
0339:             * reading primitive data types (ints, chars, etc).
0340:             * 
0341:             * @return the number of available primitive data bytes
0342:             * 
0343:             * @throws IOException
0344:             *             If any IO problem occurred when trying to compute the bytes
0345:             *             available.
0346:             */
0347:            @Override
0348:            public int available() throws IOException {
0349:                // returns 0 if next data is an object, or N if reading primitive types
0350:                checkReadPrimitiveTypes();
0351:                return primitiveData.available();
0352:            }
0353:
0354:            /**
0355:             * Checks to see if it is ok to read primitive types at this point from the
0356:             * receiver. One is not supposed to read primitive types when about to read
0357:             * an object, for example, so an exception has to be thrown.
0358:             * 
0359:             * @throws IOException
0360:             *             If any IO problem occurred when trying to read primitive type
0361:             *             or if it is illegal to read primitive types
0362:             */
0363:            private void checkReadPrimitiveTypes() throws IOException {
0364:                // If we still have primitive data, it is ok to read primitive data
0365:                if (primitiveData == input || primitiveData.available() > 0) {
0366:                    return;
0367:                }
0368:
0369:                // If we got here either we had no Stream previously created or
0370:                // we no longer have data in that one, so get more bytes
0371:                do {
0372:                    int next = 0;
0373:                    if (hasPushbackTC) {
0374:                        hasPushbackTC = false;
0375:                    } else {
0376:                        next = input.read();
0377:                        pushbackTC = (byte) next;
0378:                    }
0379:                    switch (pushbackTC) {
0380:                    case TC_BLOCKDATA:
0381:                        primitiveData = new ByteArrayInputStream(
0382:                                readBlockData());
0383:                        return;
0384:                    case TC_BLOCKDATALONG:
0385:                        primitiveData = new ByteArrayInputStream(
0386:                                readBlockDataLong());
0387:                        return;
0388:                    case TC_RESET:
0389:                        resetState();
0390:                        break;
0391:                    default:
0392:                        if (next != -1) {
0393:                            pushbackTC();
0394:                        }
0395:                        return;
0396:                    }
0397:                    // Only TC_RESET falls through
0398:                } while (true);
0399:            }
0400:
0401:            /**
0402:             * Close this ObjectInputStream. This implementation closes the target
0403:             * stream.
0404:             * 
0405:             * @throws IOException
0406:             *             If an error occurs attempting to close this stream.
0407:             */
0408:            @Override
0409:            public void close() throws IOException {
0410:                input.close();
0411:            }
0412:
0413:            /**
0414:             * Default method to read objects from the receiver. Fields defined in the
0415:             * object's class and super classes (which are Serializable) will be read.
0416:             * 
0417:             * @throws IOException
0418:             *             If an IO error occurs attempting to read the object data
0419:             * @throws ClassNotFoundException
0420:             *             If the class of the object cannot be found
0421:             * @throws NotActiveException
0422:             *             If this method is not called from readObject()
0423:             * 
0424:             * @see ObjectOutputStream#defaultWriteObject
0425:             */
0426:            public void defaultReadObject() throws IOException,
0427:                    ClassNotFoundException, NotActiveException {
0428:                // We can't be called from just anywhere. There are rules.
0429:                if (currentObject != null || !mustResolve) {
0430:                    readFieldValues(currentObject, currentClass);
0431:                } else {
0432:                    throw new NotActiveException();
0433:                }
0434:            }
0435:
0436:            /**
0437:             * Enables/disables object replacement for the receiver. By default this is
0438:             * not enabled. Only trusted subclasses (loaded with system class loader)
0439:             * can override this behavior.
0440:             * 
0441:             * @param enable
0442:             *            if true, enables replacement. If false, disables replacement.
0443:             * @return the previous configuration (if it was enabled or disabled)
0444:             * 
0445:             * @throws SecurityException
0446:             *             If the class of the receiver is not trusted
0447:             * 
0448:             * @see #resolveObject
0449:             * @see ObjectOutputStream#enableReplaceObject
0450:             */
0451:            protected boolean enableResolveObject(boolean enable)
0452:                    throws SecurityException {
0453:                if (enable) {
0454:                    // The Stream has to be trusted for this feature to be enabled.
0455:                    // trusted means the stream's classloader has to be null
0456:                    SecurityManager currentManager = System
0457:                            .getSecurityManager();
0458:                    if (currentManager != null) {
0459:                        currentManager.checkPermission(SUBSTITUTION_PERMISSION);
0460:                    }
0461:                }
0462:                boolean originalValue = enableResolve;
0463:                enableResolve = enable;
0464:                return originalValue;
0465:            }
0466:
0467:            /**
0468:             * Checks if two classes belong to the same package and returns true in the
0469:             * positive case. Return false otherwise.
0470:             * 
0471:             * @param c1
0472:             *            one of the classes to test
0473:             * @param c2
0474:             *            the other class to test
0475:             * @return <code>true</code> if the two classes belong to the same
0476:             *         package, <code>false</code> otherwise
0477:             */
0478:            private boolean inSamePackage(Class<?> c1, Class<?> c2) {
0479:                String nameC1 = c1.getName();
0480:                String nameC2 = c2.getName();
0481:                int indexDotC1 = nameC1.lastIndexOf('.');
0482:                int indexDotC2 = nameC2.lastIndexOf('.');
0483:                if (indexDotC1 != indexDotC2) {
0484:                    return false; // cannot be in the same package if indices are not
0485:                }
0486:                // the same
0487:                if (indexDotC1 < 0) {
0488:                    return true; // both of them are in default package
0489:                }
0490:                return nameC1.substring(0, indexDotC1).equals(
0491:                        nameC2.substring(0, indexDotC2));
0492:            }
0493:
0494:            /**
0495:             * Create and return a new instance of class <code>instantiationClass</code>
0496:             * but running the constructor defined in class
0497:             * <code>constructorClass</code> (same as <code>instantiationClass</code>
0498:             * or a superclass).
0499:             * 
0500:             * Has to be native to avoid visibility rules and to be able to have
0501:             * <code>instantiationClass</code> not the same as
0502:             * <code>constructorClass</code> (no such API in java.lang.reflect).
0503:             * 
0504:             * @param instantiationClass
0505:             *            The new object will be an instance of this class
0506:             * @param constructorClass
0507:             *            The empty constructor to run will be in this class
0508:             * @return the object created from <code>instantiationClass</code>
0509:             */
0510:            private static native Object newInstance(
0511:                    Class<?> instantiationClass, Class<?> constructorClass);
0512:
0513:            /**
0514:             * Return the next <code>int</code> handle to be used to indicate cyclic
0515:             * references being loaded from the stream.
0516:             * 
0517:             * @return the next handle to represent the next cyclic reference
0518:             */
0519:            private int nextHandle() {
0520:                return this .currentHandle++;
0521:            }
0522:
0523:            /**
0524:             * Return the next token code (TC) from the receiver, which indicates what
0525:             * kind of object follows
0526:             * 
0527:             * @return the next TC from the receiver
0528:             * 
0529:             * @throws IOException
0530:             *             If an IO error occurs
0531:             * 
0532:             * @see ObjectStreamConstants
0533:             */
0534:            private byte nextTC() throws IOException {
0535:                if (hasPushbackTC) {
0536:                    hasPushbackTC = false; // We are consuming it
0537:                } else {
0538:                    // Just in case a later call decides to really push it back,
0539:                    // we don't require the caller to pass it as parameter
0540:                    pushbackTC = input.readByte();
0541:                }
0542:                return pushbackTC;
0543:            }
0544:
0545:            /**
0546:             * Pushes back the last TC code read
0547:             */
0548:            private void pushbackTC() {
0549:                hasPushbackTC = true;
0550:            }
0551:
0552:            /**
0553:             * Reads a single byte from the receiver and returns the result as an int.
0554:             * The low-order byte is returned or -1 of the end of stream was
0555:             * encountered.
0556:             * 
0557:             * @return The byte read or -1 if end of stream.
0558:             * 
0559:             * @throws IOException
0560:             *             If an IO exception happened when reading the primitive data.
0561:             */
0562:            @Override
0563:            public int read() throws IOException {
0564:                checkReadPrimitiveTypes();
0565:                return primitiveData.read();
0566:            }
0567:
0568:            /**
0569:             * Reads at most <code>length</code> bytes from the receiver and stores
0570:             * them in byte array <code>buffer</code> starting at offset
0571:             * <code>offset</code>. Answer the number of bytes actually read or -1 if
0572:             * no bytes were read and end of stream was encountered.
0573:             * 
0574:             * @param buffer
0575:             *            the byte array in which to store the read bytes.
0576:             * @param offset
0577:             *            the offset in <code>buffer</code> to store the read bytes.
0578:             * @param length
0579:             *            the maximum number of bytes to store in <code>buffer</code>.
0580:             * @return The number of bytes actually read or -1 if end of stream.
0581:             * 
0582:             * @throws IOException
0583:             *             If an IO exception happened when reading the primitive data.
0584:             */
0585:            @Override
0586:            public int read(byte[] buffer, int offset, int length)
0587:                    throws IOException {
0588:                if (buffer == null) {
0589:                    throw new NullPointerException();
0590:                }
0591:                // avoid int overflow
0592:                if (offset < 0 || offset > buffer.length || length < 0
0593:                        || length > buffer.length - offset) {
0594:                    throw new ArrayIndexOutOfBoundsException();
0595:                }
0596:                if (length == 0) {
0597:                    return 0;
0598:                }
0599:                checkReadPrimitiveTypes();
0600:                return primitiveData.read(buffer, offset, length);
0601:            }
0602:
0603:            /**
0604:             * Reads and returns an array of raw bytes with primitive data. The array
0605:             * will have up to 255 bytes. The primitive data will be in the format
0606:             * described by <code>DataOutputStream</code>.
0607:             * 
0608:             * @return The primitive data read, as raw bytes
0609:             * 
0610:             * @throws IOException
0611:             *             If an IO exception happened when reading the primitive data.
0612:             */
0613:            private byte[] readBlockData() throws IOException {
0614:                byte[] result = new byte[input.readByte() & 0xff];
0615:                input.readFully(result);
0616:                return result;
0617:            }
0618:
0619:            /**
0620:             * Reads and returns an array of raw bytes with primitive data. The array
0621:             * will have more than 255 bytes. The primitive data will be in the format
0622:             * described by <code>DataOutputStream</code>.
0623:             * 
0624:             * @return The primitive data read, as raw bytes
0625:             * 
0626:             * @throws IOException
0627:             *             If an IO exception happened when reading the primitive data.
0628:             */
0629:            private byte[] readBlockDataLong() throws IOException {
0630:                byte[] result = new byte[input.readInt()];
0631:                input.readFully(result);
0632:                return result;
0633:            }
0634:
0635:            /**
0636:             * Reads and returns primitive data of type boolean read from the receiver
0637:             * 
0638:             * @return A boolean saved as primitive data using
0639:             *         <code>ObjectOutputStream.writeBoolean()</code>
0640:             * 
0641:             * @throws IOException
0642:             *             If an IO exception happened when reading the primitive data.
0643:             */
0644:            public boolean readBoolean() throws IOException {
0645:                return primitiveTypes.readBoolean();
0646:            }
0647:
0648:            /**
0649:             * Reads and returns primitive data of type byte read from the receiver
0650:             * 
0651:             * @return A byte saved as primitive data using
0652:             *         <code>ObjectOutputStream.writeByte()</code>
0653:             * 
0654:             * @throws IOException
0655:             *             If an IO exception happened when reading the primitive data.
0656:             */
0657:            public byte readByte() throws IOException {
0658:                return primitiveTypes.readByte();
0659:            }
0660:
0661:            /**
0662:             * Reads and returns primitive data of type char read from the receiver
0663:             * 
0664:             * @return A char saved as primitive data using
0665:             *         <code>ObjectOutputStream.writeChar()</code>
0666:             * 
0667:             * @throws IOException
0668:             *             If an IO exception happened when reading the primitive data.
0669:             */
0670:            public char readChar() throws IOException {
0671:                return primitiveTypes.readChar();
0672:            }
0673:
0674:            /**
0675:             * Reads and discards block data and objects until TC_ENDBLOCKDATA is found.
0676:             * 
0677:             * @throws IOException
0678:             *             If an IO exception happened when reading the optional class
0679:             *             annotation.
0680:             * @throws ClassNotFoundException
0681:             *             If the class corresponding to the class descriptor could not
0682:             *             be found.
0683:             */
0684:            private void discardData() throws ClassNotFoundException,
0685:                    IOException {
0686:                primitiveData = emptyStream;
0687:                boolean resolve = mustResolve;
0688:                mustResolve = false;
0689:                do {
0690:                    byte tc = nextTC();
0691:                    if (tc == TC_ENDBLOCKDATA) {
0692:                        mustResolve = resolve;
0693:                        return; // End of annotation
0694:                    }
0695:                    readContent(tc);
0696:                } while (true);
0697:            }
0698:
0699:            /**
0700:             * Reads a class descriptor (an <code>ObjectStreamClass</code>) from the
0701:             * stream.
0702:             * 
0703:             * @return the class descriptor read from the stream
0704:             * 
0705:             * @throws IOException
0706:             *             If an IO exception happened when reading the class
0707:             *             descriptor.
0708:             * @throws ClassNotFoundException
0709:             *             If the class corresponding to the class descriptor could not
0710:             *             be found.
0711:             */
0712:            private ObjectStreamClass readClassDesc()
0713:                    throws ClassNotFoundException, IOException {
0714:                byte tc = nextTC();
0715:                switch (tc) {
0716:                case TC_CLASSDESC:
0717:                    return readNewClassDesc(false);
0718:                case TC_PROXYCLASSDESC:
0719:                    Class<?> proxyClass = readNewProxyClassDesc();
0720:                    ObjectStreamClass streamClass = ObjectStreamClass
0721:                            .lookup(proxyClass);
0722:                    streamClass.setLoadFields(new ObjectStreamField[0]);
0723:                    registerObjectRead(streamClass, Integer
0724:                            .valueOf(nextHandle()), false);
0725:                    checkedSetSuperClassDesc(streamClass, readClassDesc());
0726:                    return streamClass;
0727:                case TC_REFERENCE:
0728:                    return (ObjectStreamClass) readCyclicReference();
0729:                case TC_NULL:
0730:                    return null;
0731:                default:
0732:                    throw new StreamCorruptedException(Msg.getString(
0733:                            "K00d2", Integer.toHexString(tc & 0xff))); //$NON-NLS-1$
0734:                }
0735:            }
0736:
0737:            /**
0738:             * Reads the content of the receiver based on the previously read token
0739:             * <code>tc</code>.
0740:             * 
0741:             * @param tc
0742:             *            The token code for the next item in the stream
0743:             * @return the object read from the stream
0744:             * 
0745:             * @throws IOException
0746:             *             If an IO exception happened when reading the class
0747:             *             descriptor.
0748:             * @throws ClassNotFoundException
0749:             *             If the class corresponding to the object being read could not
0750:             *             be found.
0751:             */
0752:            private Object readContent(byte tc) throws ClassNotFoundException,
0753:                    IOException {
0754:                switch (tc) {
0755:                case TC_BLOCKDATA:
0756:                    return readBlockData();
0757:                case TC_BLOCKDATALONG:
0758:                    return readBlockDataLong();
0759:                case TC_CLASS:
0760:                    return readNewClass(false);
0761:                case TC_CLASSDESC:
0762:                    return readNewClassDesc(false);
0763:                case TC_ARRAY:
0764:                    return readNewArray(false);
0765:                case TC_OBJECT:
0766:                    return readNewObject(false);
0767:                case TC_STRING:
0768:                    return readNewString(false);
0769:                case TC_LONGSTRING:
0770:                    return readNewLongString(false);
0771:                case TC_REFERENCE:
0772:                    return readCyclicReference();
0773:                case TC_NULL:
0774:                    return null;
0775:                case TC_EXCEPTION:
0776:                    Exception exc = readException();
0777:                    throw new WriteAbortedException(Msg.getString("K00d3"), exc); //$NON-NLS-1$
0778:                case TC_RESET:
0779:                    resetState();
0780:                    return null;
0781:                default:
0782:                    throw new StreamCorruptedException(Msg.getString(
0783:                            "K00d2", Integer.toHexString(tc & 0xff))); //$NON-NLS-1$
0784:                }
0785:            }
0786:
0787:            /**
0788:             * Reads the content of the receiver based on the previously read token
0789:             * <code>tc</code>. Primitive data content is considered an error.
0790:             * 
0791:             * @param unshared
0792:             *            read the object unshared
0793:             * @return the object read from the stream
0794:             * 
0795:             * @throws IOException
0796:             *             If an IO exception happened when reading the class
0797:             *             descriptor.
0798:             * @throws ClassNotFoundException
0799:             *             If the class corresponding to the object being read could not
0800:             *             be found.
0801:             */
0802:            private Object readNonPrimitiveContent(boolean unshared)
0803:                    throws ClassNotFoundException, IOException {
0804:                checkReadPrimitiveTypes();
0805:                if (primitiveData.available() > 0) {
0806:                    OptionalDataException e = new OptionalDataException();
0807:                    e.length = primitiveData.available();
0808:                    throw e;
0809:                }
0810:
0811:                do {
0812:                    byte tc = nextTC();
0813:                    switch (tc) {
0814:                    case TC_CLASS:
0815:                        return readNewClass(unshared);
0816:                    case TC_CLASSDESC:
0817:                        return readNewClassDesc(unshared);
0818:                    case TC_ARRAY:
0819:                        return readNewArray(unshared);
0820:                    case TC_OBJECT:
0821:                        return readNewObject(unshared);
0822:                    case TC_STRING:
0823:                        return readNewString(unshared);
0824:                    case TC_LONGSTRING:
0825:                        return readNewLongString(unshared);
0826:                    case TC_ENUM:
0827:                        return readEnum(unshared);
0828:                    case TC_REFERENCE:
0829:                        if (unshared) {
0830:                            readNewHandle();
0831:                            throw new InvalidObjectException(Msg
0832:                                    .getString("KA002")); //$NON-NLS-1$
0833:                        }
0834:                        return readCyclicReference();
0835:                    case TC_NULL:
0836:                        return null;
0837:                    case TC_EXCEPTION:
0838:                        Exception exc = readException();
0839:                        throw new WriteAbortedException(
0840:                                Msg.getString("K00d3"), exc); //$NON-NLS-1$
0841:                    case TC_RESET:
0842:                        resetState();
0843:                        break;
0844:                    case TC_ENDBLOCKDATA: // Can occur reading class annotation
0845:                        pushbackTC();
0846:                        OptionalDataException e = new OptionalDataException();
0847:                        e.eof = true;
0848:                        throw e;
0849:                    default:
0850:                        throw new StreamCorruptedException(Msg.getString(
0851:                                "K00d2", Integer.toHexString(tc & 0xff))); //$NON-NLS-1$
0852:                    }
0853:                    // Only TC_RESET falls through
0854:                } while (true);
0855:            }
0856:
0857:            /**
0858:             * Reads the next item from the stream assuming it is a cyclic reference to
0859:             * an object previously read. Return the actual object previously read.
0860:             * 
0861:             * @return the object previously read from the stream
0862:             * 
0863:             * @throws IOException
0864:             *             If an IO exception happened when reading the class
0865:             *             descriptor.
0866:             * @throws InvalidObjectException
0867:             *             If the cyclic reference is not valid.
0868:             */
0869:            private Object readCyclicReference() throws InvalidObjectException,
0870:                    IOException {
0871:                return registeredObjectRead(readNewHandle());
0872:            }
0873:
0874:            /**
0875:             * Reads and returns primitive data of type double read from the receiver
0876:             * 
0877:             * @return A double saved as primitive data using
0878:             *         <code>ObjectOutputStream.writeDouble()</code>
0879:             * 
0880:             * @throws IOException
0881:             *             If an IO exception happened when reading the primitive data.
0882:             */
0883:            public double readDouble() throws IOException {
0884:                return primitiveTypes.readDouble();
0885:            }
0886:
0887:            /**
0888:             * Read the next item assuming it is an exception. The exception is not a
0889:             * regular instance in the object graph, but the exception instance that
0890:             * happened (if any) when dumping the original object graph. The set of seen
0891:             * objects will be reset just before and just after loading this exception
0892:             * object.
0893:             * <p>
0894:             * When exceptions are found normally in the object graph, they are loaded
0895:             * as a regular object, and not by this method. In that case, the set of
0896:             * "known objects" is not reset.
0897:             * 
0898:             * @return the exception read
0899:             * 
0900:             * @throws IOException
0901:             *             If an IO exception happened when reading the exception
0902:             *             object.
0903:             * @throws ClassNotFoundException
0904:             *             If a class could not be found when reading the object graph
0905:             *             for the exception
0906:             * @throws OptionalDataException
0907:             *             If optional data could not be found when reading the
0908:             *             exception graph
0909:             * @throws WriteAbortedException
0910:             *             If another exception was caused when dumping this exception
0911:             */
0912:            private Exception readException() throws WriteAbortedException,
0913:                    OptionalDataException, ClassNotFoundException, IOException {
0914:
0915:                resetSeenObjects();
0916:
0917:                // Now we read the Throwable object that was saved
0918:                // WARNING - the grammar says it is a Throwable, but the
0919:                // WriteAbortedException constructor takes an Exception. So, we read an
0920:                // Exception from the stream
0921:                Exception exc = (Exception) readObject();
0922:
0923:                // We reset the receiver's state (the grammar has "reset" in normal
0924:                // font)
0925:                resetSeenObjects();
0926:                return exc;
0927:            }
0928:
0929:            /**
0930:             * Reads a collection of field descriptors (name, type name, etc) for the
0931:             * class descriptor <code>cDesc</code> (an <code>ObjectStreamClass</code>)
0932:             * 
0933:             * @param cDesc
0934:             *            The class descriptor (an <code>ObjectStreamClass</code>)
0935:             *            for which to write field information
0936:             * 
0937:             * @throws IOException
0938:             *             If an IO exception happened when reading the field
0939:             *             descriptors.
0940:             * @throws ClassNotFoundException
0941:             *             If a class for one of the field types could not be found
0942:             * 
0943:             * @see #readObject()
0944:             */
0945:            private void readFieldDescriptors(ObjectStreamClass cDesc)
0946:                    throws ClassNotFoundException, IOException {
0947:                short numFields = input.readShort();
0948:                ObjectStreamField[] fields = new ObjectStreamField[numFields];
0949:
0950:                // We set it now, but each element will be inserted in the array further
0951:                // down
0952:                cDesc.setLoadFields(fields);
0953:
0954:                // Check ObjectOutputStream.writeFieldDescriptors
0955:                for (short i = 0; i < numFields; i++) {
0956:                    char typecode = (char) input.readByte();
0957:                    String fieldName = input.readUTF();
0958:                    boolean isPrimType = ObjectStreamClass
0959:                            .isPrimitiveType(typecode);
0960:                    String classSig;
0961:                    if (isPrimType) {
0962:                        classSig = String.valueOf(typecode);
0963:                    } else {
0964:                        // The spec says it is a UTF, but experience shows they dump
0965:                        // this String using writeObject (unlike the field name, which
0966:                        // is saved with writeUTF).
0967:                        // And if resolveObject is enabled, the classSig may be modified
0968:                        // so that the original class descriptor cannot be read
0969:                        // properly, so it is disabled.
0970:                        boolean old = enableResolve;
0971:                        try {
0972:                            enableResolve = false;
0973:                            classSig = (String) readObject();
0974:                        } finally {
0975:                            enableResolve = old;
0976:                        }
0977:                    }
0978:
0979:                    classSig = formatClassSig(classSig);
0980:                    ObjectStreamField f = new ObjectStreamField(classSig,
0981:                            fieldName);
0982:                    fields[i] = f;
0983:                }
0984:            }
0985:
0986:            /*
0987:             * Format the class signature for ObjectStreamField, for example,
0988:             * "[L[Ljava.lang.String;;" is converted to "[Ljava.lang.String;"
0989:             */
0990:            private static String formatClassSig(String classSig) {
0991:                int start = 0;
0992:                int end = classSig.length();
0993:
0994:                if (end <= 0) {
0995:                    return classSig;
0996:                }
0997:
0998:                while (classSig.startsWith("[L", start) //$NON-NLS-1$
0999:                        && classSig.charAt(end - 1) == ';') {
1000:                    start += 2;
1001:                    end--;
1002:                }
1003:
1004:                if (start > 0) {
1005:                    start -= 2;
1006:                    end++;
1007:                    return classSig.substring(start, end);
1008:                }
1009:                return classSig;
1010:            }
1011:
1012:            /**
1013:             * Reads the fields of the object being read from the stream. The stream
1014:             * will use the currently active <code>getField</code> object, allowing
1015:             * users to load emulated fields, for cross-loading compatibility when a
1016:             * class definition changes.
1017:             * 
1018:             * @return the fields being read
1019:             * 
1020:             * @throws IOException
1021:             *             If an IO exception happened
1022:             * @throws ClassNotFoundException
1023:             *             If a class of an object being de-serialized can not be found
1024:             * @throws NotActiveException
1025:             *             If there is no object currently being loaded (invalid to call
1026:             *             this method)
1027:             */
1028:            public GetField readFields() throws IOException,
1029:                    ClassNotFoundException, NotActiveException {
1030:                // We can't be called from just anywhere. There are rules.
1031:                if (currentObject == null) {
1032:                    throw new NotActiveException();
1033:                }
1034:                EmulatedFieldsForLoading result = new EmulatedFieldsForLoading(
1035:                        currentClass);
1036:                readFieldValues(result);
1037:                return result;
1038:            }
1039:
1040:            /**
1041:             * Reads a collection of field values for the emulated fields
1042:             * <code>emulatedFields</code>
1043:             * 
1044:             * @param emulatedFields
1045:             *            an <code>EmulatedFieldsForLoading</code>, concrete subclass
1046:             *            of <code>GetField</code>
1047:             * 
1048:             * @throws IOException
1049:             *             If an IO exception happened when reading the field values.
1050:             * @throws InvalidClassException
1051:             *             If an incompatible type is being assigned to an emulated
1052:             *             field.
1053:             * @throws OptionalDataException
1054:             *             If optional data could not be found when reading the
1055:             *             exception graph
1056:             * 
1057:             * @see #readFields
1058:             * @see #readObject()
1059:             */
1060:            private void readFieldValues(EmulatedFieldsForLoading emulatedFields)
1061:                    throws OptionalDataException, InvalidClassException,
1062:                    IOException {
1063:                EmulatedFields.ObjectSlot[] slots = emulatedFields
1064:                        .emulatedFields().slots();
1065:                for (ObjectSlot element : slots) {
1066:                    element.defaulted = false;
1067:                    Class<?> type = element.field.getType();
1068:                    if (type == Integer.TYPE) {
1069:                        element.fieldValue = Integer.valueOf(input.readInt());
1070:                    } else if (type == Byte.TYPE) {
1071:                        element.fieldValue = Byte.valueOf(input.readByte());
1072:                    } else if (type == Character.TYPE) {
1073:                        element.fieldValue = Character
1074:                                .valueOf(input.readChar());
1075:                    } else if (type == Short.TYPE) {
1076:                        element.fieldValue = Short.valueOf(input.readShort());
1077:                    } else if (type == Boolean.TYPE) {
1078:                        element.fieldValue = Boolean.valueOf(input
1079:                                .readBoolean());
1080:                    } else if (type == Long.TYPE) {
1081:                        element.fieldValue = Long.valueOf(input.readLong());
1082:                    } else if (type == Float.TYPE) {
1083:                        element.fieldValue = Float.valueOf(input.readFloat());
1084:                    } else if (type == Double.TYPE) {
1085:                        element.fieldValue = Double.valueOf(input.readDouble());
1086:                    } else {
1087:                        // Either array or Object
1088:                        try {
1089:                            element.fieldValue = readObject();
1090:                        } catch (ClassNotFoundException cnf) {
1091:                            // WARNING- Not sure this is the right thing to do. Write
1092:                            // test case.
1093:                            throw new InvalidClassException(cnf.toString());
1094:                        }
1095:                    }
1096:                }
1097:            }
1098:
1099:            /**
1100:             * Reads a collection of field values for the class descriptor
1101:             * <code>classDesc</code> (an <code>ObjectStreamClass</code>). The
1102:             * values will be used to set instance fields in object <code>obj</code>.
1103:             * This is the default mechanism, when emulated fields (an
1104:             * <code>GetField</code>) are not used. Actual values to load are stored
1105:             * directly into the object <code>obj</code>.
1106:             * 
1107:             * @param obj
1108:             *            Instance in which the fields will be set.
1109:             * @param classDesc
1110:             *            A class descriptor (an <code>ObjectStreamClass</code>)
1111:             *            defining which fields should be loaded.
1112:             * 
1113:             * @throws IOException
1114:             *             If an IO exception happened when reading the field values.
1115:             * @throws InvalidClassException
1116:             *             If an incompatible type is being assigned to an emulated
1117:             *             field.
1118:             * @throws OptionalDataException
1119:             *             If optional data could not be found when reading the
1120:             *             exception graph
1121:             * @throws ClassNotFoundException
1122:             *             If a class of an object being de-serialized can not be found
1123:             * 
1124:             * @see #readFields
1125:             * @see #readObject()
1126:             */
1127:            private void readFieldValues(Object obj, ObjectStreamClass classDesc)
1128:                    throws OptionalDataException, ClassNotFoundException,
1129:                    IOException {
1130:                // Now we must read all fields and assign them to the receiver
1131:                ObjectStreamField[] fields = classDesc.getLoadFields();
1132:                fields = (null == fields ? new ObjectStreamField[] {} : fields);
1133:                Class<?> declaringClass = classDesc.forClass();
1134:                if (declaringClass == null && mustResolve) {
1135:                    throw new ClassNotFoundException(classDesc.getName());
1136:                }
1137:
1138:                for (ObjectStreamField fieldDesc : fields) {
1139:                    // Code duplication starts, just because Java is typed
1140:                    if (fieldDesc.isPrimitive()) {
1141:                        try {
1142:                            switch (fieldDesc.getTypeCode()) {
1143:                            case 'B':
1144:                                setField(obj, declaringClass, fieldDesc
1145:                                        .getName(), input.readByte());
1146:                                break;
1147:                            case 'C':
1148:                                setField(obj, declaringClass, fieldDesc
1149:                                        .getName(), input.readChar());
1150:                                break;
1151:                            case 'D':
1152:                                setField(obj, declaringClass, fieldDesc
1153:                                        .getName(), input.readDouble());
1154:                                break;
1155:                            case 'F':
1156:                                setField(obj, declaringClass, fieldDesc
1157:                                        .getName(), input.readFloat());
1158:                                break;
1159:                            case 'I':
1160:                                setField(obj, declaringClass, fieldDesc
1161:                                        .getName(), input.readInt());
1162:                                break;
1163:                            case 'J':
1164:                                setField(obj, declaringClass, fieldDesc
1165:                                        .getName(), input.readLong());
1166:                                break;
1167:                            case 'S':
1168:                                setField(obj, declaringClass, fieldDesc
1169:                                        .getName(), input.readShort());
1170:                                break;
1171:                            case 'Z':
1172:                                setField(obj, declaringClass, fieldDesc
1173:                                        .getName(), input.readBoolean());
1174:                                break;
1175:                            default:
1176:                                throw new StreamCorruptedException(
1177:                                        Msg
1178:                                                .getString(
1179:                                                        "K00d5", fieldDesc.getTypeCode())); //$NON-NLS-1$
1180:                            }
1181:                        } catch (NoSuchFieldError err) {
1182:                        }
1183:                    } else {
1184:                        // Object type (array included).
1185:                        String fieldName = fieldDesc.getName();
1186:                        boolean setBack = false;
1187:                        if (mustResolve && fieldDesc == null) {
1188:                            setBack = true;
1189:                            mustResolve = false;
1190:                        }
1191:                        Object toSet;
1192:                        if (fieldDesc != null && fieldDesc.isUnshared()) {
1193:                            toSet = readUnshared();
1194:                        } else {
1195:                            toSet = readObject();
1196:                        }
1197:                        if (setBack) {
1198:                            mustResolve = true;
1199:                        }
1200:                        if (fieldDesc != null) {
1201:                            if (toSet != null) {
1202:                                Class<?> fieldType = fieldDesc.getType();
1203:                                Class<?> valueType = toSet.getClass();
1204:                                if (!fieldType.isAssignableFrom(valueType)) {
1205:                                    throw new ClassCastException(Msg.getString(
1206:                                            "K00d4", new String[] { //$NON-NLS-1$
1207:                                            fieldType.toString(),
1208:                                                    valueType.toString(),
1209:                                                    classDesc.getName() + "." //$NON-NLS-1$
1210:                                                            + fieldName }));
1211:                                }
1212:                                try {
1213:                                    objSetField(obj, declaringClass, fieldName,
1214:                                            fieldDesc.getTypeString(), toSet);
1215:                                } catch (NoSuchFieldError e) {
1216:                                    // Ignored
1217:                                }
1218:                            }
1219:                        }
1220:                    }
1221:                }
1222:            }
1223:
1224:            /**
1225:             * Reads and returns primitive data of type float read from the receiver
1226:             * 
1227:             * @return A float saved as primitive data using
1228:             *         <code>ObjectOutputStream.writeFloat()</code>
1229:             * 
1230:             * @throws IOException
1231:             *             If an IO exception happened when reading the primitive data.
1232:             */
1233:            public float readFloat() throws IOException {
1234:                return primitiveTypes.readFloat();
1235:            }
1236:
1237:            /**
1238:             * Reads bytes from the receiver into the byte array <code>buffer</code>.
1239:             * This method will block until <code>buffer.length</code> number of bytes
1240:             * have been read.
1241:             * 
1242:             * @param buffer
1243:             *            the buffer to read bytes into
1244:             * 
1245:             * @throws IOException
1246:             *             if a problem occurs reading from this stream.
1247:             */
1248:            public void readFully(byte[] buffer) throws IOException {
1249:                primitiveTypes.readFully(buffer);
1250:            }
1251:
1252:            /**
1253:             * Reads bytes from the receiver into the byte array <code>buffer</code>.
1254:             * This method will block until <code>length</code> number of bytes have
1255:             * been read.
1256:             * 
1257:             * @param buffer
1258:             *            the byte array in which to store the read bytes.
1259:             * @param offset
1260:             *            the offset in <code>buffer</code> to store the read bytes.
1261:             * @param length
1262:             *            the maximum number of bytes to store in <code>buffer</code>.
1263:             * 
1264:             * @throws IOException
1265:             *             if a problem occurs reading from this stream.
1266:             */
1267:            public void readFully(byte[] buffer, int offset, int length)
1268:                    throws IOException {
1269:                primitiveTypes.readFully(buffer, offset, length);
1270:            }
1271:
1272:            /**
1273:             * Walks the hierarchy of classes described by class descriptor
1274:             * <code>classDesc</code> and reads the field values corresponding to
1275:             * fields declared by the corresponding class descriptor. The instance to
1276:             * store field values into is <code>object</code>. If the class
1277:             * (corresponding to class descriptor <code>classDesc</code>) defines
1278:             * private instance method <code>readObject</code> it will be used to load
1279:             * field values.
1280:             * 
1281:             * @param object
1282:             *            Instance into which stored field values loaded.
1283:             * @param classDesc
1284:             *            A class descriptor (an <code>ObjectStreamClass</code>)
1285:             *            defining which fields should be loaded.
1286:             * 
1287:             * @throws IOException
1288:             *             If an IO exception happened when reading the field values in
1289:             *             the hierarchy.
1290:             * @throws ClassNotFoundException
1291:             *             If a class for one of the field types could not be found
1292:             * @throws NotActiveException
1293:             *             If <code>defaultReadObject</code> is called from the wrong
1294:             *             context.
1295:             * 
1296:             * @see #defaultReadObject
1297:             * @see #readObject()
1298:             */
1299:            private void readHierarchy(Object object,
1300:                    ObjectStreamClass classDesc) throws IOException,
1301:                    ClassNotFoundException, NotActiveException {
1302:                // We can't be called from just anywhere. There are rules.
1303:                if (object == null && mustResolve) {
1304:                    throw new NotActiveException();
1305:                }
1306:
1307:                ArrayList<ObjectStreamClass> streamClassList = new ArrayList<ObjectStreamClass>(
1308:                        32);
1309:                ObjectStreamClass nextStreamClass = classDesc;
1310:                while (nextStreamClass != null) {
1311:                    streamClassList.add(0, nextStreamClass);
1312:                    nextStreamClass = nextStreamClass.getSuperclass();
1313:                }
1314:                if (object == null) {
1315:                    Iterator<ObjectStreamClass> streamIt = streamClassList
1316:                            .iterator();
1317:                    while (streamIt.hasNext()) {
1318:                        ObjectStreamClass streamClass = streamIt.next();
1319:                        readObjectForClass(null, streamClass);
1320:                    }
1321:                } else {
1322:                    ArrayList<Class<?>> classList = new ArrayList<Class<?>>(32);
1323:                    Class<?> nextClass = object.getClass();
1324:                    while (nextClass != null) {
1325:                        Class<?> testClass = nextClass.getSuperclass();
1326:                        if (testClass != null) {
1327:                            classList.add(0, nextClass);
1328:                        }
1329:                        nextClass = testClass;
1330:                    }
1331:                    int lastIndex = 0;
1332:                    for (int i = 0; i < classList.size(); i++) {
1333:                        Class<?> super class = classList.get(i);
1334:                        int index = findStreamSuperclass(super class,
1335:                                streamClassList, lastIndex);
1336:                        if (index == -1) {
1337:                            readObjectNoData(object, super class);
1338:                        } else {
1339:                            for (int j = lastIndex; j <= index; j++) {
1340:                                readObjectForClass(object, streamClassList
1341:                                        .get(j));
1342:                            }
1343:                            lastIndex = index + 1;
1344:                        }
1345:                    }
1346:                }
1347:            }
1348:
1349:            private int findStreamSuperclass(Class<?> cl,
1350:                    ArrayList<ObjectStreamClass> classList, int lastIndex) {
1351:                ObjectStreamClass objCl;
1352:                String forName;
1353:
1354:                for (int i = lastIndex; i < classList.size(); i++) {
1355:                    objCl = classList.get(i);
1356:                    forName = objCl.forClass().getName();
1357:
1358:                    if (objCl.getName().equals(forName)) {
1359:                        if (cl.getName().equals(objCl.getName())) {
1360:                            return i;
1361:                        }
1362:                    } else {
1363:                        // there was a class replacement
1364:                        if (cl.getName().equals(forName)) {
1365:                            return i;
1366:                        }
1367:                    }
1368:                }
1369:                return -1;
1370:            }
1371:
1372:            private void readObjectNoData(Object object, Class<?> cl)
1373:                    throws ObjectStreamException {
1374:                if (!ObjectStreamClass.isSerializable(cl)) {
1375:                    return;
1376:                }
1377:                ObjectStreamClass classDesc = ObjectStreamClass
1378:                        .lookupStreamClass(cl);
1379:                if (classDesc.hasMethodReadObjectNoData()) {
1380:                    final Method readMethod = classDesc
1381:                            .getMethodReadObjectNoData();
1382:                    try {
1383:                        readMethod.invoke(object, new Object[0]);
1384:                    } catch (InvocationTargetException e) {
1385:                        Throwable ex = e.getTargetException();
1386:                        if (ex instanceof  RuntimeException) {
1387:                            throw (RuntimeException) ex;
1388:                        } else if (ex instanceof  Error) {
1389:                            throw (Error) ex;
1390:                        }
1391:                        throw (ObjectStreamException) ex;
1392:                    } catch (IllegalAccessException e) {
1393:                        throw new RuntimeException(e.toString());
1394:                    }
1395:                }
1396:
1397:            }
1398:
1399:            private void readObjectForClass(Object object,
1400:                    ObjectStreamClass classDesc) throws IOException,
1401:                    ClassNotFoundException, NotActiveException {
1402:                // Have to do this before calling defaultReadObject or anything that
1403:                // calls defaultReadObject
1404:                currentObject = object;
1405:                currentClass = classDesc;
1406:
1407:                boolean hadWriteMethod = (classDesc.getFlags() & SC_WRITE_METHOD) > 0;
1408:                Class<?> targetClass = classDesc.forClass();
1409:
1410:                final Method readMethod;
1411:                if (targetClass == null || !mustResolve) {
1412:                    readMethod = null;
1413:                } else {
1414:                    readMethod = classDesc.getMethodReadObject();
1415:                }
1416:                try {
1417:                    if (readMethod != null) {
1418:                        // We have to be able to fetch its value, even if it is private
1419:                        AccessController.doPrivileged(new PriviAction<Object>(
1420:                                readMethod));
1421:                        try {
1422:                            readMethod.invoke(object, new Object[] { this  });
1423:                        } catch (InvocationTargetException e) {
1424:                            Throwable ex = e.getTargetException();
1425:                            if (ex instanceof  ClassNotFoundException) {
1426:                                throw (ClassNotFoundException) ex;
1427:                            } else if (ex instanceof  RuntimeException) {
1428:                                throw (RuntimeException) ex;
1429:                            } else if (ex instanceof  Error) {
1430:                                throw (Error) ex;
1431:                            }
1432:                            throw (IOException) ex;
1433:                        } catch (IllegalAccessException e) {
1434:                            throw new RuntimeException(e.toString());
1435:                        }
1436:                    } else {
1437:                        defaultReadObject();
1438:                    }
1439:                    if (hadWriteMethod) {
1440:                        discardData();
1441:                    }
1442:                } finally {
1443:                    // Cleanup, needs to run always so that we can later detect invalid
1444:                    // calls to defaultReadObject
1445:                    currentObject = null; // We did not set this, so we do not need to
1446:                    // clean it
1447:                    currentClass = null;
1448:                }
1449:            }
1450:
1451:            /**
1452:             * Reads and returns primitive data of type int read from the receiver
1453:             * 
1454:             * @return an int saved as primitive data using
1455:             *         <code>ObjectOutputStream.writeInt()</code>
1456:             * 
1457:             * @throws IOException
1458:             *             If an IO exception happened when reading the primitive data.
1459:             */
1460:            public int readInt() throws IOException {
1461:                return primitiveTypes.readInt();
1462:            }
1463:
1464:            /**
1465:             * Reads and returns the next line (primitive data of type String) read from
1466:             * the receiver
1467:             * 
1468:             * @return a String saved as primitive data using
1469:             *         <code>ObjectOutputStream.writeLine()</code>
1470:             * 
1471:             * @throws IOException
1472:             *             If an IO exception happened when reading the primitive data.
1473:             * 
1474:             * @deprecated Use BufferedReader
1475:             */
1476:            @SuppressWarnings("deprecation")
1477:            @Deprecated
1478:            public String readLine() throws IOException {
1479:                return primitiveTypes.readLine();
1480:            }
1481:
1482:            /**
1483:             * Reads and returns primitive data of type long read from the receiver
1484:             * 
1485:             * @return a long saved as primitive data using
1486:             *         <code>ObjectOutputStream.writeLong()</code>
1487:             * 
1488:             * @throws IOException
1489:             *             If an IO exception happened when reading the primitive data.
1490:             */
1491:            public long readLong() throws IOException {
1492:                return primitiveTypes.readLong();
1493:            }
1494:
1495:            /**
1496:             * Read a new array from the receiver. It is assumed the array has not been
1497:             * read yet (not a cyclic reference). Return the array read.
1498:             * 
1499:             * @param unshared
1500:             *            read the object unshared
1501:             * @return the array read
1502:             * 
1503:             * @throws IOException
1504:             *             If an IO exception happened when reading the array.
1505:             * @throws ClassNotFoundException
1506:             *             If a class for one of the objects could not be found
1507:             * @throws OptionalDataException
1508:             *             If optional data could not be found when reading the array.
1509:             */
1510:            private Object readNewArray(boolean unshared)
1511:                    throws OptionalDataException, ClassNotFoundException,
1512:                    IOException {
1513:                ObjectStreamClass classDesc = readClassDesc();
1514:
1515:                if (classDesc == null) {
1516:                    throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$
1517:                }
1518:
1519:                Integer newHandle = Integer.valueOf(nextHandle());
1520:
1521:                // Array size
1522:                int size = input.readInt();
1523:                Class<?> arrayClass = classDesc.forClass();
1524:                Class<?> componentType = arrayClass.getComponentType();
1525:                Object result = Array.newInstance(componentType, size);
1526:
1527:                registerObjectRead(result, newHandle, unshared);
1528:
1529:                // Now we have code duplication just because Java is typed. We have to
1530:                // read N elements and assign to array positions, but we must typecast
1531:                // the array first, and also call different methods depending on the
1532:                // elements.
1533:                if (componentType.isPrimitive()) {
1534:                    if (componentType == Integer.TYPE) {
1535:                        int[] intArray = (int[]) result;
1536:                        for (int i = 0; i < size; i++) {
1537:                            intArray[i] = input.readInt();
1538:                        }
1539:                    } else if (componentType == Byte.TYPE) {
1540:                        byte[] byteArray = (byte[]) result;
1541:                        input.readFully(byteArray, 0, size);
1542:                    } else if (componentType == Character.TYPE) {
1543:                        char[] charArray = (char[]) result;
1544:                        for (int i = 0; i < size; i++) {
1545:                            charArray[i] = input.readChar();
1546:                        }
1547:                    } else if (componentType == Short.TYPE) {
1548:                        short[] shortArray = (short[]) result;
1549:                        for (int i = 0; i < size; i++) {
1550:                            shortArray[i] = input.readShort();
1551:                        }
1552:                    } else if (componentType == Boolean.TYPE) {
1553:                        boolean[] booleanArray = (boolean[]) result;
1554:                        for (int i = 0; i < size; i++) {
1555:                            booleanArray[i] = input.readBoolean();
1556:                        }
1557:                    } else if (componentType == Long.TYPE) {
1558:                        long[] longArray = (long[]) result;
1559:                        for (int i = 0; i < size; i++) {
1560:                            longArray[i] = input.readLong();
1561:                        }
1562:                    } else if (componentType == Float.TYPE) {
1563:                        float[] floatArray = (float[]) result;
1564:                        for (int i = 0; i < size; i++) {
1565:                            floatArray[i] = input.readFloat();
1566:                        }
1567:                    } else if (componentType == Double.TYPE) {
1568:                        double[] doubleArray = (double[]) result;
1569:                        for (int i = 0; i < size; i++) {
1570:                            doubleArray[i] = input.readDouble();
1571:                        }
1572:                    } else {
1573:                        throw new ClassNotFoundException(Msg.getString(
1574:                                "K00d7", classDesc.getName())); //$NON-NLS-1$
1575:                    }
1576:                } else {
1577:                    // Array of Objects
1578:                    Object[] objectArray = (Object[]) result;
1579:                    for (int i = 0; i < size; i++) {
1580:                        objectArray[i] = readObject();
1581:                    }
1582:                }
1583:                if (enableResolve) {
1584:                    result = resolveObject(result);
1585:                    registerObjectRead(result, newHandle, false);
1586:                }
1587:                return result;
1588:            }
1589:
1590:            /**
1591:             * Reads a new class from the receiver. It is assumed the class has not been
1592:             * read yet (not a cyclic reference). Return the class read.
1593:             * 
1594:             * @param unshared
1595:             *            read the object unshared
1596:             * @return The <code>java.lang.Class</code> read from the stream.
1597:             * 
1598:             * @throws IOException
1599:             *             If an IO exception happened when reading the class.
1600:             * @throws ClassNotFoundException
1601:             *             If a class for one of the objects could not be found
1602:             */
1603:            private Class<?> readNewClass(boolean unshared)
1604:                    throws ClassNotFoundException, IOException {
1605:                ObjectStreamClass classDesc = readClassDesc();
1606:
1607:                if (classDesc != null) {
1608:                    Integer newHandle = Integer.valueOf(nextHandle());
1609:                    Class<?> localClass = classDesc.forClass();
1610:                    if (localClass != null) {
1611:                        registerObjectRead(localClass, newHandle, unshared);
1612:                    }
1613:                    return localClass;
1614:                }
1615:                throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$
1616:            }
1617:
1618:            /*
1619:             * read class type for Enum, note there's difference between enum and normal
1620:             * classes
1621:             */
1622:            private ObjectStreamClass readEnumDesc() throws IOException,
1623:                    ClassNotFoundException {
1624:                byte tc = nextTC();
1625:                switch (tc) {
1626:                case TC_CLASSDESC:
1627:                    return readEnumDescInternal();
1628:                case TC_REFERENCE:
1629:                    return (ObjectStreamClass) readCyclicReference();
1630:                case TC_NULL:
1631:                    return null;
1632:                default:
1633:                    throw new StreamCorruptedException(Msg.getString(
1634:                            "K00d2", Integer.toHexString(tc & 0xff))); //$NON-NLS-1$
1635:                }
1636:            }
1637:
1638:            private ObjectStreamClass readEnumDescInternal()
1639:                    throws IOException, ClassNotFoundException {
1640:                ObjectStreamClass classDesc;
1641:                primitiveData = input;
1642:                Integer oldHandle = descriptorHandle;
1643:                descriptorHandle = Integer.valueOf(nextHandle());
1644:                classDesc = readClassDescriptor();
1645:                registerObjectRead(classDesc, descriptorHandle, false);
1646:                descriptorHandle = oldHandle;
1647:                primitiveData = emptyStream;
1648:                classDesc.setClass(resolveClass(classDesc));
1649:                // Consume unread class annotation data and TC_ENDBLOCKDATA
1650:                discardData();
1651:                ObjectStreamClass super Class = readClassDesc();
1652:                checkedSetSuperClassDesc(classDesc, super Class);
1653:                // Check SUIDs, note all SUID for Enum is 0L
1654:                if (0L != classDesc.getSerialVersionUID()
1655:                        || 0L != super Class.getSerialVersionUID()) {
1656:                    throw new InvalidClassException(super Class.getName(), Msg
1657:                            .getString("K00da", super Class, //$NON-NLS-1$
1658:                                    super Class));
1659:                }
1660:                byte tc = nextTC();
1661:                // discard TC_ENDBLOCKDATA after classDesc if any
1662:                if (tc == TC_ENDBLOCKDATA) {
1663:                    // read next parent class. For enum, it may be null
1664:                    super Class.setSuperclass(readClassDesc());
1665:                } else {
1666:                    // not TC_ENDBLOCKDATA, push back for next read
1667:                    pushbackTC();
1668:                }
1669:                return classDesc;
1670:            }
1671:
1672:            @SuppressWarnings("unchecked")
1673:            // For the Enum.valueOf call
1674:            private Object readEnum(boolean unshared)
1675:                    throws OptionalDataException, ClassNotFoundException,
1676:                    IOException {
1677:                // read classdesc for Enum first
1678:                ObjectStreamClass classDesc = readEnumDesc();
1679:                Integer newHandle = Integer.valueOf(nextHandle());
1680:                // read name after class desc
1681:                String name;
1682:                byte tc = nextTC();
1683:                switch (tc) {
1684:                case TC_REFERENCE:
1685:                    if (unshared) {
1686:                        readNewHandle();
1687:                        throw new InvalidObjectException(Msg.getString("KA002")); //$NON-NLS-1$
1688:                    }
1689:                    name = (String) readCyclicReference();
1690:                    break;
1691:                case TC_STRING:
1692:                    name = (String) readNewString(unshared);
1693:                    break;
1694:                default:
1695:                    throw new StreamCorruptedException(Msg.getString("K00d2"));//$NON-NLS-1$
1696:                }
1697:
1698:                Enum<?> result = Enum.valueOf((Class) classDesc.forClass(),
1699:                        name);
1700:                registerObjectRead(result, newHandle, unshared);
1701:
1702:                return result;
1703:            }
1704:
1705:            /**
1706:             * Reads a new class descriptor from the receiver. It is assumed the class
1707:             * descriptor has not been read yet (not a cyclic reference). Return the
1708:             * class descriptor read.
1709:             * 
1710:             * @param unshared
1711:             *            read the object unshared
1712:             * @return The <code>ObjectStreamClass</code> read from the stream.
1713:             * 
1714:             * @throws IOException
1715:             *             If an IO exception happened when reading the class
1716:             *             descriptor.
1717:             * @throws ClassNotFoundException
1718:             *             If a class for one of the objects could not be found
1719:             */
1720:            private ObjectStreamClass readNewClassDesc(boolean unshared)
1721:                    throws ClassNotFoundException, IOException {
1722:                // So read...() methods can be used by
1723:                // subclasses during readClassDescriptor()
1724:                primitiveData = input;
1725:                Integer oldHandle = descriptorHandle;
1726:                descriptorHandle = Integer.valueOf(nextHandle());
1727:                ObjectStreamClass newClassDesc = readClassDescriptor();
1728:                registerObjectRead(newClassDesc, descriptorHandle, unshared);
1729:                descriptorHandle = oldHandle;
1730:                primitiveData = emptyStream;
1731:
1732:                // We need to map classDesc to class.
1733:                try {
1734:                    newClassDesc.setClass(resolveClass(newClassDesc));
1735:                    // Check SUIDs & base name of the class
1736:                    verifyAndInit(newClassDesc);
1737:                } catch (ClassNotFoundException e) {
1738:                    if (mustResolve) {
1739:                        throw e;
1740:                        // Just continue, the class may not be required
1741:                    }
1742:                }
1743:
1744:                // Resolve the field signatures using the class loader of the
1745:                // resolved class
1746:                ObjectStreamField[] fields = newClassDesc.getLoadFields();
1747:                fields = (null == fields ? new ObjectStreamField[] {} : fields);
1748:                ClassLoader loader = newClassDesc.forClass() == null ? callerClassLoader
1749:                        : newClassDesc.forClass().getClassLoader();
1750:                for (ObjectStreamField element : fields) {
1751:                    element.resolve(loader);
1752:                }
1753:
1754:                // Consume unread class annotation data and TC_ENDBLOCKDATA
1755:                discardData();
1756:                checkedSetSuperClassDesc(newClassDesc, readClassDesc());
1757:                return newClassDesc;
1758:            }
1759:
1760:            /**
1761:             * Reads a new proxy class descriptor from the receiver. It is assumed the
1762:             * proxy class descriptor has not been read yet (not a cyclic reference).
1763:             * Return the proxy class descriptor read.
1764:             * 
1765:             * @return The <code>Class</code> read from the stream.
1766:             * 
1767:             * @throws IOException
1768:             *             If an IO exception happened when reading the class
1769:             *             descriptor.
1770:             * @throws ClassNotFoundException
1771:             *             If a class for one of the objects could not be found
1772:             */
1773:            private Class<?> readNewProxyClassDesc()
1774:                    throws ClassNotFoundException, IOException {
1775:                int count = input.readInt();
1776:                String[] interfaceNames = new String[count];
1777:                for (int i = 0; i < count; i++) {
1778:                    interfaceNames[i] = input.readUTF();
1779:                }
1780:                Class<?> proxy = resolveProxyClass(interfaceNames);
1781:                // Consume unread class annotation data and TC_ENDBLOCKDATA
1782:                discardData();
1783:                return proxy;
1784:            }
1785:
1786:            /**
1787:             * Reads a new class descriptor from the receiver. Return the class
1788:             * descriptor read.
1789:             * 
1790:             * @return The <code>ObjectStreamClass</code> read from the stream.
1791:             * 
1792:             * @throws IOException
1793:             *             If an IO exception happened when reading the class
1794:             *             descriptor.
1795:             * @throws ClassNotFoundException
1796:             *             If a class for one of the objects could not be found
1797:             */
1798:            protected ObjectStreamClass readClassDescriptor()
1799:                    throws IOException, ClassNotFoundException {
1800:
1801:                ObjectStreamClass newClassDesc = new ObjectStreamClass();
1802:                String name = input.readUTF();
1803:                if (name.length() == 0) {
1804:                    // luni.07 = The stream is corrupted
1805:                    throw new IOException(Messages.getString("luni.07")); //$NON-NLS-1$
1806:                }
1807:                newClassDesc.setName(name);
1808:                newClassDesc.setSerialVersionUID(input.readLong());
1809:                newClassDesc.setFlags(input.readByte());
1810:
1811:                /*
1812:                 * We must register the class descriptor before reading field
1813:                 * descriptors. If called outside of readObject, the descriptorHandle
1814:                 * might be null.
1815:                 */
1816:                descriptorHandle = (null == descriptorHandle ? Integer
1817:                        .valueOf(nextHandle()) : descriptorHandle);
1818:                registerObjectRead(newClassDesc, descriptorHandle, false);
1819:
1820:                readFieldDescriptors(newClassDesc);
1821:                return newClassDesc;
1822:            }
1823:
1824:            /**
1825:             * Retrieves the proxy class corresponding to the interface names.
1826:             * 
1827:             * @param interfaceNames
1828:             *            The interfaces used to create the proxy class
1829:             * @return A proxy class
1830:             * 
1831:             * @throws IOException
1832:             *             If any IO problem occurred when trying to load the class.
1833:             * @throws ClassNotFoundException
1834:             *             If the proxy class cannot be created
1835:             */
1836:            protected Class<?> resolveProxyClass(String[] interfaceNames)
1837:                    throws IOException, ClassNotFoundException {
1838:                ClassLoader loader = VM.getNonBootstrapClassLoader();
1839:                Class<?>[] interfaces = new Class<?>[interfaceNames.length];
1840:                for (int i = 0; i < interfaceNames.length; i++) {
1841:                    interfaces[i] = Class.forName(interfaceNames[i], false,
1842:                            loader);
1843:                }
1844:                try {
1845:                    return Proxy.getProxyClass(loader, interfaces);
1846:                } catch (IllegalArgumentException e) {
1847:                    throw new ClassNotFoundException(e.toString(), e);
1848:                }
1849:            }
1850:
1851:            /**
1852:             * Write a new handle describing a cyclic reference from the stream.
1853:             * 
1854:             * @return the handle read
1855:             * 
1856:             * @throws IOException
1857:             *             If an IO exception happened when reading the handle
1858:             */
1859:            private Integer readNewHandle() throws IOException {
1860:                return Integer.valueOf(input.readInt());
1861:            }
1862:
1863:            /**
1864:             * Read a new object from the stream. It is assumed the object has not been
1865:             * loaded yet (not a cyclic reference). Return the object read.
1866:             * 
1867:             * If the object implements <code>Externalizable</code> its
1868:             * <code>readExternal</code> is called. Otherwise, all fields described by
1869:             * the class hierarchy are loaded. Each class can define how its declared
1870:             * instance fields are loaded by defining a private method
1871:             * <code>readObject</code>
1872:             * 
1873:             * @param unshared
1874:             *            read the object unshared
1875:             * @return the object read
1876:             * 
1877:             * @throws IOException
1878:             *             If an IO exception happened when reading the object.
1879:             * @throws OptionalDataException
1880:             *             If optional data could not be found when reading the object
1881:             *             graph
1882:             * @throws ClassNotFoundException
1883:             *             If a class for one of the objects could not be found
1884:             */
1885:            private Object readNewObject(boolean unshared)
1886:                    throws OptionalDataException, ClassNotFoundException,
1887:                    IOException {
1888:                ObjectStreamClass classDesc = readClassDesc();
1889:
1890:                if (classDesc == null) {
1891:                    throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$
1892:                }
1893:
1894:                Integer newHandle = Integer.valueOf(nextHandle());
1895:
1896:                // Note that these values come from the Stream, and in fact it could be
1897:                // that the classes have been changed so that the info below now
1898:                // conflicts with the newer class
1899:                boolean wasExternalizable = (classDesc.getFlags() & SC_EXTERNALIZABLE) > 0;
1900:                boolean wasSerializable = (classDesc.getFlags() & SC_SERIALIZABLE) > 0;
1901:
1902:                // Maybe we should cache the values above in classDesc ? It may be the
1903:                // case that when reading classDesc we may need to read more stuff
1904:                // depending on the values above
1905:                Class<?> objectClass = classDesc.forClass();
1906:
1907:                Object result, registeredResult = null;
1908:                if (objectClass != null) {
1909:                    // The class of the instance may not be the same as the class of the
1910:                    // constructor to run
1911:                    // This is the constructor to run if Externalizable
1912:                    Class<?> constructorClass = objectClass;
1913:
1914:                    // WARNING - What if the object is serializable and externalizable ?
1915:                    // Is that possible ?
1916:                    if (wasSerializable) {
1917:                        // Now we must run the constructor of the class just above the
1918:                        // one that implements Serializable so that slots that were not
1919:                        // dumped can be initialized properly
1920:                        while (constructorClass != null
1921:                                && ObjectStreamClass
1922:                                        .isSerializable(constructorClass)) {
1923:                            constructorClass = constructorClass.getSuperclass();
1924:                        }
1925:                    }
1926:
1927:                    // Fetch the empty constructor, or null if none.
1928:                    Constructor<?> constructor = null;
1929:                    if (constructorClass != null) {
1930:                        try {
1931:                            constructor = constructorClass
1932:                                    .getDeclaredConstructor(ObjectStreamClass.EMPTY_CONSTRUCTOR_PARAM_TYPES);
1933:                        } catch (NoSuchMethodException nsmEx) {
1934:                            // Ignored
1935:                        }
1936:                    }
1937:
1938:                    // Has to have an empty constructor
1939:                    if (constructor == null) {
1940:                        throw new InvalidClassException(constructorClass
1941:                                .getName(), Msg.getString("K00dc")); //$NON-NLS-1$
1942:                    }
1943:
1944:                    int constructorModifiers = constructor.getModifiers();
1945:
1946:                    // Now we must check if the empty constructor is visible to the
1947:                    // instantiation class
1948:                    if (Modifier.isPrivate(constructorModifiers)
1949:                            || (wasExternalizable && !Modifier
1950:                                    .isPublic(constructorModifiers))) {
1951:                        throw new InvalidClassException(constructorClass
1952:                                .getName(), Msg.getString("K00dc")); //$NON-NLS-1$
1953:                    }
1954:
1955:                    // We know we are testing from a subclass, so the only other case
1956:                    // where the visibility is not allowed is when the constructor has
1957:                    // default visibility and the instantiation class is in a different
1958:                    // package than the constructor class
1959:                    if (!Modifier.isPublic(constructorModifiers)
1960:                            && !Modifier.isProtected(constructorModifiers)) {
1961:                        // Not public, not private and not protected...means default
1962:                        // visibility. Check if same package
1963:                        if (!inSamePackage(constructorClass, objectClass)) {
1964:                            throw new InvalidClassException(constructorClass
1965:                                    .getName(), Msg.getString("K00dc")); //$NON-NLS-1$
1966:                        }
1967:                    }
1968:
1969:                    // Now we know which class to instantiate and which constructor to
1970:                    // run. We are allowed to run the constructor.
1971:                    result = newInstance(objectClass, constructorClass);
1972:                    registerObjectRead(result, newHandle, unshared);
1973:
1974:                    registeredResult = result;
1975:                } else {
1976:                    result = null;
1977:                }
1978:
1979:                try {
1980:                    // This is how we know what to do in defaultReadObject. And it is
1981:                    // also used by defaultReadObject to check if it was called from an
1982:                    // invalid place. It also allows readExternal to call
1983:                    // defaultReadObject and have it work.
1984:                    currentObject = result;
1985:                    currentClass = classDesc;
1986:
1987:                    // If Externalizable, just let the object read itself
1988:                    if (wasExternalizable) {
1989:                        boolean blockData = (classDesc.getFlags() & SC_BLOCK_DATA) > 0;
1990:                        if (!blockData) {
1991:                            primitiveData = input;
1992:                        }
1993:                        if (mustResolve) {
1994:                            Externalizable extern = (Externalizable) result;
1995:                            extern.readExternal(this );
1996:                        }
1997:                        if (blockData) {
1998:                            // Similar to readHierarchy. Anything not read by
1999:                            // readExternal has to be consumed here
2000:                            discardData();
2001:                        } else {
2002:                            primitiveData = emptyStream;
2003:                        }
2004:                    } else {
2005:                        // If we got here, it is Serializable but not Externalizable.
2006:                        // Walk the hierarchy reading each class' slots
2007:                        readHierarchy(result, classDesc);
2008:                    }
2009:                } finally {
2010:                    // Cleanup, needs to run always so that we can later detect invalid
2011:                    // calls to defaultReadObject
2012:                    currentObject = null;
2013:                    currentClass = null;
2014:                }
2015:
2016:                if (objectClass != null) {
2017:
2018:                    ObjectStreamClass desc = ObjectStreamClass
2019:                            .lookupStreamClass(objectClass);
2020:                    if (desc.hasMethodReadResolve()) {
2021:                        Method methodReadResolve = desc.getMethodReadResolve();
2022:                        try {
2023:                            result = methodReadResolve.invoke(result,
2024:                                    (Object[]) null);
2025:                        } catch (IllegalAccessException iae) {
2026:                        } catch (InvocationTargetException ite) {
2027:                            Throwable target = ite.getTargetException();
2028:                            if (target instanceof  ObjectStreamException) {
2029:                                throw (ObjectStreamException) target;
2030:                            } else if (target instanceof  Error) {
2031:                                throw (Error) target;
2032:                            } else {
2033:                                throw (RuntimeException) target;
2034:                            }
2035:                        }
2036:
2037:                    }
2038:                }
2039:                // We get here either if class-based replacement was not needed or if it
2040:                // was needed but produced the same object or if it could not be
2041:                // computed.
2042:
2043:                // The object to return is the one we instantiated or a replacement for
2044:                // it
2045:                if (result != null && enableResolve) {
2046:                    result = resolveObject(result);
2047:                }
2048:                if (registeredResult != result) {
2049:                    registerObjectRead(result, newHandle, unshared);
2050:                }
2051:                return result;
2052:            }
2053:
2054:            /**
2055:             * Read a new String in UTF format from the receiver. Return the string
2056:             * read.
2057:             * 
2058:             * @param unshared
2059:             *            read the object unshared
2060:             * @return the string just read.
2061:             * 
2062:             * @throws IOException
2063:             *             If an IO exception happened when reading the String.
2064:             */
2065:            private Object readNewString(boolean unshared) throws IOException {
2066:                Object result = input.readUTF();
2067:                if (enableResolve) {
2068:                    result = resolveObject(result);
2069:                }
2070:                int newHandle = nextHandle();
2071:                registerObjectRead(result, Integer.valueOf(newHandle), unshared);
2072:
2073:                return result;
2074:            }
2075:
2076:            /**
2077:             * Read a new String in UTF format from the receiver. Return the string
2078:             * read.
2079:             * 
2080:             * @param unshared
2081:             *            read the object unshared
2082:             * @return the string just read.
2083:             * 
2084:             * @throws IOException
2085:             *             If an IO exception happened when reading the String.
2086:             */
2087:            private Object readNewLongString(boolean unshared)
2088:                    throws IOException {
2089:                long length = input.readLong();
2090:                Object result = input.decodeUTF((int) length);
2091:                if (enableResolve) {
2092:                    result = resolveObject(result);
2093:                }
2094:                int newHandle = nextHandle();
2095:                registerObjectRead(result, Integer.valueOf(newHandle), unshared);
2096:
2097:                return result;
2098:            }
2099:
2100:            /**
2101:             * Read the next object from the receiver's underlying stream.
2102:             * 
2103:             * @return the new object read.
2104:             * 
2105:             * @throws IOException
2106:             *             If an IO exception happened when reading the object
2107:             * @throws ClassNotFoundException
2108:             *             If the class of one of the objects in the object graph could
2109:             *             not be found
2110:             * @throws OptionalDataException
2111:             *             If primitive data types were found instead of an object.
2112:             * 
2113:             * @see ObjectOutputStream#writeObject(Object)
2114:             */
2115:            public final Object readObject() throws OptionalDataException,
2116:                    ClassNotFoundException, IOException {
2117:                return readObject(false);
2118:            }
2119:
2120:            /**
2121:             * Read the next unshared object from the receiver's underlying stream.
2122:             * 
2123:             * @return the new object read.
2124:             * 
2125:             * @throws IOException
2126:             *             If an IO exception happened when reading the object
2127:             * @throws ClassNotFoundException
2128:             *             If the class of one of the objects in the object graph could
2129:             *             not be found
2130:             * 
2131:             * @see ObjectOutputStream#writeUnshared
2132:             */
2133:            public Object readUnshared() throws IOException,
2134:                    ClassNotFoundException {
2135:                return readObject(true);
2136:            }
2137:
2138:            private Object readObject(boolean unshared)
2139:                    throws OptionalDataException, ClassNotFoundException,
2140:                    IOException {
2141:                boolean restoreInput = (primitiveData == input);
2142:                if (restoreInput) {
2143:                    primitiveData = emptyStream;
2144:                }
2145:
2146:                // This is the spec'ed behavior in JDK 1.2. Very bizarre way to allow
2147:                // behavior overriding.
2148:                if (subclassOverridingImplementation && !unshared) {
2149:                    return readObjectOverride();
2150:                }
2151:
2152:                // If we still had primitive types to read, should we discard them
2153:                // (reset the primitiveTypes stream) or leave as is, so that attempts to
2154:                // read primitive types won't read 'past data' ???
2155:                Object result;
2156:                try {
2157:                    // We need this so we can tell when we are returning to the
2158:                    // original/outside caller
2159:                    if (++nestedLevels == 1) {
2160:                        // Remember the caller's class loader
2161:                        callerClassLoader = VM.getNonBootstrapClassLoader();
2162:                    }
2163:
2164:                    result = readNonPrimitiveContent(unshared);
2165:                    if (restoreInput) {
2166:                        primitiveData = input;
2167:                    }
2168:                } finally {
2169:                    // We need this so we can tell when we are returning to the
2170:                    // original/outside caller
2171:                    if (--nestedLevels == 0) {
2172:                        // We are going to return to the original caller, perform
2173:                        // cleanups.
2174:                        // No more need to remember the caller's class loader
2175:                        callerClassLoader = null;
2176:                    }
2177:                }
2178:
2179:                // Done reading this object. Is it time to return to the original
2180:                // caller? If so we need to perform validations first.
2181:                if (nestedLevels == 0 && validations != null) {
2182:                    // We are going to return to the original caller. If validation is
2183:                    // enabled we need to run them now and then cleanup the validation
2184:                    // collection
2185:                    try {
2186:                        for (InputValidationDesc element : validations) {
2187:                            element.validator.validateObject();
2188:                        }
2189:                    } finally {
2190:                        // Validations have to be renewed, since they are only called
2191:                        // from readObject
2192:                        validations = null;
2193:                    }
2194:                }
2195:                return result;
2196:            }
2197:
2198:            /**
2199:             * Method to be overriden by subclasses to read the next object from the
2200:             * receiver's underlying stream.
2201:             * 
2202:             * @return the new object read.
2203:             * 
2204:             * @throws IOException
2205:             *             If an IO exception happened when reading the object
2206:             * @throws ClassNotFoundException
2207:             *             If the class of one of the objects in the object graph could
2208:             *             not be found
2209:             * @throws OptionalDataException
2210:             *             If primitive data types were found instead of an object.
2211:             * 
2212:             * @see ObjectOutputStream#writeObjectOverride
2213:             */
2214:            protected Object readObjectOverride() throws OptionalDataException,
2215:                    ClassNotFoundException, IOException {
2216:                if (input == null) {
2217:                    return null;
2218:                }
2219:                // Subclasses must override.
2220:                throw new IOException();
2221:            }
2222:
2223:            /**
2224:             * Reads and returns primitive data of type short from the receiver
2225:             * 
2226:             * @return a short saved as primitive data using
2227:             *         <code>ObjectOutputStream.writeShort()</code>
2228:             * 
2229:             * @throws IOException
2230:             *             If an IO exception happened when reading the primitive data.
2231:             */
2232:            public short readShort() throws IOException {
2233:                return primitiveTypes.readShort();
2234:            }
2235:
2236:            /**
2237:             * Reads and validates the ObjectInputStream header from the receiver
2238:             * 
2239:             * @throws IOException
2240:             *             If an IO exception happened when reading the stream header.
2241:             * @throws StreamCorruptedException
2242:             *             If the underlying stream does not contain serialized objects
2243:             *             that can be read.
2244:             */
2245:            protected void readStreamHeader() throws IOException,
2246:                    StreamCorruptedException {
2247:                if (input.readShort() == STREAM_MAGIC
2248:                        && input.readShort() == STREAM_VERSION) {
2249:                    return;
2250:                }
2251:                throw new StreamCorruptedException();
2252:            }
2253:
2254:            /**
2255:             * Reads and returns primitive data of type byte (unsigned) from the
2256:             * receiver
2257:             * 
2258:             * @return a byte saved as primitive data using
2259:             *         <code>ObjectOutputStream.writeUnsignedByte()</code>
2260:             * 
2261:             * @throws IOException
2262:             *             If an IO exception happened when reading the primitive data.
2263:             */
2264:            public int readUnsignedByte() throws IOException {
2265:                return primitiveTypes.readUnsignedByte();
2266:            }
2267:
2268:            /**
2269:             * Reads and returns primitive data of type short (unsigned) from the
2270:             * receiver
2271:             * 
2272:             * @return a short saved as primitive data using
2273:             *         <code>ObjectOutputStream.writeUnsignedShort()</code>
2274:             * 
2275:             * @throws IOException
2276:             *             If an IO exception happened when reading the primitive data.
2277:             */
2278:            public int readUnsignedShort() throws IOException {
2279:                return primitiveTypes.readUnsignedShort();
2280:            }
2281:
2282:            /**
2283:             * Reads and returns primitive data of type String read in UTF format from
2284:             * the receiver
2285:             * 
2286:             * @return a String saved as primitive data using
2287:             *         <code>ObjectOutputStream.writeUTF()</code>
2288:             * 
2289:             * @throws IOException
2290:             *             If an IO exception happened when reading the primitive data.
2291:             */
2292:            public String readUTF() throws IOException {
2293:                return primitiveTypes.readUTF();
2294:            }
2295:
2296:            /**
2297:             * Return the object previously read tagged with handle <code>handle</code>.
2298:             * 
2299:             * @param handle
2300:             *            The handle that this object was assigned when it was read.
2301:             * @return the object previously read.
2302:             * 
2303:             * @throws InvalidObjectException
2304:             *             If there is no previously read object with this handle
2305:             */
2306:            private Object registeredObjectRead(Integer handle)
2307:                    throws InvalidObjectException {
2308:                Object res = objectsRead.get(handle);
2309:
2310:                if (res == UNSHARED_OBJ) {
2311:                    throw new InvalidObjectException(Msg.getString("KA010")); //$NON-NLS-1$
2312:                }
2313:
2314:                return res;
2315:            }
2316:
2317:            /**
2318:             * Assume object <code>obj</code> has been read, and assign a handle to
2319:             * it, <code>handle</code>.
2320:             * 
2321:             * @param obj
2322:             *            Non-null object being loaded.
2323:             * @param handle
2324:             *            An Integer, the handle to this object
2325:             * @param unshared
2326:             *            Boolean, indicates that caller is reading in unshared mode
2327:             * 
2328:             * @see #nextHandle
2329:             */
2330:            private void registerObjectRead(Object obj, Integer handle,
2331:                    boolean unshared) {
2332:                objectsRead.put(handle, unshared ? UNSHARED_OBJ : obj);
2333:            }
2334:
2335:            /**
2336:             * Register object validator <code>object</code> to be executed to perform
2337:             * validation of objects loaded from the receiver. Validations will be run
2338:             * in order of decreasing priority, defined by <code>priority</code>.
2339:             * 
2340:             * @param object
2341:             *            An ObjectInputValidation to validate objects loaded.
2342:             * @param priority
2343:             *            validator priority
2344:             * 
2345:             * @throws NotActiveException
2346:             *             If this method is not called from <code>readObject()</code>
2347:             * @throws InvalidObjectException
2348:             *             If <code>object</code> is null.
2349:             */
2350:            public synchronized void registerValidation(
2351:                    ObjectInputValidation object, int priority)
2352:                    throws NotActiveException, InvalidObjectException {
2353:                // Validation can only be registered when inside readObject calls
2354:                Object instanceBeingRead = this .currentObject;
2355:
2356:                // We can't be called from just anywhere. There are rules.
2357:                if (instanceBeingRead == null && nestedLevels == 0) {
2358:                    throw new NotActiveException();
2359:                }
2360:                if (object == null) {
2361:                    throw new InvalidObjectException(Msg.getString("K00d9")); //$NON-NLS-1$
2362:                }
2363:                // From now on it is just insertion in a SortedCollection. Since
2364:                // the Java class libraries don't provide that, we have to
2365:                // implement it from scratch here.
2366:                InputValidationDesc desc = new InputValidationDesc();
2367:                desc.validator = object;
2368:                desc.priority = priority;
2369:                // No need for this, validateObject does not take a parameter
2370:                // desc.toValidate = instanceBeingRead;
2371:                if (validations == null) {
2372:                    validations = new InputValidationDesc[1];
2373:                    validations[0] = desc;
2374:                } else {
2375:                    int i = 0;
2376:                    for (; i < validations.length; i++) {
2377:                        InputValidationDesc validation = validations[i];
2378:                        // Sorted, higher priority first.
2379:                        if (priority >= validation.priority) {
2380:                            break; // Found the index where to insert
2381:                        }
2382:                    }
2383:                    InputValidationDesc[] oldValidations = validations;
2384:                    int currentSize = oldValidations.length;
2385:                    validations = new InputValidationDesc[currentSize + 1];
2386:                    System.arraycopy(oldValidations, 0, validations, 0, i);
2387:                    System.arraycopy(oldValidations, i, validations, i + 1,
2388:                            currentSize - i);
2389:                    validations[i] = desc;
2390:                }
2391:            }
2392:
2393:            /**
2394:             * Reset the collection of objects already loaded by the receiver.
2395:             */
2396:            private void resetSeenObjects() {
2397:                objectsRead = new Hashtable<Integer, Object>();
2398:                currentHandle = baseWireHandle;
2399:                primitiveData = emptyStream;
2400:            }
2401:
2402:            /**
2403:             * Reset the receiver. The collection of objects already read by the
2404:             * receiver is reset, and internal structures are also reset so that the
2405:             * receiver knows it is in a fresh clean state.
2406:             */
2407:            private void resetState() {
2408:                resetSeenObjects();
2409:                hasPushbackTC = false;
2410:                pushbackTC = 0;
2411:                // nestedLevels = 0;
2412:            }
2413:
2414:            /**
2415:             * Loads the Java class corresponding to the class descriptor
2416:             * <code>osClass</code>(ObjectStreamClass) just read from the receiver.
2417:             * 
2418:             * @param osClass
2419:             *            An ObjectStreamClass read from the receiver.
2420:             * @return a Class corresponding to the descriptor loaded.
2421:             * 
2422:             * @throws IOException
2423:             *             If any IO problem occurred when trying to load the class.
2424:             * @throws ClassNotFoundException
2425:             *             If the corresponding class cannot be found.
2426:             */
2427:            protected Class<?> resolveClass(ObjectStreamClass osClass)
2428:                    throws IOException, ClassNotFoundException {
2429:                String className = osClass.getName();
2430:                // if it is primitive class, for example, long.class
2431:                Class<?> cls = PRIMITIVE_CLASSES.get(className);
2432:                if (null == cls) {
2433:                    // not primitive class
2434:                    // Use the first non-null ClassLoader on the stack. If null, use the
2435:                    // system class loader
2436:                    return Class.forName(className, true, callerClassLoader);
2437:                }
2438:                return cls;
2439:            }
2440:
2441:            /**
2442:             * If <code>enableResolveObject()</code> was activated, computes the
2443:             * replacement object for the original object <code>object</code> and
2444:             * returns the replacement. Otherwise returns <code>object</code>.
2445:             * 
2446:             * @param object
2447:             *            Original object for which a replacement may be defined
2448:             * @return a possibly new, replacement object for <code>object</code>
2449:             * 
2450:             * @throws IOException
2451:             *             If any IO problem occurred when trying to resolve the object.
2452:             * 
2453:             * @see #enableResolveObject
2454:             * @see ObjectOutputStream#enableReplaceObject
2455:             * @see ObjectOutputStream#replaceObject
2456:             */
2457:            protected Object resolveObject(Object object) throws IOException {
2458:                // By default no object replacement. Subclasses can override
2459:                return object;
2460:            }
2461:
2462:            /**
2463:             * Set a given declared field named <code>fieldName</code> of
2464:             * <code>instance</code> to the new <code>byte</code> value
2465:             * <code>value</code>.
2466:             * 
2467:             * This method could be implemented non-natively on top of java.lang.reflect
2468:             * implementations that support the <code>setAccessible</code> API, at the
2469:             * expense of extra object creation (java.lang.reflect.Field). Otherwise
2470:             * Serialization could not set private fields, except by the use of a native
2471:             * method like this one.
2472:             * 
2473:             * @param instance
2474:             *            Object whose field to set
2475:             * @param declaringClass
2476:             *            <code>instance</code>'s declaring class
2477:             * @param fieldName
2478:             *            Name of the field to set
2479:             * @param value
2480:             *            New value for the field
2481:             * 
2482:             * @throws NoSuchFieldError
2483:             *             If the field does not exist.
2484:             */
2485:            private static native void setField(Object instance,
2486:                    Class<?> declaringClass, String fieldName, byte value)
2487:                    throws NoSuchFieldError;
2488:
2489:            /**
2490:             * Set a given declared field named <code>fieldName</code> of
2491:             * <code>instance</code> to the new <code>char</code> value
2492:             * <code>value</code>.
2493:             * 
2494:             * This method could be implemented non-natively on top of java.lang.reflect
2495:             * implementations that support the <code>setAccessible</code> API, at the
2496:             * expense of extra object creation (java.lang.reflect.Field). Otherwise
2497:             * Serialization could not set private fields, except by the use of a native
2498:             * method like this one.
2499:             * 
2500:             * @param instance
2501:             *            Object whose field to set
2502:             * @param declaringClass
2503:             *            <code>instance</code>'s declaring class
2504:             * @param fieldName
2505:             *            Name of the field to set
2506:             * @param value
2507:             *            New value for the field
2508:             * 
2509:             * @throws NoSuchFieldError
2510:             *             If the field does not exist.
2511:             */
2512:            private static native void setField(Object instance,
2513:                    Class<?> declaringClass, String fieldName, char value)
2514:                    throws NoSuchFieldError;
2515:
2516:            /**
2517:             * Set a given declared field named <code>fieldName</code> of
2518:             * <code>instance</code> to the new <code>double</code> value
2519:             * <code>value</code>.
2520:             * 
2521:             * This method could be implemented non-natively on top of java.lang.reflect
2522:             * implementations that support the <code>setAccessible</code> API, at the
2523:             * expense of extra object creation (java.lang.reflect.Field). Otherwise
2524:             * Serialization could not set private fields, except by the use of a native
2525:             * method like this one.
2526:             * 
2527:             * @param instance
2528:             *            Object whose field to set
2529:             * @param declaringClass
2530:             *            <code>instance</code>'s declaring class
2531:             * @param fieldName
2532:             *            Name of the field to set
2533:             * @param value
2534:             *            New value for the field
2535:             * 
2536:             * @throws NoSuchFieldError
2537:             *             If the field does not exist.
2538:             */
2539:            private static native void setField(Object instance,
2540:                    Class<?> declaringClass, String fieldName, double value)
2541:                    throws NoSuchFieldError;
2542:
2543:            /**
2544:             * Set a given declared field named <code>fieldName</code> of
2545:             * <code>instance</code> to the new <code>float</code> value
2546:             * <code>value</code>.
2547:             * 
2548:             * This method could be implemented non-natively on top of java.lang.reflect
2549:             * implementations that support the <code>setAccessible</code> API, at the
2550:             * expense of extra object creation (java.lang.reflect.Field). Otherwise
2551:             * Serialization could not set private fields, except by the use of a native
2552:             * method like this one.
2553:             * 
2554:             * @param instance
2555:             *            Object whose field to set
2556:             * @param declaringClass
2557:             *            <code>instance</code>'s declaring class
2558:             * @param fieldName
2559:             *            Name of the field to set
2560:             * @param value
2561:             *            New value for the field
2562:             * 
2563:             * @throws NoSuchFieldError
2564:             *             If the field does not exist.
2565:             */
2566:            private static native void setField(Object instance,
2567:                    Class<?> declaringClass, String fieldName, float value)
2568:                    throws NoSuchFieldError;
2569:
2570:            /**
2571:             * Set a given declared field named <code>fieldName</code> of
2572:             * <code>instance</code> to the new <code>int</code> value
2573:             * <code>value</code>.
2574:             * 
2575:             * This method could be implemented non-natively on top of java.lang.reflect
2576:             * implementations that support the <code>setAccessible</code> API, at the
2577:             * expense of extra object creation (java.lang.reflect.Field). Otherwise
2578:             * Serialization could not set private fields, except by the use of a native
2579:             * method like this one.
2580:             * 
2581:             * @param instance
2582:             *            Object whose field to set
2583:             * @param declaringClass
2584:             *            <code>instance</code>'s declaring class
2585:             * @param fieldName
2586:             *            Name of the field to set
2587:             * @param value
2588:             *            New value for the field
2589:             * 
2590:             * @throws NoSuchFieldError
2591:             *             If the field does not exist.
2592:             */
2593:            private static native void setField(Object instance,
2594:                    Class<?> declaringClass, String fieldName, int value)
2595:                    throws NoSuchFieldError;
2596:
2597:            /**
2598:             * Set a given declared field named <code>fieldName</code> of
2599:             * <code>instance</code> to the new <code>long</code> value
2600:             * <code>value</code>.
2601:             * 
2602:             * This method could be implemented non-natively on top of java.lang.reflect
2603:             * implementations that support the <code>setAccessible</code> API, at the
2604:             * expense of extra object creation (java.lang.reflect.Field). Otherwise
2605:             * Serialization could not set private fields, except by the use of a native
2606:             * method like this one.
2607:             * 
2608:             * @param instance
2609:             *            Object whose field to set
2610:             * @param declaringClass
2611:             *            <code>instance</code>'s declaring class
2612:             * @param fieldName
2613:             *            Name of the field to set
2614:             * @param value
2615:             *            New value for the field
2616:             * 
2617:             * @throws NoSuchFieldError
2618:             *             If the field does not exist.
2619:             */
2620:            private static native void setField(Object instance,
2621:                    Class<?> declaringClass, String fieldName, long value)
2622:                    throws NoSuchFieldError;
2623:
2624:            /**
2625:             * Set a given declared field named <code>fieldName</code> of
2626:             * <code>instance</code> to the new value <code>value</code>.
2627:             * 
2628:             * This method could be implemented non-natively on top of java.lang.reflect
2629:             * implementations that support the <code>setAccessible</code> API, at the
2630:             * expense of extra object creation (java.lang.reflect.Field). Otherwise
2631:             * Serialization could not set private fields, except by the use of a native
2632:             * method like this one.
2633:             * 
2634:             * @param instance
2635:             *            Object whose field to set
2636:             * @param declaringClass
2637:             *            Class which declares the field
2638:             * @param fieldName
2639:             *            Name of the field to set
2640:             * @param fieldTypeName
2641:             *            Name of the class defining the type of the field
2642:             * @param value
2643:             *            New value for the field
2644:             * 
2645:             * @throws NoSuchFieldError
2646:             *             If the field does not exist.
2647:             */
2648:            private static native void objSetField(Object instance,
2649:                    Class<?> declaringClass, String fieldName,
2650:                    String fieldTypeName, Object value) throws NoSuchFieldError;
2651:
2652:            /**
2653:             * Set a given declared field named <code>fieldName</code> of
2654:             * <code>instance</code> to the new <code>short</code> value
2655:             * <code>value</code>.
2656:             * 
2657:             * This method could be implemented non-natively on top of java.lang.reflect
2658:             * implementations that support the <code>setAccessible</code> API, at the
2659:             * expense of extra object creation (java.lang.reflect.Field). Otherwise
2660:             * Serialization could not set private fields, except by the use of a native
2661:             * method like this one.
2662:             * 
2663:             * @param instance
2664:             *            Object whose field to set
2665:             * @param declaringClass
2666:             *            <code>instance</code>'s declaring class
2667:             * @param fieldName
2668:             *            Name of the field to set
2669:             * @param value
2670:             *            New value for the field
2671:             * 
2672:             * @throws NoSuchFieldError
2673:             *             If the field does not exist.
2674:             */
2675:            private static native void setField(Object instance,
2676:                    Class<?> declaringClass, String fieldName, short value)
2677:                    throws NoSuchFieldError;
2678:
2679:            /**
2680:             * Set a given declared field named <code>fieldName</code> of
2681:             * <code>instance</code> to the new <code>boolean</code> value
2682:             * <code>value</code>.
2683:             * 
2684:             * This method could be implemented non-natively on top of java.lang.reflect
2685:             * implementations that support the <code>setAccessible</code> API, at the
2686:             * expense of extra object creation (java.lang.reflect.Field). Otherwise
2687:             * Serialization could not set private fields, except by the use of a native
2688:             * method like this one.
2689:             * 
2690:             * @param instance
2691:             *            Object whose field to set
2692:             * @param declaringClass
2693:             *            <code>instance</code>'s declaring class
2694:             * @param fieldName
2695:             *            Name of the field to set
2696:             * @param value
2697:             *            New value for the field
2698:             * 
2699:             * @throws NoSuchFieldError
2700:             *             If the field does not exist.
2701:             */
2702:            private static native void setField(Object instance,
2703:                    Class<?> declaringClass, String fieldName, boolean value)
2704:                    throws NoSuchFieldError;
2705:
2706:            /**
2707:             * Skips <code>length</code> bytes of primitive data from the receiver. It
2708:             * should not be used to skip bytes at any arbitrary position; just when
2709:             * reading primitive data types (ints, chars, etc).
2710:             * 
2711:             * 
2712:             * @param length
2713:             *            How many bytes to skip
2714:             * @return number of bytes skipped
2715:             * 
2716:             * @throws IOException
2717:             *             If any IO problem occurred when trying to skip the bytes.
2718:             */
2719:            public int skipBytes(int length) throws IOException {
2720:                // To be used with available. Ok to call if reading primitive buffer
2721:                if (input == null) {
2722:                    throw new NullPointerException();
2723:                }
2724:
2725:                int offset = 0;
2726:                while (offset < length) {
2727:                    checkReadPrimitiveTypes();
2728:                    long skipped = primitiveData.skip(length - offset);
2729:                    if (skipped == 0) {
2730:                        return offset;
2731:                    }
2732:                    offset += (int) skipped;
2733:                }
2734:                return length;
2735:            }
2736:
2737:            /**
2738:             * Verify if the SUID & the base name for descriptor 
2739:             * <code>loadedStreamClass</code>matches
2740:             * the SUID & the base name of the corresponding loaded class and
2741:             * init private fields.
2742:             * 
2743:             * @param loadedStreamClass
2744:             *            An ObjectStreamClass that was loaded from the stream.
2745:             * 
2746:             * @throws InvalidClassException
2747:             *             If the SUID of the stream class does not match the VM class
2748:             */
2749:            private void verifyAndInit(ObjectStreamClass loadedStreamClass)
2750:                    throws InvalidClassException {
2751:
2752:                Class<?> localClass = loadedStreamClass.forClass();
2753:                ObjectStreamClass localStreamClass = ObjectStreamClass
2754:                        .lookupStreamClass(localClass);
2755:
2756:                if (loadedStreamClass.getSerialVersionUID() != localStreamClass
2757:                        .getSerialVersionUID()) {
2758:                    throw new InvalidClassException(
2759:                            loadedStreamClass.getName(), Msg.getString(
2760:                                    "K00da", loadedStreamClass, //$NON-NLS-1$
2761:                                    localStreamClass));
2762:                }
2763:
2764:                String loadedClassBaseName = getBaseName(loadedStreamClass
2765:                        .getName());
2766:                String localClassBaseName = getBaseName(localStreamClass
2767:                        .getName());
2768:
2769:                if (!loadedClassBaseName.equals(localClassBaseName)) {
2770:                    throw new InvalidClassException(
2771:                            loadedStreamClass.getName(), Msg.getString(
2772:                                    "KA015", loadedClassBaseName, //$NON-NLS-1$
2773:                                    localClassBaseName));
2774:                }
2775:
2776:                loadedStreamClass.initPrivateFields(localStreamClass);
2777:            }
2778:
2779:            private static String getBaseName(String fullName) {
2780:                int k = fullName.lastIndexOf("."); //$NON-NLS-1$
2781:
2782:                if (k == -1 || k == (fullName.length() - 1)) {
2783:                    return fullName;
2784:                }
2785:                return fullName.substring(k + 1);
2786:            }
2787:
2788:            // Avoid recursive defining.
2789:            private static void checkedSetSuperClassDesc(
2790:                    ObjectStreamClass desc, ObjectStreamClass super Desc)
2791:                    throws StreamCorruptedException {
2792:                if (desc.equals(super Desc)) {
2793:                    throw new StreamCorruptedException();
2794:                }
2795:                desc.setSuperclass(superDesc);
2796:            }
2797:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.