/**
 * 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;
    }

    protected ValueMember[] _value_members = null;

    private ValueMember[] getValueMembers() {
        getTypeCode(); // ensure recursion through typecode for non-array types

        if (_value_members == null) {
            _value_members = new ValueMember[_fields.length];
            for (int i = 0; i < _fields.length; i++) {
                _value_members[i] = _fields[i].getValueMember(repo);
            }
        }

        return _value_members;
    }

    @Override
    protected TypeCode genTypeCode() {
        ORB orb = ORB.init();
        TypeCode typeCode = orb.create_recursive_tc(getRepositoryID());

        TypeCode _base = ((_super_descriptor == null) ? null : _super_descriptor.getTypeCode());

        Class javaClass = type;
        if (javaClass.isArray()) {
            TypeDescriptor desc = repo.getDescriptor(javaClass.getComponentType());
            typeCode = desc.getTypeCode();
            typeCode = orb.create_sequence_tc(0, typeCode);
            typeCode = orb.create_value_box_tc(getRepositoryID(), "Sequence", typeCode);
        } else {
            typeCode = orb.create_value_tc(getRepositoryID(), javaClass.getSimpleName(), VM_NONE.value, _base, getValueMembers());
        }

        return typeCode;
    }

    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);
            }
        }
    }
}
