blob: eb91e9f823d4f49562b90f472720c9e1d8b4a733 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.yoko.rmi.impl;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableSet;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.ObjectStreamField;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.yoko.rmi.util.StringUtil;
import org.omg.CORBA.AttributeDescription;
import org.omg.CORBA.Initializer;
import org.omg.CORBA.MARSHAL;
import org.omg.CORBA.ORB;
import org.omg.CORBA.OperationDescription;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.VM_NONE;
import org.omg.CORBA.ValueMember;
import org.omg.CORBA.ValueDefPackage.FullValueDescription;
import org.omg.CORBA.portable.InputStream;
import org.omg.CORBA.portable.OutputStream;
import org.omg.CORBA.portable.UnknownException;
import org.omg.SendingContext.CodeBase;
import org.omg.SendingContext.CodeBaseHelper;
import org.omg.SendingContext.RunTime;
import sun.reflect.ReflectionFactory;
class ValueDescriptor extends TypeDescriptor {
static final Logger logger = Logger.getLogger(ValueDescriptor.class.getName());
private boolean _is_externalizable;
private boolean _is_serializable;
private Method _write_replace_method;
private Method _read_resolve_method;
private Constructor _constructor;
private Method _write_object_method;
private Method _read_object_method;
private Field _serial_version_uid_field;
protected ValueDescriptor _super_descriptor;
protected FieldDescriptor[] _fields;
private ObjectDeserializer _object_deserializer;
private boolean _is_immutable_value;
private boolean _is_rmi_stub;
private String _custom_repid;
private static final Set<? extends Class<? extends Serializable>> _immutable_value_classes = unmodifiableSet(new HashSet<>(asList(Integer.class,
Character.class, Boolean.class, Byte.class, Long.class, Float.class, Double.class, Short.class)));
private long _hash_code;
ValueDescriptor(Class type, TypeRepository repository) {
super(type, repository);
}
protected boolean isEnum() { return false; }
@Override
protected String genRepId() {
return String.format("RMI:%s:%016X:%016X", StringUtil.convertToValidIDLNames(type.getName()),
_hash_code, getSerialVersionUID());
}
private String genCustomRepId() {
return String.format("RMI:org.omg.custom.%s", getRepositoryID().substring(4));
}
public final String getCustomRepositoryID() {
if (_custom_repid == null) _custom_repid = genCustomRepId();
return _custom_repid;
}
protected long getSerialVersionUID() {
if (_serial_version_uid_field != null) {
try {
return _serial_version_uid_field.getLong(null);
} catch (IllegalAccessException ex) {
// skip //
}
}
ObjectStreamClass serialForm = ObjectStreamClass.lookup(type);
return (serialForm != null) ? serialForm.getSerialVersionUID() : 0L;
}
public void init() {
try {
init0();
super.init();
if (_fields == null) {
throw new RuntimeException("fields==null after init!");
}
} catch (RuntimeException | Error ex) {
logger.log(Level.FINE, "runtime error in ValueDescriptor.init " + ex.getMessage(), ex);
}
}
private void init0() {
final Class<?> superClass = type.getSuperclass();
_is_rmi_stub = RMIStub.class.isAssignableFrom(type);
_is_externalizable = Externalizable.class.isAssignableFrom(type);
_is_serializable = Serializable.class.isAssignableFrom(type);
_is_immutable_value = _immutable_value_classes.contains(type);
if ((superClass != null) && (superClass != Object.class)) {
TypeDescriptor superDesc = repo.getDescriptor(superClass);
if (superDesc instanceof ValueDescriptor) {
_super_descriptor = (ValueDescriptor) superDesc;
}
}
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
for (Class<?> curr = type; curr != null; curr = curr.getSuperclass()) {
//
// get writeReplace, if any
//
try {
_write_replace_method = curr.getDeclaredMethod("writeReplace");
_write_replace_method.setAccessible(true);
break;
} catch (NoSuchMethodException ignored) {
}
}
//
// Get readResolve, if present
//
try {
_read_resolve_method = type.getDeclaredMethod("readResolve");
_read_resolve_method.setAccessible(true);
} catch (NoSuchMethodException ignored) {
}
//
// get readObject
//
try {
_read_object_method = type.getDeclaredMethod("readObject", ObjectInputStream.class);
_read_object_method.setAccessible(true);
} catch (NoSuchMethodException ignored) {
}
//
// get readObject
//
try {
_write_object_method = type.getDeclaredMethod("writeObject", ObjectOutputStream.class);
_write_object_method.setAccessible(true);
} catch (NoSuchMethodException ignored) {
}
//
// validate readObject
//
if ((_write_object_method == null) || !Modifier.isPrivate(_write_object_method.getModifiers())
|| Modifier.isStatic(_write_object_method.getModifiers()) || (_write_object_method.getDeclaringClass() != type)) {
_write_object_method = null;
}
//
// validate writeObject
//
if ((_read_object_method == null) || !Modifier.isPrivate(_read_object_method.getModifiers())
|| Modifier.isStatic(_read_object_method.getModifiers())) {
_read_object_method = null;
}
//
// get serialVersionUID field
//
try {
_serial_version_uid_field = type.getDeclaredField("serialVersionUID");
if (Modifier.isStatic(_serial_version_uid_field.getModifiers())) {
_serial_version_uid_field.setAccessible(true);
} else {
_serial_version_uid_field = null;
}
} catch (NoSuchFieldException ex) {
// skip //
}
//
// get serialPersistentFields field
//
ObjectStreamField[] serial_persistent_fields = null;
try {
Field _serial_persistent_fields_field = type.getDeclaredField("serialPersistentFields");
_serial_persistent_fields_field.setAccessible(true);
serial_persistent_fields = (ObjectStreamField[]) _serial_persistent_fields_field.get(null);
} catch (IllegalAccessException | NoSuchFieldException ex) {
// skip //
}
if (_is_externalizable) {
//
// Get the default constructor
//
try {
_constructor = type.getDeclaredConstructor();
_constructor.setAccessible(true);
} catch (NoSuchMethodException ex) {
logger.log(Level.WARNING, "Class " + type.getName() + " is not properly externalizable. "
+ "It has not default constructor.", ex);
}
} else if (_is_serializable && !type.isInterface()) {
Class<?> initClass = type;
while ((initClass != null) && Serializable.class.isAssignableFrom(initClass)) {
initClass = initClass.getSuperclass();
}
if (initClass == null) {
logger.warning("Class " + type.getName() + " is not properly serializable. " + "It has no non-serializable super-class");
} else {
try {
Constructor init_cons = initClass.getDeclaredConstructor();
if (Modifier.isPublic(init_cons.getModifiers()) || Modifier.isProtected(init_cons.getModifiers())) {
// do nothing - it's accessible
} else if (!samePackage(type, initClass)) {
logger.warning("Class " + type.getName() + " is not properly serializable. "
+ "The default constructor of its first " + "non-serializable super-class (" + initClass.getName()
+ ") is not accessible.");
}
_constructor = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(type, init_cons);
if (_constructor == null) {
logger.warning("Unable to get constructor for serialization for class " + java_name);
} else {
_constructor.setAccessible(true);
}
} catch (NoSuchMethodException ex) {
logger.log(Level.WARNING, "Class " + type.getName() + " is not properly serializable. "
+ "First non-serializable super-class (" + initClass.getName() + ") has no default constructor.", ex);
}
}
}
if (serial_persistent_fields == null) {
//
// Get relevant field definitions
//
Field[] ff = type.getDeclaredFields();
if ((ff == null) || (ff.length == 0)) {
_fields = new FieldDescriptor[0];
} else {
List<FieldDescriptor> flist = new ArrayList<>();
for (Field f : ff) {
int mod = f.getModifiers();
if (Modifier.isStatic(mod) || Modifier.isTransient(mod)) {
continue;
}
f.setAccessible(true);
FieldDescriptor fd = FieldDescriptor.get(f, repo);
flist.add(fd);
}
_fields = new FieldDescriptor[flist.size()];
_fields = flist.toArray(_fields);
//
// sort the fields
//
Arrays.sort(_fields);
}
} else {
_fields = new FieldDescriptor[serial_persistent_fields.length];
for (int i = 0; i < serial_persistent_fields.length; i++) {
ObjectStreamField f = serial_persistent_fields[i];
FieldDescriptor fd = null;
try {
Field rf = type.getField(f.getName());
rf.setAccessible(true);
if (rf.getType() == f.getType()) {
fd = FieldDescriptor.get(rf,repo);
}
} catch (SecurityException | NoSuchFieldException ex) {
}
if (fd == null) {
fd = FieldDescriptor.get(type, f, repo);
}
_fields[i] = fd;
}
//
// sort the fields (this is also the case for serial
// persistent
// fields, because they have to map to some foreign
// IDL).
//
Arrays.sort(_fields);
}
//
// Compute the structural hash
//
_hash_code = computeHashCode();
//
// Setup the default deserializer
//
_object_deserializer = new ObjectDeserializer(ValueDescriptor.this);
return null;
}
});
}
private boolean samePackage(Class type, Class initClass) {
String pkg1 = getPackageName(type);
String pkg2 = getPackageName(initClass);
return pkg1.equals(pkg2);
}
private String getPackageName(Class type) {
String name = type.getName();
int idx = name.lastIndexOf('.');
return (idx == -1) ? "" : name.substring(0, idx);
}
/** Read an instance of this value from a CDR stream */
public Object read(org.omg.CORBA.portable.InputStream in) {
return ((org.omg.CORBA_2_3.portable.InputStream) in).read_value();
}
/** Write an instance of this value to a CDR stream */
public void write(OutputStream out, Object value) {
((org.omg.CORBA_2_3.portable.OutputStream) out).write_value((Serializable) value);
}
public boolean isCustomMarshalled() {
return (_is_externalizable || (_write_object_method != null));
}
public boolean isChunked() {
if (isCustomMarshalled()) return true;
return (_super_descriptor != null) && _super_descriptor.isChunked();
}
public Serializable writeReplace(Serializable val) {
if (_write_replace_method != null) {
try {
return (Serializable) _write_replace_method.invoke(val);
} catch (IllegalAccessException ex) {
throw (MARSHAL) new MARSHAL("cannot call " + _write_replace_method).initCause(ex);
} catch (IllegalArgumentException ex) {
throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
} catch (InvocationTargetException ex) {
throw (UnknownException) new UnknownException(ex.getTargetException()).initCause(ex.getTargetException());
}
}
return val;
}
public Serializable readResolve(Serializable val) {
if (_read_resolve_method != null) {
try {
return (Serializable) _read_resolve_method.invoke(val);
} catch (IllegalAccessException ex) {
throw (MARSHAL) new MARSHAL("cannot call " + _read_resolve_method).initCause(ex);
} catch (IllegalArgumentException ex) {
throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
} catch (InvocationTargetException ex) {
throw (UnknownException) new UnknownException(ex.getTargetException()).initCause(ex.getTargetException());
}
}
return val;
}
public void writeValue(final OutputStream out, final Serializable value) {
try {
ObjectWriter writer = (ObjectWriter) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
try {
return new CorbaObjectWriter(out, value);
} catch (IOException ex) {
throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
}
}
});
writeValue(writer, value);
} catch (IOException ex) {
throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
}
}
protected void defaultWriteValue(ObjectWriter writer, Serializable val) throws IOException {
logger.finer("writing fields for " + type);
FieldDescriptor[] fields = _fields;
if (fields == null) {
return;
}
for (int i = 0; i < fields.length; i++) {
logger.finer("writing field " + _fields[i].java_name);
fields[i].write(writer, val);
}
}
protected void writeValue(ObjectWriter writer, Serializable val) throws IOException {
if (_is_externalizable) {
writer.invokeWriteExternal((Externalizable) val);
return;
}
if (_super_descriptor != null) {
_super_descriptor.writeValue(writer, val);
}
if (_write_object_method != null) {
try {
writer.invokeWriteObject(this, val, _write_object_method);
} catch (IllegalAccessException | IllegalArgumentException ex) {
throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
} catch (InvocationTargetException ex) {
throw (UnknownException) new UnknownException(ex.getTargetException()).initCause(ex.getTargetException());
}
} else {
defaultWriteValue(writer, val);
}
}
private Serializable createBlankInstance() {
if (_constructor != null) {
try {
return (Serializable) _constructor.newInstance();
} catch (IllegalAccessException ex) {
throw (MARSHAL) new MARSHAL("cannot call " + _constructor).initCause(ex);
} catch (IllegalArgumentException | InstantiationException ex) {
throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
} catch (InvocationTargetException ex) {
throw (UnknownException) new UnknownException(ex.getTargetException()).initCause(ex.getTargetException());
} catch (NullPointerException ex) {
logger.log(Level.WARNING, "unable to create instance of " + type.getName(), ex);
logger.warning("constructor => " + _constructor);
throw ex;
}
} else {
return null;
}
}
public Serializable readValue(final InputStream in, final Map<Integer, Object> offsetMap, final Integer offset) {
final Serializable value = createBlankInstance();
offsetMap.put(offset, value);
try {
ObjectReader reader = (ObjectReader) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
try {
return new CorbaObjectReader(in, offsetMap, value);
} catch (IOException ex) {
throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
}
}
});
readValue(reader, value);
final Serializable resolved = readResolve(value);
if (value != resolved) {
offsetMap.put(offset, resolved);
}
return resolved;
} catch (IOException ex) {
throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
}
}
void print(PrintWriter pw, Map<Object, Integer> recurse, Object val) {
if (val == null) {
pw.print("null");
}
Integer old = recurse.get(val);
if (old != null) {
pw.print("^" + old);
} else {
int key = System.identityHashCode(val);
recurse.put(val, key);
pw.println(type.getName() + "@" + Integer.toHexString(key) + "[");
printFields(pw, recurse, val);
pw.println("]");
}
}
void printFields(PrintWriter pw, Map recurse, Object val) {
pw.print("(" + getClass().getName() + ")");
if (_super_descriptor != null) {
_super_descriptor.printFields(pw, recurse, val);
}
if (_fields == null)
return;
for (int i = 0; i < _fields.length; i++) {
if (i != 0) {
pw.print("; ");
}
_fields[i].print(pw, recurse, val);
}
}
protected void defaultReadValue(ObjectReader reader, Serializable value) throws IOException {
// System.out.println ("defaultReadValue "+getJavaClass());
if (_fields == null) {
// System.out.println ("fields == null for "+getJavaClass ());
return;
}
logger.fine("reading fields for " + type.getName());
for (FieldDescriptor _field : _fields) {
logger.fine("reading field " + _field.java_name + " of type " + _field.getType().getName() + " using " + _field.getClass().getName());
try {
_field.read(reader, value);
} catch (MARSHAL ex) {
if (ex.getMessage() != null)
throw ex;
String msg = String.format("%s, while reading %s.%s", ex, java_name, _field.java_name);
throw (MARSHAL) new MARSHAL(msg, ex.minor, ex.completed).initCause(ex);
}
}
}
Map readFields(ObjectReader reader) throws IOException {
if ((_fields == null) || (_fields.length == 0)) {
return Collections.EMPTY_MAP;
}
logger.finer("reading fields for " + type.getName());
Map map = new HashMap();
for (FieldDescriptor _field : _fields) {
logger.finer("reading field " + _field.java_name);
_field.readFieldIntoMap(reader, map);
}
return map;
}
void writeFields(ObjectWriter writer, Map fieldMap) throws IOException {
if ((_fields == null) || (_fields.length == 0)) {
return;
}
logger.finer("writing fields for " + type.getName());
for (FieldDescriptor _field : _fields) {
logger.finer("writing field " + _field.java_name);
_field.writeFieldFromMap(writer, fieldMap);
}
}
/**
* This methods reads the fields of a single class slice.
*/
protected void readValue(ObjectReader reader, Serializable value) throws IOException {
if (_is_externalizable) {
try {
reader.readExternal((Externalizable) value);
} catch (ClassNotFoundException e) {
throw new IOException("cannot instantiate class", e);
}
return;
}
if (_super_descriptor != null) {
_super_descriptor.readValue(reader, value);
}
// check whether the class (not its ancestors) does any custom marshalling
if (_write_object_method != null) {
// read custom marshalling value header
byte cmsfVersion = reader.readByte(); // custom marshal stream format version
boolean dwoCalled = reader.readBoolean(); // was defaultWriteObject() called?
logger.log(Level.FINE, "Reading value in streamFormatVersion=" + cmsfVersion + " defaultWriteObject=" + dwoCalled);
if (cmsfVersion == 2) {
// use a wrapped reader to open the secondary custom valuetype
ObjectReader wrapper = new CustomMarshaledObjectReader(reader);
readSerializable(_read_object_method == null ? reader : wrapper, value);
// invoke close to skip to the end of the secondary custom valuetype
wrapper.close();
return;
}
}
readSerializable(reader, value);
}
private void readSerializable(ObjectReader reader, Serializable value) throws IOException {
if (_read_object_method != null) {
try {
reader.setCurrentValueDescriptor(this);
_read_object_method.invoke(value, reader);
reader.setCurrentValueDescriptor(null);
} catch (IllegalAccessException | IllegalArgumentException ex) {
throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
} catch (InvocationTargetException ex) {
throw (UnknownException) new UnknownException(ex.getTargetException()).initCause(ex.getTargetException());
}
} else {
defaultReadValue(reader, value);
}
}
protected long computeHashCode() {
Class type = this.type;
if (_is_externalizable) {
return 1L;
}
if (!Serializable.class.isAssignableFrom(type)) {
return 0;
}
long hash = 0L;
try {
ByteArrayOutputStream barr = new ByteArrayOutputStream(512);
MessageDigest md = MessageDigest.getInstance("SHA");
DigestOutputStream digestout = new DigestOutputStream(barr, md);
DataOutputStream out = new DataOutputStream(digestout);
Class superType = type.getSuperclass();
if (superType != null) {
TypeDescriptor desc = repo.getDescriptor(superType);
out.writeLong(desc.getHashCode());
}
if (_write_object_method == null)
out.writeInt(1);
else
out.writeInt(2);
FieldDescriptor[] fds = new FieldDescriptor[_fields.length];
System.arraycopy(_fields, 0, fds, 0, _fields.length);
if (fds.length > 1)
Arrays.sort(fds, compareByName);
for (FieldDescriptor f : fds) {
out.writeUTF(f.java_name);
out.writeUTF(makeSignature(f.getType()));
}
/*
* Field[] fields = type.getDeclaredFields (); if (fields.length >
* 1) java.util.Arrays.sort (fields, compareByName); for(int i = 0;
* i < fields.length; i++) { Field f = fields[i]; int mod =
* f.getModifiers (); if (!Modifier.isTransient(mod) &&
* !Modifier.isStatic (mod)) { out.writeUTF(f.getName());
* out.writeUTF( makeSignature (f.getType ())); } }
*/
out.flush();
byte[] data = md.digest();
int end = Math.min(8, data.length);
for (int j = 0; j < end; j++) {
hash += (long) (data[j] & 0xff) << (j * 8);
}
} catch (Exception ex) {
throw new RuntimeException("cannot compute RMI hash code", ex);
}
return hash;
}
private static final Comparator compareByName = new Comparator() {
public int compare(Object f1, Object f2) {
String n1 = ((FieldDescriptor) f1).java_name;
String n2 = ((FieldDescriptor) f2).java_name;
return n1.compareTo(n2);
}
};
long getHashCode() {
return _hash_code;
}
private volatile ValueMember[] valueMembers = null;
protected ValueMember[] genValueMembers() {
final ValueMember[] members = new ValueMember[_fields.length];
for (int i = 0; i < _fields.length; i++) {
members[i] = _fields[i].getValueMember(repo);
}
return members;
}
final ValueMember[] getValueMembers() {
getTypeCode(); // ensure recursion through typecode for non-array types
if (null == valueMembers) valueMembers = genValueMembers();
return valueMembers;
}
@Override
protected TypeCode genTypeCode() {
ORB orb = ORB.init();
setTypeCode(orb.create_recursive_tc(getRepositoryID()));
TypeCode _base = ((_super_descriptor == null) ? null : _super_descriptor.getTypeCode());
TypeCode tc;
if (type.isArray()) {
TypeDescriptor desc = repo.getDescriptor(type.getComponentType());
tc = desc.getTypeCode();
tc = orb.create_sequence_tc(0, tc);
tc = orb.create_value_box_tc(getRepositoryID(), "Sequence", tc);
} else {
tc = orb.create_value_tc(getRepositoryID(), type.getSimpleName(), VM_NONE.value, _base, getValueMembers());
}
return tc;
}
private static final OperationDescription[] ZERO_OPERATIONS = {};
private static final AttributeDescription[] ZERO_ATTRIBUTES = {};
private static final Initializer[] ZERO_INITIALIZERS = {};
private static final String[] ZERO_STRINGS = {};
FullValueDescription getFullValueDescription() {
FullValueDescription fvd = new FullValueDescription();
fvd.name = type.getName();
fvd.id = getRepositoryID();
fvd.is_abstract = false;
fvd.is_custom = isCustomMarshalled();
fvd.defined_in = "";
fvd.version = "1.0";
fvd.operations = ZERO_OPERATIONS;
fvd.attributes = ZERO_ATTRIBUTES;
fvd.members = getValueMembers();
fvd.initializers = ZERO_INITIALIZERS;
fvd.supported_interfaces = ZERO_STRINGS;
fvd.abstract_base_values = ZERO_STRINGS;
fvd.is_truncatable = false;
fvd.base_value = ((_super_descriptor == null) ? "" : _super_descriptor.getRepositoryID());
fvd.type = getTypeCode();
return fvd;
}
class ObjectDeserializer {
ObjectDeserializer super_descriptor;
String repository_id;
final FieldDescriptor[] fields;
ObjectDeserializer(ValueDescriptor desc) {
fields = desc._fields;
repository_id = desc.getRepositoryID();
if (desc._super_descriptor != null) {
super_descriptor = desc._super_descriptor._object_deserializer;
}
}
ObjectDeserializer(FullValueDescription desc, RunTime runtime) throws IOException {
Class myClass = type;
ValueMember[] members = desc.members;
fields = new FieldDescriptor[members.length];
for (int i = 0; i < members.length; i++) {
Class type = getClassFromTypeCode(members[i].type);
fields[i] = FieldDescriptor.get(myClass, type, members[i].name, null, repo);
}
if (!"".equals(desc.base_value)) {
Class clz = ValueHandlerImpl.getClassFromRepositoryID(desc.base_value);
TypeDescriptor tdesc = repo.getDescriptor(clz);
if ((tdesc instanceof ValueDescriptor)) {
super_descriptor = ((ValueDescriptor) tdesc).getObjectDeserializer(desc.base_value, runtime);
}
}
}
}
private ObjectDeserializer getObjectDeserializer(String repositoryID, RunTime runtime) throws IOException {
if (repositoryID.equals(getRepositoryID())) {
return _object_deserializer;
}
CodeBase codebase = CodeBaseHelper.narrow(runtime);
if (codebase == null) {
throw new IOException("cannot narrow RunTime -> CodeBase");
}
FullValueDescription desc = codebase.meta(repositoryID);
return new ObjectDeserializer(desc, codebase);
}
private static Class getClassFromTypeCode(TypeCode tc) {
return null;
}
public boolean copyWithinState() {
return !(_is_immutable_value | _is_rmi_stub);
}
Object copyObject(Object orig, CopyState state) {
if (_is_immutable_value || _is_rmi_stub) {
return orig;
}
Serializable oorig = (Serializable) orig;
logger.finer("copying " + orig);
oorig = writeReplace(oorig);
ValueDescriptor wdesc;
if (oorig == orig) {
wdesc = this;
} else {
wdesc = (ValueDescriptor) repo.getDescriptor(oorig.getClass());
logger.finer("writeReplace -> " + type.getName());
}
return wdesc.copyObject2(oorig, state);
}
/**
* this is called after write-replace on the type descriptor of the correct
* type for writing
*/
private Serializable copyObject2(Serializable oorig, CopyState state) {
// create instance of copied object, and register
Serializable copy = createBlankInstance();
state.put(oorig, copy);
// write original object
ObjectWriter writer = writeObject(oorig, state);
// read into copy
return readObject(writer, copy);
}
private ObjectWriter writeObject(Serializable oorig, CopyState state) {
try {
ObjectWriter writer = state.createObjectWriter(oorig);
writeValue(writer, oorig);
return writer;
} catch (IOException ex) {
String msg = String.format("%s writing %s", ex, type.getName());
throw (MARSHAL) new MARSHAL(msg).initCause(ex);
}
}
private Serializable readObject(ObjectWriter writer, Serializable copy) {
try {
ObjectReader reader = writer.getObjectReader(copy);
readValue(reader, copy);
return readResolve(copy);
} catch (IOException ex) {
String msg = String.format("%s reading instance of %s", ex, type.getName());
throw (MARSHAL) new MARSHAL(msg).initCause(ex);
}
}
void writeMarshalValue(PrintWriter pw, String outName, String paramName) {
pw.print(outName);
pw.print('.');
pw.print("write_value");
// this ValueDescriptor could represent an Abstract Value,
// in which case we need to cast the first argument.
// We'll just always do that, because most of the time
// HotSpot will remove this cast anyway.
pw.print("((java.io.Serializable)");
pw.print(paramName);
pw.print(',');
MethodDescriptor.writeJavaType(pw, type);
pw.print(".class)");
}
void writeUnmarshalValue(PrintWriter pw, String inName) {
pw.print(inName);
pw.print('.');
pw.print("read_value");
pw.print('(');
MethodDescriptor.writeJavaType(pw, type);
pw.print(".class)");
}
@Override
void addDependencies(Set<Class<?>> classes) {
Class c = type;
if ((c == Object.class) || classes.contains(c))
return;
classes.add(c);
if (c.getSuperclass() != null) {
TypeDescriptor desc = repo.getDescriptor(c.getSuperclass());
desc.addDependencies(classes);
}
Class[] ifaces = c.getInterfaces();
for (Class iface : ifaces) {
TypeDescriptor desc = repo.getDescriptor(iface);
desc.addDependencies(classes);
}
if (_fields != null) {
for (FieldDescriptor _field : _fields) {
if (_field.isPrimitive())
continue;
TypeDescriptor desc = repo.getDescriptor(_field.type);
desc.addDependencies(classes);
}
}
}
}