1.1 --- a/emul/compact/src/main/java/java/io/ObjectStreamClass.java Mon Feb 25 19:00:08 2013 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,1396 +0,0 @@
1.4 -/*
1.5 - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 - *
1.8 - * This code is free software; you can redistribute it and/or modify it
1.9 - * under the terms of the GNU General Public License version 2 only, as
1.10 - * published by the Free Software Foundation. Oracle designates this
1.11 - * particular file as subject to the "Classpath" exception as provided
1.12 - * by Oracle in the LICENSE file that accompanied this code.
1.13 - *
1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 - * version 2 for more details (a copy is included in the LICENSE file that
1.18 - * accompanied this code).
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License version
1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 - *
1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 - * or visit www.oracle.com if you need additional information or have any
1.26 - * questions.
1.27 - */
1.28 -
1.29 -package java.io;
1.30 -
1.31 -import java.lang.ref.Reference;
1.32 -import java.lang.ref.ReferenceQueue;
1.33 -import java.lang.ref.SoftReference;
1.34 -import java.lang.ref.WeakReference;
1.35 -import java.lang.reflect.Constructor;
1.36 -import java.lang.reflect.Field;
1.37 -import java.lang.reflect.InvocationTargetException;
1.38 -import java.lang.reflect.Member;
1.39 -import java.lang.reflect.Method;
1.40 -import java.lang.reflect.Modifier;
1.41 -import java.lang.reflect.Proxy;
1.42 -import java.util.ArrayList;
1.43 -import java.util.Arrays;
1.44 -import java.util.Collections;
1.45 -import java.util.Comparator;
1.46 -import java.util.HashSet;
1.47 -import java.util.Set;
1.48 -
1.49 -/**
1.50 - * Serialization's descriptor for classes. It contains the name and
1.51 - * serialVersionUID of the class. The ObjectStreamClass for a specific class
1.52 - * loaded in this Java VM can be found/created using the lookup method.
1.53 - *
1.54 - * <p>The algorithm to compute the SerialVersionUID is described in
1.55 - * <a href="../../../platform/serialization/spec/class.html#4100">Object
1.56 - * Serialization Specification, Section 4.6, Stream Unique Identifiers</a>.
1.57 - *
1.58 - * @author Mike Warres
1.59 - * @author Roger Riggs
1.60 - * @see ObjectStreamField
1.61 - * @see <a href="../../../platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a>
1.62 - * @since JDK1.1
1.63 - */
1.64 -public class ObjectStreamClass implements Serializable {
1.65 -
1.66 - /** serialPersistentFields value indicating no serializable fields */
1.67 - public static final ObjectStreamField[] NO_FIELDS =
1.68 - new ObjectStreamField[0];
1.69 -
1.70 - private static final long serialVersionUID = -6120832682080437368L;
1.71 - private static final ObjectStreamField[] serialPersistentFields =
1.72 - NO_FIELDS;
1.73 -
1.74 -
1.75 - /** class associated with this descriptor (if any) */
1.76 - private Class<?> cl;
1.77 - /** name of class represented by this descriptor */
1.78 - private String name;
1.79 - /** serialVersionUID of represented class (null if not computed yet) */
1.80 - private volatile Long suid;
1.81 -
1.82 - /** true if represents dynamic proxy class */
1.83 - private boolean isProxy;
1.84 - /** true if represents enum type */
1.85 - private boolean isEnum;
1.86 - /** true if represented class implements Serializable */
1.87 - private boolean serializable;
1.88 - /** true if represented class implements Externalizable */
1.89 - private boolean externalizable;
1.90 - /** true if desc has data written by class-defined writeObject method */
1.91 - private boolean hasWriteObjectData;
1.92 - /**
1.93 - * true if desc has externalizable data written in block data format; this
1.94 - * must be true by default to accommodate ObjectInputStream subclasses which
1.95 - * override readClassDescriptor() to return class descriptors obtained from
1.96 - * ObjectStreamClass.lookup() (see 4461737)
1.97 - */
1.98 - private boolean hasBlockExternalData = true;
1.99 -
1.100 - /** exception (if any) thrown while attempting to resolve class */
1.101 - private ClassNotFoundException resolveEx;
1.102 - /** exception (if any) to throw if non-enum deserialization attempted */
1.103 - private InvalidClassException deserializeEx;
1.104 - /** exception (if any) to throw if non-enum serialization attempted */
1.105 - private InvalidClassException serializeEx;
1.106 - /** exception (if any) to throw if default serialization attempted */
1.107 - private InvalidClassException defaultSerializeEx;
1.108 -
1.109 - /** serializable fields */
1.110 - private ObjectStreamField[] fields;
1.111 - /** aggregate marshalled size of primitive fields */
1.112 - private int primDataSize;
1.113 - /** number of non-primitive fields */
1.114 - private int numObjFields;
1.115 - /** reflector for setting/getting serializable field values */
1.116 -// private FieldReflector fieldRefl;
1.117 - /** data layout of serialized objects described by this class desc */
1.118 - private volatile ClassDataSlot[] dataLayout;
1.119 -
1.120 - /** serialization-appropriate constructor, or null if none */
1.121 - private Constructor cons;
1.122 - /** class-defined writeObject method, or null if none */
1.123 - private Method writeObjectMethod;
1.124 - /** class-defined readObject method, or null if none */
1.125 - private Method readObjectMethod;
1.126 - /** class-defined readObjectNoData method, or null if none */
1.127 - private Method readObjectNoDataMethod;
1.128 - /** class-defined writeReplace method, or null if none */
1.129 - private Method writeReplaceMethod;
1.130 - /** class-defined readResolve method, or null if none */
1.131 - private Method readResolveMethod;
1.132 -
1.133 - /** local class descriptor for represented class (may point to self) */
1.134 - private ObjectStreamClass localDesc;
1.135 - /** superclass descriptor appearing in stream */
1.136 - private ObjectStreamClass superDesc;
1.137 -
1.138 - /**
1.139 - * Initializes native code.
1.140 - */
1.141 - private static native void initNative();
1.142 - static {
1.143 - initNative();
1.144 - }
1.145 -
1.146 - /**
1.147 - * Find the descriptor for a class that can be serialized. Creates an
1.148 - * ObjectStreamClass instance if one does not exist yet for class. Null is
1.149 - * returned if the specified class does not implement java.io.Serializable
1.150 - * or java.io.Externalizable.
1.151 - *
1.152 - * @param cl class for which to get the descriptor
1.153 - * @return the class descriptor for the specified class
1.154 - */
1.155 - public static ObjectStreamClass lookup(Class<?> cl) {
1.156 - return lookup(cl, false);
1.157 - }
1.158 -
1.159 - /**
1.160 - * Returns the descriptor for any class, regardless of whether it
1.161 - * implements {@link Serializable}.
1.162 - *
1.163 - * @param cl class for which to get the descriptor
1.164 - * @return the class descriptor for the specified class
1.165 - * @since 1.6
1.166 - */
1.167 - public static ObjectStreamClass lookupAny(Class<?> cl) {
1.168 - return lookup(cl, true);
1.169 - }
1.170 -
1.171 - /**
1.172 - * Returns the name of the class described by this descriptor.
1.173 - * This method returns the name of the class in the format that
1.174 - * is used by the {@link Class#getName} method.
1.175 - *
1.176 - * @return a string representing the name of the class
1.177 - */
1.178 - public String getName() {
1.179 - return name;
1.180 - }
1.181 -
1.182 - /**
1.183 - * Return the serialVersionUID for this class. The serialVersionUID
1.184 - * defines a set of classes all with the same name that have evolved from a
1.185 - * common root class and agree to be serialized and deserialized using a
1.186 - * common format. NonSerializable classes have a serialVersionUID of 0L.
1.187 - *
1.188 - * @return the SUID of the class described by this descriptor
1.189 - */
1.190 - public long getSerialVersionUID() {
1.191 - // REMIND: synchronize instead of relying on volatile?
1.192 - if (suid == null) {
1.193 - return computeDefaultSUID(cl);
1.194 - }
1.195 - return suid.longValue();
1.196 - }
1.197 -
1.198 - /**
1.199 - * Return the class in the local VM that this version is mapped to. Null
1.200 - * is returned if there is no corresponding local class.
1.201 - *
1.202 - * @return the <code>Class</code> instance that this descriptor represents
1.203 - */
1.204 - public Class<?> forClass() {
1.205 - return cl;
1.206 - }
1.207 -
1.208 - /**
1.209 - * Return an array of the fields of this serializable class.
1.210 - *
1.211 - * @return an array containing an element for each persistent field of
1.212 - * this class. Returns an array of length zero if there are no
1.213 - * fields.
1.214 - * @since 1.2
1.215 - */
1.216 - public ObjectStreamField[] getFields() {
1.217 - return getFields(true);
1.218 - }
1.219 -
1.220 - /**
1.221 - * Get the field of this class by name.
1.222 - *
1.223 - * @param name the name of the data field to look for
1.224 - * @return The ObjectStreamField object of the named field or null if
1.225 - * there is no such named field.
1.226 - */
1.227 - public ObjectStreamField getField(String name) {
1.228 - return getField(name, null);
1.229 - }
1.230 -
1.231 - /**
1.232 - * Return a string describing this ObjectStreamClass.
1.233 - */
1.234 - public String toString() {
1.235 - return name + ": static final long serialVersionUID = " +
1.236 - getSerialVersionUID() + "L;";
1.237 - }
1.238 -
1.239 - /**
1.240 - * Looks up and returns class descriptor for given class, or null if class
1.241 - * is non-serializable and "all" is set to false.
1.242 - *
1.243 - * @param cl class to look up
1.244 - * @param all if true, return descriptors for all classes; if false, only
1.245 - * return descriptors for serializable classes
1.246 - */
1.247 - static ObjectStreamClass lookup(Class<?> cl, boolean all) {
1.248 - if (!(all || Serializable.class.isAssignableFrom(cl))) {
1.249 - return null;
1.250 - }
1.251 - Object entry = null;
1.252 - EntryFuture future = null;
1.253 - if (entry == null) {
1.254 - EntryFuture newEntry = new EntryFuture();
1.255 - Reference<?> newRef = new SoftReference<>(newEntry);
1.256 - if (entry == null) {
1.257 - future = newEntry;
1.258 - }
1.259 - }
1.260 -
1.261 - if (entry instanceof ObjectStreamClass) { // check common case first
1.262 - return (ObjectStreamClass) entry;
1.263 - }
1.264 - if (entry instanceof EntryFuture) {
1.265 - future = (EntryFuture) entry;
1.266 - if (true) {
1.267 - /*
1.268 - * Handle nested call situation described by 4803747: waiting
1.269 - * for future value to be set by a lookup() call further up the
1.270 - * stack will result in deadlock, so calculate and set the
1.271 - * future value here instead.
1.272 - */
1.273 - entry = null;
1.274 - } else {
1.275 - entry = future.get();
1.276 - }
1.277 - }
1.278 - if (entry == null) {
1.279 - try {
1.280 - entry = new ObjectStreamClass(cl);
1.281 - } catch (Throwable th) {
1.282 - entry = th;
1.283 - }
1.284 - // nested lookup call already set future
1.285 - entry = future.get();
1.286 - }
1.287 -
1.288 - if (entry instanceof ObjectStreamClass) {
1.289 - return (ObjectStreamClass) entry;
1.290 - } else if (entry instanceof RuntimeException) {
1.291 - throw (RuntimeException) entry;
1.292 - } else if (entry instanceof Error) {
1.293 - throw (Error) entry;
1.294 - } else {
1.295 - throw new InternalError("unexpected entry: " + entry);
1.296 - }
1.297 - }
1.298 -
1.299 - /**
1.300 - * Placeholder used in class descriptor and field reflector lookup tables
1.301 - * for an entry in the process of being initialized. (Internal) callers
1.302 - * which receive an EntryFuture belonging to another thread as the result
1.303 - * of a lookup should call the get() method of the EntryFuture; this will
1.304 - * return the actual entry once it is ready for use and has been set(). To
1.305 - * conserve objects, EntryFutures synchronize on themselves.
1.306 - */
1.307 - private static class EntryFuture {
1.308 -
1.309 - private static final Object unset = new Object();
1.310 - private Object entry = unset;
1.311 -
1.312 - /**
1.313 - * Attempts to set the value contained by this EntryFuture. If the
1.314 - * EntryFuture's value has not been set already, then the value is
1.315 - * saved, any callers blocked in the get() method are notified, and
1.316 - * true is returned. If the value has already been set, then no saving
1.317 - * or notification occurs, and false is returned.
1.318 - */
1.319 - synchronized boolean set(Object entry) {
1.320 - if (this.entry != unset) {
1.321 - return false;
1.322 - }
1.323 - this.entry = entry;
1.324 - notifyAll();
1.325 - return true;
1.326 - }
1.327 -
1.328 - /**
1.329 - * Returns the value contained by this EntryFuture, blocking if
1.330 - * necessary until a value is set.
1.331 - */
1.332 - synchronized Object get() {
1.333 - boolean interrupted = false;
1.334 - while (entry == unset) {
1.335 - try {
1.336 - wait();
1.337 - } catch (InterruptedException ex) {
1.338 - interrupted = true;
1.339 - }
1.340 - }
1.341 - return entry;
1.342 - }
1.343 - }
1.344 -
1.345 - /**
1.346 - * Creates local class descriptor representing given class.
1.347 - */
1.348 - private ObjectStreamClass(final Class<?> cl) {
1.349 - this.cl = cl;
1.350 - name = cl.getName();
1.351 - isProxy = Proxy.isProxyClass(cl);
1.352 - isEnum = Enum.class.isAssignableFrom(cl);
1.353 - serializable = Serializable.class.isAssignableFrom(cl);
1.354 - externalizable = Externalizable.class.isAssignableFrom(cl);
1.355 -
1.356 - Class<?> superCl = cl.getSuperclass();
1.357 - superDesc = (superCl != null) ? lookup(superCl, false) : null;
1.358 - localDesc = this;
1.359 -
1.360 - suid = Long.valueOf(0);
1.361 - fields = NO_FIELDS;
1.362 -
1.363 -
1.364 - if (deserializeEx == null) {
1.365 - if (isEnum) {
1.366 - deserializeEx = new InvalidClassException(name, "enum type");
1.367 - } else if (cons == null) {
1.368 - deserializeEx = new InvalidClassException(
1.369 - name, "no valid constructor");
1.370 - }
1.371 - }
1.372 - for (int i = 0; i < fields.length; i++) {
1.373 - if (fields[i].getField() == null) {
1.374 - defaultSerializeEx = new InvalidClassException(
1.375 - name, "unmatched serializable field(s) declared");
1.376 - }
1.377 - }
1.378 - }
1.379 -
1.380 - /**
1.381 - * Creates blank class descriptor which should be initialized via a
1.382 - * subsequent call to initProxy(), initNonProxy() or readNonProxy().
1.383 - */
1.384 - ObjectStreamClass() {
1.385 - }
1.386 -
1.387 - /**
1.388 - * Initializes class descriptor representing a proxy class.
1.389 - */
1.390 - void initProxy(Class<?> cl,
1.391 - ClassNotFoundException resolveEx,
1.392 - ObjectStreamClass superDesc)
1.393 - throws InvalidClassException
1.394 - {
1.395 - this.cl = cl;
1.396 - this.resolveEx = resolveEx;
1.397 - this.superDesc = superDesc;
1.398 - isProxy = true;
1.399 - serializable = true;
1.400 - suid = Long.valueOf(0);
1.401 - fields = NO_FIELDS;
1.402 -
1.403 - if (cl != null) {
1.404 - localDesc = lookup(cl, true);
1.405 - if (!localDesc.isProxy) {
1.406 - throw new InvalidClassException(
1.407 - "cannot bind proxy descriptor to a non-proxy class");
1.408 - }
1.409 - name = localDesc.name;
1.410 - externalizable = localDesc.externalizable;
1.411 - cons = localDesc.cons;
1.412 - writeReplaceMethod = localDesc.writeReplaceMethod;
1.413 - readResolveMethod = localDesc.readResolveMethod;
1.414 - deserializeEx = localDesc.deserializeEx;
1.415 - }
1.416 - }
1.417 -
1.418 - /**
1.419 - * Initializes class descriptor representing a non-proxy class.
1.420 - */
1.421 - void initNonProxy(ObjectStreamClass model,
1.422 - Class<?> cl,
1.423 - ClassNotFoundException resolveEx,
1.424 - ObjectStreamClass superDesc)
1.425 - throws InvalidClassException
1.426 - {
1.427 - this.cl = cl;
1.428 - this.resolveEx = resolveEx;
1.429 - this.superDesc = superDesc;
1.430 - name = model.name;
1.431 - suid = Long.valueOf(model.getSerialVersionUID());
1.432 - isProxy = false;
1.433 - isEnum = model.isEnum;
1.434 - serializable = model.serializable;
1.435 - externalizable = model.externalizable;
1.436 - hasBlockExternalData = model.hasBlockExternalData;
1.437 - hasWriteObjectData = model.hasWriteObjectData;
1.438 - fields = model.fields;
1.439 - primDataSize = model.primDataSize;
1.440 - numObjFields = model.numObjFields;
1.441 -
1.442 - if (cl != null) {
1.443 - localDesc = lookup(cl, true);
1.444 - if (localDesc.isProxy) {
1.445 - throw new InvalidClassException(
1.446 - "cannot bind non-proxy descriptor to a proxy class");
1.447 - }
1.448 - if (isEnum != localDesc.isEnum) {
1.449 - throw new InvalidClassException(isEnum ?
1.450 - "cannot bind enum descriptor to a non-enum class" :
1.451 - "cannot bind non-enum descriptor to an enum class");
1.452 - }
1.453 -
1.454 - if (serializable == localDesc.serializable &&
1.455 - !cl.isArray() &&
1.456 - suid.longValue() != localDesc.getSerialVersionUID())
1.457 - {
1.458 - throw new InvalidClassException(localDesc.name,
1.459 - "local class incompatible: " +
1.460 - "stream classdesc serialVersionUID = " + suid +
1.461 - ", local class serialVersionUID = " +
1.462 - localDesc.getSerialVersionUID());
1.463 - }
1.464 -
1.465 - if (!classNamesEqual(name, localDesc.name)) {
1.466 - throw new InvalidClassException(localDesc.name,
1.467 - "local class name incompatible with stream class " +
1.468 - "name \"" + name + "\"");
1.469 - }
1.470 -
1.471 - if (!isEnum) {
1.472 - if ((serializable == localDesc.serializable) &&
1.473 - (externalizable != localDesc.externalizable))
1.474 - {
1.475 - throw new InvalidClassException(localDesc.name,
1.476 - "Serializable incompatible with Externalizable");
1.477 - }
1.478 -
1.479 - if ((serializable != localDesc.serializable) ||
1.480 - (externalizable != localDesc.externalizable) ||
1.481 - !(serializable || externalizable))
1.482 - {
1.483 - deserializeEx = new InvalidClassException(localDesc.name,
1.484 - "class invalid for deserialization");
1.485 - }
1.486 - }
1.487 -
1.488 - cons = localDesc.cons;
1.489 - writeObjectMethod = localDesc.writeObjectMethod;
1.490 - readObjectMethod = localDesc.readObjectMethod;
1.491 - readObjectNoDataMethod = localDesc.readObjectNoDataMethod;
1.492 - writeReplaceMethod = localDesc.writeReplaceMethod;
1.493 - readResolveMethod = localDesc.readResolveMethod;
1.494 - if (deserializeEx == null) {
1.495 - deserializeEx = localDesc.deserializeEx;
1.496 - }
1.497 - }
1.498 - // reassign to matched fields so as to reflect local unshared settings
1.499 - fields = null;
1.500 - }
1.501 -
1.502 - /**
1.503 - * Reads non-proxy class descriptor information from given input stream.
1.504 - * The resulting class descriptor is not fully functional; it can only be
1.505 - * used as input to the ObjectInputStream.resolveClass() and
1.506 - * ObjectStreamClass.initNonProxy() methods.
1.507 - */
1.508 - void readNonProxy(ObjectInputStream in)
1.509 - throws IOException, ClassNotFoundException
1.510 - {
1.511 - name = in.readUTF();
1.512 - suid = Long.valueOf(in.readLong());
1.513 - isProxy = false;
1.514 -
1.515 - byte flags = in.readByte();
1.516 - hasWriteObjectData =
1.517 - ((flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0);
1.518 - hasBlockExternalData =
1.519 - ((flags & ObjectStreamConstants.SC_BLOCK_DATA) != 0);
1.520 - externalizable =
1.521 - ((flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0);
1.522 - boolean sflag =
1.523 - ((flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0);
1.524 - if (externalizable && sflag) {
1.525 - throw new InvalidClassException(
1.526 - name, "serializable and externalizable flags conflict");
1.527 - }
1.528 - serializable = externalizable || sflag;
1.529 - isEnum = ((flags & ObjectStreamConstants.SC_ENUM) != 0);
1.530 - if (isEnum && suid.longValue() != 0L) {
1.531 - throw new InvalidClassException(name,
1.532 - "enum descriptor has non-zero serialVersionUID: " + suid);
1.533 - }
1.534 -
1.535 - int numFields = in.readShort();
1.536 - if (isEnum && numFields != 0) {
1.537 - throw new InvalidClassException(name,
1.538 - "enum descriptor has non-zero field count: " + numFields);
1.539 - }
1.540 - fields = (numFields > 0) ?
1.541 - new ObjectStreamField[numFields] : NO_FIELDS;
1.542 - for (int i = 0; i < numFields; i++) {
1.543 - char tcode = (char) in.readByte();
1.544 - String fname = in.readUTF();
1.545 - String signature = ((tcode == 'L') || (tcode == '[')) ?
1.546 - in.readTypeString() : new String(new char[] { tcode });
1.547 - try {
1.548 - fields[i] = new ObjectStreamField(fname, signature, false);
1.549 - } catch (RuntimeException e) {
1.550 - throw (IOException) new InvalidClassException(name,
1.551 - "invalid descriptor for field " + fname).initCause(e);
1.552 - }
1.553 - }
1.554 - computeFieldOffsets();
1.555 - }
1.556 -
1.557 - /**
1.558 - * Writes non-proxy class descriptor information to given output stream.
1.559 - */
1.560 - void writeNonProxy(ObjectOutputStream out) throws IOException {
1.561 - out.writeUTF(name);
1.562 - out.writeLong(getSerialVersionUID());
1.563 -
1.564 - byte flags = 0;
1.565 - if (externalizable) {
1.566 - flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
1.567 - int protocol = out.getProtocolVersion();
1.568 - if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {
1.569 - flags |= ObjectStreamConstants.SC_BLOCK_DATA;
1.570 - }
1.571 - } else if (serializable) {
1.572 - flags |= ObjectStreamConstants.SC_SERIALIZABLE;
1.573 - }
1.574 - if (hasWriteObjectData) {
1.575 - flags |= ObjectStreamConstants.SC_WRITE_METHOD;
1.576 - }
1.577 - if (isEnum) {
1.578 - flags |= ObjectStreamConstants.SC_ENUM;
1.579 - }
1.580 - out.writeByte(flags);
1.581 -
1.582 - out.writeShort(fields.length);
1.583 - for (int i = 0; i < fields.length; i++) {
1.584 - ObjectStreamField f = fields[i];
1.585 - out.writeByte(f.getTypeCode());
1.586 - out.writeUTF(f.getName());
1.587 - if (!f.isPrimitive()) {
1.588 - out.writeTypeString(f.getTypeString());
1.589 - }
1.590 - }
1.591 - }
1.592 -
1.593 - /**
1.594 - * Returns ClassNotFoundException (if any) thrown while attempting to
1.595 - * resolve local class corresponding to this class descriptor.
1.596 - */
1.597 - ClassNotFoundException getResolveException() {
1.598 - return resolveEx;
1.599 - }
1.600 -
1.601 - /**
1.602 - * Throws an InvalidClassException if object instances referencing this
1.603 - * class descriptor should not be allowed to deserialize. This method does
1.604 - * not apply to deserialization of enum constants.
1.605 - */
1.606 - void checkDeserialize() throws InvalidClassException {
1.607 - if (deserializeEx != null) {
1.608 - InvalidClassException ice =
1.609 - new InvalidClassException(deserializeEx.classname,
1.610 - deserializeEx.getMessage());
1.611 - ice.initCause(deserializeEx);
1.612 - throw ice;
1.613 - }
1.614 - }
1.615 -
1.616 - /**
1.617 - * Throws an InvalidClassException if objects whose class is represented by
1.618 - * this descriptor should not be allowed to serialize. This method does
1.619 - * not apply to serialization of enum constants.
1.620 - */
1.621 - void checkSerialize() throws InvalidClassException {
1.622 - if (serializeEx != null) {
1.623 - InvalidClassException ice =
1.624 - new InvalidClassException(serializeEx.classname,
1.625 - serializeEx.getMessage());
1.626 - ice.initCause(serializeEx);
1.627 - throw ice;
1.628 - }
1.629 - }
1.630 -
1.631 - /**
1.632 - * Throws an InvalidClassException if objects whose class is represented by
1.633 - * this descriptor should not be permitted to use default serialization
1.634 - * (e.g., if the class declares serializable fields that do not correspond
1.635 - * to actual fields, and hence must use the GetField API). This method
1.636 - * does not apply to deserialization of enum constants.
1.637 - */
1.638 - void checkDefaultSerialize() throws InvalidClassException {
1.639 - if (defaultSerializeEx != null) {
1.640 - InvalidClassException ice =
1.641 - new InvalidClassException(defaultSerializeEx.classname,
1.642 - defaultSerializeEx.getMessage());
1.643 - ice.initCause(defaultSerializeEx);
1.644 - throw ice;
1.645 - }
1.646 - }
1.647 -
1.648 - /**
1.649 - * Returns superclass descriptor. Note that on the receiving side, the
1.650 - * superclass descriptor may be bound to a class that is not a superclass
1.651 - * of the subclass descriptor's bound class.
1.652 - */
1.653 - ObjectStreamClass getSuperDesc() {
1.654 - return superDesc;
1.655 - }
1.656 -
1.657 - /**
1.658 - * Returns the "local" class descriptor for the class associated with this
1.659 - * class descriptor (i.e., the result of
1.660 - * ObjectStreamClass.lookup(this.forClass())) or null if there is no class
1.661 - * associated with this descriptor.
1.662 - */
1.663 - ObjectStreamClass getLocalDesc() {
1.664 - return localDesc;
1.665 - }
1.666 -
1.667 - /**
1.668 - * Returns arrays of ObjectStreamFields representing the serializable
1.669 - * fields of the represented class. If copy is true, a clone of this class
1.670 - * descriptor's field array is returned, otherwise the array itself is
1.671 - * returned.
1.672 - */
1.673 - ObjectStreamField[] getFields(boolean copy) {
1.674 - return copy ? fields.clone() : fields;
1.675 - }
1.676 -
1.677 - /**
1.678 - * Looks up a serializable field of the represented class by name and type.
1.679 - * A specified type of null matches all types, Object.class matches all
1.680 - * non-primitive types, and any other non-null type matches assignable
1.681 - * types only. Returns matching field, or null if no match found.
1.682 - */
1.683 - ObjectStreamField getField(String name, Class<?> type) {
1.684 - for (int i = 0; i < fields.length; i++) {
1.685 - ObjectStreamField f = fields[i];
1.686 - if (f.getName().equals(name)) {
1.687 - if (type == null ||
1.688 - (type == Object.class && !f.isPrimitive()))
1.689 - {
1.690 - return f;
1.691 - }
1.692 - Class<?> ftype = f.getType();
1.693 - if (ftype != null && type.isAssignableFrom(ftype)) {
1.694 - return f;
1.695 - }
1.696 - }
1.697 - }
1.698 - return null;
1.699 - }
1.700 -
1.701 - /**
1.702 - * Returns true if class descriptor represents a dynamic proxy class, false
1.703 - * otherwise.
1.704 - */
1.705 - boolean isProxy() {
1.706 - return isProxy;
1.707 - }
1.708 -
1.709 - /**
1.710 - * Returns true if class descriptor represents an enum type, false
1.711 - * otherwise.
1.712 - */
1.713 - boolean isEnum() {
1.714 - return isEnum;
1.715 - }
1.716 -
1.717 - /**
1.718 - * Returns true if represented class implements Externalizable, false
1.719 - * otherwise.
1.720 - */
1.721 - boolean isExternalizable() {
1.722 - return externalizable;
1.723 - }
1.724 -
1.725 - /**
1.726 - * Returns true if represented class implements Serializable, false
1.727 - * otherwise.
1.728 - */
1.729 - boolean isSerializable() {
1.730 - return serializable;
1.731 - }
1.732 -
1.733 - /**
1.734 - * Returns true if class descriptor represents externalizable class that
1.735 - * has written its data in 1.2 (block data) format, false otherwise.
1.736 - */
1.737 - boolean hasBlockExternalData() {
1.738 - return hasBlockExternalData;
1.739 - }
1.740 -
1.741 - /**
1.742 - * Returns true if class descriptor represents serializable (but not
1.743 - * externalizable) class which has written its data via a custom
1.744 - * writeObject() method, false otherwise.
1.745 - */
1.746 - boolean hasWriteObjectData() {
1.747 - return hasWriteObjectData;
1.748 - }
1.749 -
1.750 - /**
1.751 - * Returns true if represented class is serializable/externalizable and can
1.752 - * be instantiated by the serialization runtime--i.e., if it is
1.753 - * externalizable and defines a public no-arg constructor, or if it is
1.754 - * non-externalizable and its first non-serializable superclass defines an
1.755 - * accessible no-arg constructor. Otherwise, returns false.
1.756 - */
1.757 - boolean isInstantiable() {
1.758 - return (cons != null);
1.759 - }
1.760 -
1.761 - /**
1.762 - * Returns true if represented class is serializable (but not
1.763 - * externalizable) and defines a conformant writeObject method. Otherwise,
1.764 - * returns false.
1.765 - */
1.766 - boolean hasWriteObjectMethod() {
1.767 - return (writeObjectMethod != null);
1.768 - }
1.769 -
1.770 - /**
1.771 - * Returns true if represented class is serializable (but not
1.772 - * externalizable) and defines a conformant readObject method. Otherwise,
1.773 - * returns false.
1.774 - */
1.775 - boolean hasReadObjectMethod() {
1.776 - return (readObjectMethod != null);
1.777 - }
1.778 -
1.779 - /**
1.780 - * Returns true if represented class is serializable (but not
1.781 - * externalizable) and defines a conformant readObjectNoData method.
1.782 - * Otherwise, returns false.
1.783 - */
1.784 - boolean hasReadObjectNoDataMethod() {
1.785 - return (readObjectNoDataMethod != null);
1.786 - }
1.787 -
1.788 - /**
1.789 - * Returns true if represented class is serializable or externalizable and
1.790 - * defines a conformant writeReplace method. Otherwise, returns false.
1.791 - */
1.792 - boolean hasWriteReplaceMethod() {
1.793 - return (writeReplaceMethod != null);
1.794 - }
1.795 -
1.796 - /**
1.797 - * Returns true if represented class is serializable or externalizable and
1.798 - * defines a conformant readResolve method. Otherwise, returns false.
1.799 - */
1.800 - boolean hasReadResolveMethod() {
1.801 - return (readResolveMethod != null);
1.802 - }
1.803 -
1.804 - /**
1.805 - * Creates a new instance of the represented class. If the class is
1.806 - * externalizable, invokes its public no-arg constructor; otherwise, if the
1.807 - * class is serializable, invokes the no-arg constructor of the first
1.808 - * non-serializable superclass. Throws UnsupportedOperationException if
1.809 - * this class descriptor is not associated with a class, if the associated
1.810 - * class is non-serializable or if the appropriate no-arg constructor is
1.811 - * inaccessible/unavailable.
1.812 - */
1.813 - Object newInstance()
1.814 - throws InstantiationException, InvocationTargetException,
1.815 - UnsupportedOperationException
1.816 - {
1.817 - if (cons != null) {
1.818 - try {
1.819 - return cons.newInstance();
1.820 - } catch (IllegalAccessException ex) {
1.821 - // should not occur, as access checks have been suppressed
1.822 - throw new InternalError();
1.823 - }
1.824 - } else {
1.825 - throw new UnsupportedOperationException();
1.826 - }
1.827 - }
1.828 -
1.829 - /**
1.830 - * Invokes the writeObject method of the represented serializable class.
1.831 - * Throws UnsupportedOperationException if this class descriptor is not
1.832 - * associated with a class, or if the class is externalizable,
1.833 - * non-serializable or does not define writeObject.
1.834 - */
1.835 - void invokeWriteObject(Object obj, ObjectOutputStream out)
1.836 - throws IOException, UnsupportedOperationException
1.837 - {
1.838 - if (writeObjectMethod != null) {
1.839 - try {
1.840 - writeObjectMethod.invoke(obj, new Object[]{ out });
1.841 - } catch (InvocationTargetException ex) {
1.842 - Throwable th = ex.getTargetException();
1.843 - if (th instanceof IOException) {
1.844 - throw (IOException) th;
1.845 - } else {
1.846 - throwMiscException(th);
1.847 - }
1.848 - } catch (IllegalAccessException ex) {
1.849 - // should not occur, as access checks have been suppressed
1.850 - throw new InternalError();
1.851 - }
1.852 - } else {
1.853 - throw new UnsupportedOperationException();
1.854 - }
1.855 - }
1.856 -
1.857 - /**
1.858 - * Invokes the readObject method of the represented serializable class.
1.859 - * Throws UnsupportedOperationException if this class descriptor is not
1.860 - * associated with a class, or if the class is externalizable,
1.861 - * non-serializable or does not define readObject.
1.862 - */
1.863 - void invokeReadObject(Object obj, ObjectInputStream in)
1.864 - throws ClassNotFoundException, IOException,
1.865 - UnsupportedOperationException
1.866 - {
1.867 - if (readObjectMethod != null) {
1.868 - try {
1.869 - readObjectMethod.invoke(obj, new Object[]{ in });
1.870 - } catch (InvocationTargetException ex) {
1.871 - Throwable th = ex.getTargetException();
1.872 - if (th instanceof ClassNotFoundException) {
1.873 - throw (ClassNotFoundException) th;
1.874 - } else if (th instanceof IOException) {
1.875 - throw (IOException) th;
1.876 - } else {
1.877 - throwMiscException(th);
1.878 - }
1.879 - } catch (IllegalAccessException ex) {
1.880 - // should not occur, as access checks have been suppressed
1.881 - throw new InternalError();
1.882 - }
1.883 - } else {
1.884 - throw new UnsupportedOperationException();
1.885 - }
1.886 - }
1.887 -
1.888 - /**
1.889 - * Invokes the readObjectNoData method of the represented serializable
1.890 - * class. Throws UnsupportedOperationException if this class descriptor is
1.891 - * not associated with a class, or if the class is externalizable,
1.892 - * non-serializable or does not define readObjectNoData.
1.893 - */
1.894 - void invokeReadObjectNoData(Object obj)
1.895 - throws IOException, UnsupportedOperationException
1.896 - {
1.897 - if (readObjectNoDataMethod != null) {
1.898 - try {
1.899 - readObjectNoDataMethod.invoke(obj, (Object[]) null);
1.900 - } catch (InvocationTargetException ex) {
1.901 - Throwable th = ex.getTargetException();
1.902 - if (th instanceof ObjectStreamException) {
1.903 - throw (ObjectStreamException) th;
1.904 - } else {
1.905 - throwMiscException(th);
1.906 - }
1.907 - } catch (IllegalAccessException ex) {
1.908 - // should not occur, as access checks have been suppressed
1.909 - throw new InternalError();
1.910 - }
1.911 - } else {
1.912 - throw new UnsupportedOperationException();
1.913 - }
1.914 - }
1.915 -
1.916 - /**
1.917 - * Invokes the writeReplace method of the represented serializable class and
1.918 - * returns the result. Throws UnsupportedOperationException if this class
1.919 - * descriptor is not associated with a class, or if the class is
1.920 - * non-serializable or does not define writeReplace.
1.921 - */
1.922 - Object invokeWriteReplace(Object obj)
1.923 - throws IOException, UnsupportedOperationException
1.924 - {
1.925 - if (writeReplaceMethod != null) {
1.926 - try {
1.927 - return writeReplaceMethod.invoke(obj, (Object[]) null);
1.928 - } catch (InvocationTargetException ex) {
1.929 - Throwable th = ex.getTargetException();
1.930 - if (th instanceof ObjectStreamException) {
1.931 - throw (ObjectStreamException) th;
1.932 - } else {
1.933 - throwMiscException(th);
1.934 - throw new InternalError(); // never reached
1.935 - }
1.936 - } catch (IllegalAccessException ex) {
1.937 - // should not occur, as access checks have been suppressed
1.938 - throw new InternalError();
1.939 - }
1.940 - } else {
1.941 - throw new UnsupportedOperationException();
1.942 - }
1.943 - }
1.944 -
1.945 - /**
1.946 - * Invokes the readResolve method of the represented serializable class and
1.947 - * returns the result. Throws UnsupportedOperationException if this class
1.948 - * descriptor is not associated with a class, or if the class is
1.949 - * non-serializable or does not define readResolve.
1.950 - */
1.951 - Object invokeReadResolve(Object obj)
1.952 - throws IOException, UnsupportedOperationException
1.953 - {
1.954 - if (readResolveMethod != null) {
1.955 - try {
1.956 - return readResolveMethod.invoke(obj, (Object[]) null);
1.957 - } catch (InvocationTargetException ex) {
1.958 - Throwable th = ex.getTargetException();
1.959 - if (th instanceof ObjectStreamException) {
1.960 - throw (ObjectStreamException) th;
1.961 - } else {
1.962 - throwMiscException(th);
1.963 - throw new InternalError(); // never reached
1.964 - }
1.965 - } catch (IllegalAccessException ex) {
1.966 - // should not occur, as access checks have been suppressed
1.967 - throw new InternalError();
1.968 - }
1.969 - } else {
1.970 - throw new UnsupportedOperationException();
1.971 - }
1.972 - }
1.973 -
1.974 - /**
1.975 - * Class representing the portion of an object's serialized form allotted
1.976 - * to data described by a given class descriptor. If "hasData" is false,
1.977 - * the object's serialized form does not contain data associated with the
1.978 - * class descriptor.
1.979 - */
1.980 - static class ClassDataSlot {
1.981 -
1.982 - /** class descriptor "occupying" this slot */
1.983 - final ObjectStreamClass desc;
1.984 - /** true if serialized form includes data for this slot's descriptor */
1.985 - final boolean hasData;
1.986 -
1.987 - ClassDataSlot(ObjectStreamClass desc, boolean hasData) {
1.988 - this.desc = desc;
1.989 - this.hasData = hasData;
1.990 - }
1.991 - }
1.992 -
1.993 - /**
1.994 - * Returns array of ClassDataSlot instances representing the data layout
1.995 - * (including superclass data) for serialized objects described by this
1.996 - * class descriptor. ClassDataSlots are ordered by inheritance with those
1.997 - * containing "higher" superclasses appearing first. The final
1.998 - * ClassDataSlot contains a reference to this descriptor.
1.999 - */
1.1000 - ClassDataSlot[] getClassDataLayout() throws InvalidClassException {
1.1001 - // REMIND: synchronize instead of relying on volatile?
1.1002 - if (dataLayout == null) {
1.1003 - dataLayout = getClassDataLayout0();
1.1004 - }
1.1005 - return dataLayout;
1.1006 - }
1.1007 -
1.1008 - private ClassDataSlot[] getClassDataLayout0()
1.1009 - throws InvalidClassException
1.1010 - {
1.1011 - ArrayList<ClassDataSlot> slots = new ArrayList<>();
1.1012 - Class<?> start = cl, end = cl;
1.1013 -
1.1014 - // locate closest non-serializable superclass
1.1015 - while (end != null && Serializable.class.isAssignableFrom(end)) {
1.1016 - end = end.getSuperclass();
1.1017 - }
1.1018 -
1.1019 - for (ObjectStreamClass d = this; d != null; d = d.superDesc) {
1.1020 -
1.1021 - // search up inheritance hierarchy for class with matching name
1.1022 - String searchName = (d.cl != null) ? d.cl.getName() : d.name;
1.1023 - Class<?> match = null;
1.1024 - for (Class<?> c = start; c != end; c = c.getSuperclass()) {
1.1025 - if (searchName.equals(c.getName())) {
1.1026 - match = c;
1.1027 - break;
1.1028 - }
1.1029 - }
1.1030 -
1.1031 - // add "no data" slot for each unmatched class below match
1.1032 - if (match != null) {
1.1033 - for (Class<?> c = start; c != match; c = c.getSuperclass()) {
1.1034 - slots.add(new ClassDataSlot(
1.1035 - ObjectStreamClass.lookup(c, true), false));
1.1036 - }
1.1037 - start = match.getSuperclass();
1.1038 - }
1.1039 -
1.1040 - // record descriptor/class pairing
1.1041 - slots.add(new ClassDataSlot(d.getVariantFor(match), true));
1.1042 - }
1.1043 -
1.1044 - // add "no data" slot for any leftover unmatched classes
1.1045 - for (Class<?> c = start; c != end; c = c.getSuperclass()) {
1.1046 - slots.add(new ClassDataSlot(
1.1047 - ObjectStreamClass.lookup(c, true), false));
1.1048 - }
1.1049 -
1.1050 - // order slots from superclass -> subclass
1.1051 - Collections.reverse(slots);
1.1052 - return slots.toArray(new ClassDataSlot[slots.size()]);
1.1053 - }
1.1054 -
1.1055 - /**
1.1056 - * Returns aggregate size (in bytes) of marshalled primitive field values
1.1057 - * for represented class.
1.1058 - */
1.1059 - int getPrimDataSize() {
1.1060 - return primDataSize;
1.1061 - }
1.1062 -
1.1063 - /**
1.1064 - * Returns number of non-primitive serializable fields of represented
1.1065 - * class.
1.1066 - */
1.1067 - int getNumObjFields() {
1.1068 - return numObjFields;
1.1069 - }
1.1070 -
1.1071 - /**
1.1072 - * Fetches the serializable primitive field values of object obj and
1.1073 - * marshals them into byte array buf starting at offset 0. It is the
1.1074 - * responsibility of the caller to ensure that obj is of the proper type if
1.1075 - * non-null.
1.1076 - */
1.1077 - void getPrimFieldValues(Object obj, byte[] buf) {
1.1078 - }
1.1079 -
1.1080 - /**
1.1081 - * Sets the serializable primitive fields of object obj using values
1.1082 - * unmarshalled from byte array buf starting at offset 0. It is the
1.1083 - * responsibility of the caller to ensure that obj is of the proper type if
1.1084 - * non-null.
1.1085 - */
1.1086 - void setPrimFieldValues(Object obj, byte[] buf) {
1.1087 - }
1.1088 -
1.1089 - /**
1.1090 - * Fetches the serializable object field values of object obj and stores
1.1091 - * them in array vals starting at offset 0. It is the responsibility of
1.1092 - * the caller to ensure that obj is of the proper type if non-null.
1.1093 - */
1.1094 - void getObjFieldValues(Object obj, Object[] vals) {
1.1095 - }
1.1096 -
1.1097 - /**
1.1098 - * Sets the serializable object fields of object obj using values from
1.1099 - * array vals starting at offset 0. It is the responsibility of the caller
1.1100 - * to ensure that obj is of the proper type if non-null.
1.1101 - */
1.1102 - void setObjFieldValues(Object obj, Object[] vals) {
1.1103 - }
1.1104 -
1.1105 - /**
1.1106 - * Calculates and sets serializable field offsets, as well as primitive
1.1107 - * data size and object field count totals. Throws InvalidClassException
1.1108 - * if fields are illegally ordered.
1.1109 - */
1.1110 - private void computeFieldOffsets() throws InvalidClassException {
1.1111 - primDataSize = 0;
1.1112 - numObjFields = 0;
1.1113 - int firstObjIndex = -1;
1.1114 -
1.1115 - for (int i = 0; i < fields.length; i++) {
1.1116 - ObjectStreamField f = fields[i];
1.1117 - switch (f.getTypeCode()) {
1.1118 - case 'Z':
1.1119 - case 'B':
1.1120 - f.setOffset(primDataSize++);
1.1121 - break;
1.1122 -
1.1123 - case 'C':
1.1124 - case 'S':
1.1125 - f.setOffset(primDataSize);
1.1126 - primDataSize += 2;
1.1127 - break;
1.1128 -
1.1129 - case 'I':
1.1130 - case 'F':
1.1131 - f.setOffset(primDataSize);
1.1132 - primDataSize += 4;
1.1133 - break;
1.1134 -
1.1135 - case 'J':
1.1136 - case 'D':
1.1137 - f.setOffset(primDataSize);
1.1138 - primDataSize += 8;
1.1139 - break;
1.1140 -
1.1141 - case '[':
1.1142 - case 'L':
1.1143 - f.setOffset(numObjFields++);
1.1144 - if (firstObjIndex == -1) {
1.1145 - firstObjIndex = i;
1.1146 - }
1.1147 - break;
1.1148 -
1.1149 - default:
1.1150 - throw new InternalError();
1.1151 - }
1.1152 - }
1.1153 - if (firstObjIndex != -1 &&
1.1154 - firstObjIndex + numObjFields != fields.length)
1.1155 - {
1.1156 - throw new InvalidClassException(name, "illegal field order");
1.1157 - }
1.1158 - }
1.1159 -
1.1160 - /**
1.1161 - * If given class is the same as the class associated with this class
1.1162 - * descriptor, returns reference to this class descriptor. Otherwise,
1.1163 - * returns variant of this class descriptor bound to given class.
1.1164 - */
1.1165 - private ObjectStreamClass getVariantFor(Class<?> cl)
1.1166 - throws InvalidClassException
1.1167 - {
1.1168 - if (this.cl == cl) {
1.1169 - return this;
1.1170 - }
1.1171 - ObjectStreamClass desc = new ObjectStreamClass();
1.1172 - if (isProxy) {
1.1173 - desc.initProxy(cl, null, superDesc);
1.1174 - } else {
1.1175 - desc.initNonProxy(this, cl, null, superDesc);
1.1176 - }
1.1177 - return desc;
1.1178 - }
1.1179 -
1.1180 - /**
1.1181 - * Returns public no-arg constructor of given class, or null if none found.
1.1182 - * Access checks are disabled on the returned constructor (if any), since
1.1183 - * the defining class may still be non-public.
1.1184 - */
1.1185 - private static Constructor getExternalizableConstructor(Class<?> cl) {
1.1186 - throw new SecurityException();
1.1187 - }
1.1188 -
1.1189 - /**
1.1190 - * Returns subclass-accessible no-arg constructor of first non-serializable
1.1191 - * superclass, or null if none found. Access checks are disabled on the
1.1192 - * returned constructor (if any).
1.1193 - */
1.1194 - private static Constructor getSerializableConstructor(Class<?> cl) {
1.1195 - Class<?> initCl = cl;
1.1196 - while (Serializable.class.isAssignableFrom(initCl)) {
1.1197 - if ((initCl = initCl.getSuperclass()) == null) {
1.1198 - return null;
1.1199 - }
1.1200 - }
1.1201 - throw new SecurityException();
1.1202 - }
1.1203 -
1.1204 - /**
1.1205 - * Returns non-static, non-abstract method with given signature provided it
1.1206 - * is defined by or accessible (via inheritance) by the given class, or
1.1207 - * null if no match found. Access checks are disabled on the returned
1.1208 - * method (if any).
1.1209 - */
1.1210 - private static Method getInheritableMethod(Class<?> cl, String name,
1.1211 - Class<?>[] argTypes,
1.1212 - Class<?> returnType)
1.1213 - {
1.1214 - throw new SecurityException();
1.1215 - }
1.1216 -
1.1217 - /**
1.1218 - * Returns non-static private method with given signature defined by given
1.1219 - * class, or null if none found. Access checks are disabled on the
1.1220 - * returned method (if any).
1.1221 - */
1.1222 - private static Method getPrivateMethod(Class<?> cl, String name,
1.1223 - Class<?>[] argTypes,
1.1224 - Class<?> returnType)
1.1225 - {
1.1226 - throw new SecurityException();
1.1227 - }
1.1228 -
1.1229 - /**
1.1230 - * Returns true if classes are defined in the same runtime package, false
1.1231 - * otherwise.
1.1232 - */
1.1233 - private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
1.1234 - return (cl1.getClassLoader() == cl2.getClassLoader() &&
1.1235 - getPackageName(cl1).equals(getPackageName(cl2)));
1.1236 - }
1.1237 -
1.1238 - /**
1.1239 - * Returns package name of given class.
1.1240 - */
1.1241 - private static String getPackageName(Class<?> cl) {
1.1242 - String s = cl.getName();
1.1243 - int i = s.lastIndexOf('[');
1.1244 - if (i >= 0) {
1.1245 - s = s.substring(i + 2);
1.1246 - }
1.1247 - i = s.lastIndexOf('.');
1.1248 - return (i >= 0) ? s.substring(0, i) : "";
1.1249 - }
1.1250 -
1.1251 - /**
1.1252 - * Compares class names for equality, ignoring package names. Returns true
1.1253 - * if class names equal, false otherwise.
1.1254 - */
1.1255 - private static boolean classNamesEqual(String name1, String name2) {
1.1256 - name1 = name1.substring(name1.lastIndexOf('.') + 1);
1.1257 - name2 = name2.substring(name2.lastIndexOf('.') + 1);
1.1258 - return name1.equals(name2);
1.1259 - }
1.1260 -
1.1261 - /**
1.1262 - * Returns JVM type signature for given class.
1.1263 - */
1.1264 - private static String getClassSignature(Class<?> cl) {
1.1265 - StringBuilder sbuf = new StringBuilder();
1.1266 - while (cl.isArray()) {
1.1267 - sbuf.append('[');
1.1268 - cl = cl.getComponentType();
1.1269 - }
1.1270 - if (cl.isPrimitive()) {
1.1271 - if (cl == Integer.TYPE) {
1.1272 - sbuf.append('I');
1.1273 - } else if (cl == Byte.TYPE) {
1.1274 - sbuf.append('B');
1.1275 - } else if (cl == Long.TYPE) {
1.1276 - sbuf.append('J');
1.1277 - } else if (cl == Float.TYPE) {
1.1278 - sbuf.append('F');
1.1279 - } else if (cl == Double.TYPE) {
1.1280 - sbuf.append('D');
1.1281 - } else if (cl == Short.TYPE) {
1.1282 - sbuf.append('S');
1.1283 - } else if (cl == Character.TYPE) {
1.1284 - sbuf.append('C');
1.1285 - } else if (cl == Boolean.TYPE) {
1.1286 - sbuf.append('Z');
1.1287 - } else if (cl == Void.TYPE) {
1.1288 - sbuf.append('V');
1.1289 - } else {
1.1290 - throw new InternalError();
1.1291 - }
1.1292 - } else {
1.1293 - sbuf.append('L' + cl.getName().replace('.', '/') + ';');
1.1294 - }
1.1295 - return sbuf.toString();
1.1296 - }
1.1297 -
1.1298 - /**
1.1299 - * Returns JVM type signature for given list of parameters and return type.
1.1300 - */
1.1301 - private static String getMethodSignature(Class<?>[] paramTypes,
1.1302 - Class<?> retType)
1.1303 - {
1.1304 - StringBuilder sbuf = new StringBuilder();
1.1305 - sbuf.append('(');
1.1306 - for (int i = 0; i < paramTypes.length; i++) {
1.1307 - sbuf.append(getClassSignature(paramTypes[i]));
1.1308 - }
1.1309 - sbuf.append(')');
1.1310 - sbuf.append(getClassSignature(retType));
1.1311 - return sbuf.toString();
1.1312 - }
1.1313 -
1.1314 - /**
1.1315 - * Convenience method for throwing an exception that is either a
1.1316 - * RuntimeException, Error, or of some unexpected type (in which case it is
1.1317 - * wrapped inside an IOException).
1.1318 - */
1.1319 - private static void throwMiscException(Throwable th) throws IOException {
1.1320 - if (th instanceof RuntimeException) {
1.1321 - throw (RuntimeException) th;
1.1322 - } else if (th instanceof Error) {
1.1323 - throw (Error) th;
1.1324 - } else {
1.1325 - IOException ex = new IOException("unexpected exception type");
1.1326 - ex.initCause(th);
1.1327 - throw ex;
1.1328 - }
1.1329 - }
1.1330 -
1.1331 - /**
1.1332 - * Returns ObjectStreamField array describing the serializable fields of
1.1333 - * the given class. Serializable fields backed by an actual field of the
1.1334 - * class are represented by ObjectStreamFields with corresponding non-null
1.1335 - * Field objects. Throws InvalidClassException if the (explicitly
1.1336 - * declared) serializable fields are invalid.
1.1337 - */
1.1338 - private static ObjectStreamField[] getSerialFields(Class<?> cl)
1.1339 - throws InvalidClassException
1.1340 - {
1.1341 - ObjectStreamField[] fields;
1.1342 - if (Serializable.class.isAssignableFrom(cl) &&
1.1343 - !Externalizable.class.isAssignableFrom(cl) &&
1.1344 - !Proxy.isProxyClass(cl) &&
1.1345 - !cl.isInterface())
1.1346 - {
1.1347 - if ((fields = getDeclaredSerialFields(cl)) == null) {
1.1348 - fields = getDefaultSerialFields(cl);
1.1349 - }
1.1350 - Arrays.sort(fields);
1.1351 - } else {
1.1352 - fields = NO_FIELDS;
1.1353 - }
1.1354 - return fields;
1.1355 - }
1.1356 -
1.1357 - /**
1.1358 - * Returns serializable fields of given class as defined explicitly by a
1.1359 - * "serialPersistentFields" field, or null if no appropriate
1.1360 - * "serialPersistentFields" field is defined. Serializable fields backed
1.1361 - * by an actual field of the class are represented by ObjectStreamFields
1.1362 - * with corresponding non-null Field objects. For compatibility with past
1.1363 - * releases, a "serialPersistentFields" field with a null value is
1.1364 - * considered equivalent to not declaring "serialPersistentFields". Throws
1.1365 - * InvalidClassException if the declared serializable fields are
1.1366 - * invalid--e.g., if multiple fields share the same name.
1.1367 - */
1.1368 - private static ObjectStreamField[] getDeclaredSerialFields(Class<?> cl)
1.1369 - throws InvalidClassException
1.1370 - {
1.1371 - throw new SecurityException();
1.1372 - }
1.1373 -
1.1374 - /**
1.1375 - * Returns array of ObjectStreamFields corresponding to all non-static
1.1376 - * non-transient fields declared by given class. Each ObjectStreamField
1.1377 - * contains a Field object for the field it represents. If no default
1.1378 - * serializable fields exist, NO_FIELDS is returned.
1.1379 - */
1.1380 - private static ObjectStreamField[] getDefaultSerialFields(Class<?> cl) {
1.1381 - throw new SecurityException();
1.1382 - }
1.1383 -
1.1384 - /**
1.1385 - * Returns explicit serial version UID value declared by given class, or
1.1386 - * null if none.
1.1387 - */
1.1388 - private static Long getDeclaredSUID(Class<?> cl) {
1.1389 - return null;
1.1390 - }
1.1391 -
1.1392 - /**
1.1393 - * Computes the default serial version UID value for the given class.
1.1394 - */
1.1395 - private static long computeDefaultSUID(Class<?> cl) {
1.1396 - throw new SecurityException();
1.1397 - }
1.1398 -
1.1399 -}