}
localClassDesc = lookupInternal(cl);
if (localClassDesc == null)
// XXX I18N, logging needed
throw new InvalidClassException(cl.getName(),
"Local class not compatible");
if (suid != localClassDesc.suid) {
/* Check for exceptional cases that allow mismatched suid. */
/* Allow adding Serializable or Externalizable
* to a later release of the class.
*/
boolean addedSerialOrExtern =
isNonSerializable() || localClassDesc.isNonSerializable();
/* Disregard the serialVersionUID of an array
* when name and cl.Name differ. If resolveClass() returns
* an array with a different package name,
* the serialVersionUIDs will not match since the fully
* qualified array class is used in the
* computation of the array's serialVersionUID. There is
* no way to set a permanent serialVersionUID for an array type.
*/
boolean arraySUID = (cl.isArray() && ! cl.getName().equals(name));
if (! arraySUID && ! addedSerialOrExtern ) {
// XXX I18N, logging needed
throw new InvalidClassException(cl.getName(),
"Local class not compatible:" +
" stream classdesc serialVersionUID=" + suid +
" local class serialVersionUID=" + localClassDesc.suid);
}
}
/* compare the class names, stripping off package names. */
if (! compareClassNames(name, cl.getName(), '.'))
// XXX I18N, logging needed
throw new InvalidClassException(cl.getName(),
"Incompatible local class name. " +
"Expected class name compatible with " +
name);
/*
* Test that both implement either serializable or externalizable.
*/
// The next check is more generic, since it covers the
// Proxy case, the JDK 1.3 serialization code has
// both checks
//if ((serializable && localClassDesc.externalizable) ||
// (externalizable && localClassDesc.serializable))
// throw new InvalidClassException(localCl.getName(),
// "Serializable is incompatible with Externalizable");
if ((serializable != localClassDesc.serializable) ||
(externalizable != localClassDesc.externalizable) ||
(!serializable && !externalizable))
// XXX I18N, logging needed
throw new InvalidClassException(cl.getName(),
"Serialization incompatible with Externalization");
/* Set up the reflected Fields in the class where the value of each
* field in this descriptor should be stored.
* Each field in this ObjectStreamClass (the source) is located (by
* name) in the ObjectStreamClass of the class(the destination).
* In the usual (non-versioned case) the field is in both
* descriptors and the types match, so the reflected Field is copied.
* If the type does not match, a InvalidClass exception is thrown.
* If the field is not present in the class, the reflected Field
* remains null so the field will be read but discarded.
* If extra fields are present in the class they are ignored. Their
* values will be set to the default value by the object allocator.
* Both the src and dest field list are sorted by type and name.
*/
ObjectStreamField[] destfield =
(ObjectStreamField[])localClassDesc.fields;
ObjectStreamField[] srcfield =
(ObjectStreamField[])fields;
int j = 0;
nextsrc:
for (int i = 0; i < srcfield.length; i++ ) {
/* Find this field in the dest*/
for (int k = j; k < destfield.length; k++) {
if (srcfield[i].getName().equals(destfield[k].getName())) {
/* found match */
if (srcfield[i].isPrimitive() &&
!srcfield[i].typeEquals(destfield[k])) {
// XXX I18N, logging needed
throw new InvalidClassException(cl.getName(),
"The type of field " +
srcfield[i].getName() +
" of class " + name +
" is incompatible.");
}