/**
 *
 * 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
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  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 java.io.Externalizable;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.rmi.AccessException;
import java.rmi.MarshalException;
import java.rmi.NoSuchObjectException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.ServerError;
import java.rmi.ServerException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.rmi.PortableRemoteObject;
import javax.rmi.CORBA.Stub;
import javax.rmi.CORBA.Tie;
import javax.rmi.CORBA.Util;
import javax.rmi.CORBA.UtilDelegate;
import javax.rmi.CORBA.ValueHandler;

import org.apache.yoko.rmi.util.GetSystemPropertyAction;
import org.apache.yoko.osgi.ProviderLocator;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.COMM_FAILURE;
import org.omg.CORBA.INVALID_TRANSACTION;
import org.omg.CORBA.INV_OBJREF;
import org.omg.CORBA.MARSHAL;
import org.omg.CORBA.NO_IMPLEMENT;
import org.omg.CORBA.NO_PERMISSION;
import org.omg.CORBA.OBJECT_NOT_EXIST;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.TCKind;
import org.omg.CORBA.TRANSACTION_REQUIRED;
import org.omg.CORBA.TRANSACTION_ROLLEDBACK;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.portable.IDLEntity;
import org.omg.CORBA.portable.UnknownException;

public class UtilImpl implements UtilDelegate {
    private static final Logger logger = Logger.getLogger(UtilImpl.class.getName());

    // Note: this field must be declared before the static intializer that calls Util.loadClass
    // since that method will call loadClass0 which uses this field... if it is below the static
    // initializer the _secman field will be null
    private static final SecMan _secman = getSecMan();

    private static final ClassLoader BEST_GUESS_AT_EXTENSION_CLASS_LOADER;
    static {
        ClassLoader candidateLoader = getClassLoader(UtilImpl.class);

        if (candidateLoader == null) {
            // looks like this class was loaded by the boot class loader
            // so it is safe to try loading stuff by reflection without
            // worrying about whether we have imported the packages into the OSGi bundle
            candidateLoader = findFirstNonNullLoader(
                    "sun.net.spi.nameservice.dns.DNSNameService",
                    "javax.transaction.UserTransaction");
        }

        // We will try to find the extension class
        // loader by ascending the loader hierarchy 
        // starting from whatever loader we found.
        for (ClassLoader l = candidateLoader; l != null; l = l.getParent()) {
            candidateLoader = l;
        }
        
        BEST_GUESS_AT_EXTENSION_CLASS_LOADER = candidateLoader;
    }

    private static ClassLoader findFirstNonNullLoader(String...classNames) {
        for (String className : classNames) {
            try {
                final Class<?> c = Class.forName(className);
                ClassLoader cl = getClassLoader(c);
                if (cl != null) return cl;
            } catch (Exception|NoClassDefFoundError swallowed) {
            }
        }
        return null;
    }

    /**
     * Translate a CORBA SystemException to the corresponding RemoteException
     */
    public RemoteException mapSystemException(final SystemException theException) {

        SystemException ex = theException;

        if (ex instanceof UnknownException) {
            Throwable orig = ((UnknownException) ex).originalEx;
            if (orig instanceof Error) {
                return new ServerError("Error occurred in server thread",
                        (Error) orig);
            } else if (orig instanceof RemoteException) {
                return new ServerException(
                        "RemoteException occurred in server thread",
                        (Exception) orig);
            } else if (orig instanceof RuntimeException) {
                throw (RuntimeException) orig;
            }
        }

        Class<? extends SystemException> exclass = ex.getClass();
        String name = exclass.getName();

         // construct the exception message according to �1.4.8

        StringBuffer buf = new StringBuffer("CORBA ");

        final String prefix = "org.omg.CORBA";
        if (name.startsWith(prefix)) {
            buf.append(name.substring(prefix.length() + 1));
        } else {
            buf.append(name);
        }

        buf.append(" ");
        buf.append(ex.minor);

        switch (ex.completed.value()) {
            case org.omg.CORBA.CompletionStatus._COMPLETED_YES:
                buf.append(" Yes");
                break;

            case org.omg.CORBA.CompletionStatus._COMPLETED_NO:
                buf.append(" No");
                break;

            case org.omg.CORBA.CompletionStatus._COMPLETED_MAYBE:
                buf.append(" Maybe");
                break;
        }

        String exceptionMessage = buf.toString();

        return createRemoteException(ex, exceptionMessage);
    }

    private RemoteException createRemoteException(SystemException sysEx, String s) {
        RemoteException result;
        try {
            throw sysEx;
        } catch (BAD_PARAM|COMM_FAILURE|MARSHAL e) {
            result = new MarshalException(s);
        } catch (INV_OBJREF|NO_IMPLEMENT|OBJECT_NOT_EXIST e) {
            result = new NoSuchObjectException(s);
        } catch(NO_PERMISSION e) {
            result = new AccessException(s);
        } catch (TRANSACTION_REQUIRED e) {
            result = createRemoteException("javax.transaction.TransactionRequiredException", s);
        } catch (TRANSACTION_ROLLEDBACK e) {
            result = createRemoteException("javax.transaction.TransactionRolledbackException", s);
        } catch (INVALID_TRANSACTION e) {
            result = createRemoteException("javax.transaction.InvalidTransactionException", s);
        } catch (SystemException catchAll) {
            result = new RemoteException(s);
        }
        result.detail = sysEx;
        return result;
    }
    
    private static RemoteException createRemoteException(String className, String s) {
        RemoteException result;
        try {
            @SuppressWarnings("unchecked")
            Class<? extends RemoteException> clazz =  Util.loadClass(className, null, null);
            Constructor<? extends RemoteException> ctor = clazz.getConstructor(String.class);
            result = ctor.newInstance(s);
        } catch (Throwable t) {
            result = new RemoteException(s);
            result.addSuppressed(t);
        }
        return result;
    }

    static SystemException mapRemoteException(RemoteException rex) {
        if (rex.detail instanceof org.omg.CORBA.SystemException)
            return (org.omg.CORBA.SystemException) rex.detail;

        if (rex.detail instanceof RemoteException)
            rex = (RemoteException) rex.detail;
        
        SystemException sysEx;

        if (rex instanceof java.rmi.NoSuchObjectException) {
            sysEx = new org.omg.CORBA.INV_OBJREF(rex.getMessage());
        } else if (rex instanceof java.rmi.AccessException) {
            sysEx = new org.omg.CORBA.NO_PERMISSION(rex.getMessage());
        } else if (rex instanceof java.rmi.MarshalException) {
            sysEx = new org.omg.CORBA.MARSHAL(rex.getMessage());
        } else {
            sysEx = createSystemException(rex);
        }
        sysEx.initCause(rex);
        throw sysEx;
    }
    
    private static SystemException createSystemException(RemoteException rex) {
        return createSystemException(rex, rex.getClass());
    }
    
    /**
     * utility method to check for JTA exception types without linking to the JTA classes directly
     */
    private static SystemException createSystemException(RemoteException rex, Class<?> fromClass) {
        // Recurse up the parent chain,
        // until we reach a known JTA type. 
        switch(fromClass.getName()) {
            // Of course, we place some known elephants in Cairo.
            case "java.lang.Object":
            case "java.lang.Throwable":
            case "java.lang.Exception":
            case "java.lang.RuntimeException":
            case "java.lang.Error":
            case "java.io.IOException":
            case "java.rmi.RemoteException":
                return new UnknownException(rex);
            case "javax.transaction.InvalidTransactionException":
                return new INVALID_TRANSACTION(rex.getMessage());
            case "javax.transaction.TransactionRolledbackException":
                return new TRANSACTION_ROLLEDBACK(rex.getMessage());
            case "javax.transaction.TransactionRequiredException":
                return new TRANSACTION_REQUIRED(rex.getMessage());
        }
        return createSystemException(rex, fromClass.getSuperclass());
    }

    /**
     * Write an org.omg.CORBA.Any containing the given object.
     * <p/>
     * The object is not converted or translated, simply written. Thus, it must
     * be either an IDL-generated entity, a Serializable value or an
     * org.omg.CORBA.Object. Specifically, a Remote objects and Servants cannot
     * be written, but their corresponding Stubs can.
     *
     * @param out The stream to which the value should be written
     * @param obj The object/value to write
     * @throws org.omg.CORBA.MARSHAL if the value cannot be written
     */
    public void writeAny(org.omg.CORBA.portable.OutputStream out, Object obj)
            throws org.omg.CORBA.SystemException {
        //
        // In this implementation of RMI/IIOP we do not use type codes
        // beyond the implementation of this method, and it's
        // counterpart readAny.
        //

        org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
        Any any = orb.create_any();

        if (obj == null) {
            // JDK 1.3.1-1 doesn't like NULL typecodes, so
            // we write it as a null Value.

            any.insert_Value(null);

        } else if (obj instanceof String) {
            any.insert_Value((String) obj);

        } else if (obj instanceof org.omg.CORBA.Object) {
            any.insert_Object((org.omg.CORBA.Object) obj);

        } else if (obj instanceof Any) {
            any.insert_any((Any) obj);

        } else if (obj instanceof IDLEntity) {
            any.insert_Value((Serializable) obj);

        } else if (obj instanceof java.rmi.Remote) {
            Remote ro = (Remote) obj;
            org.omg.CORBA.Object corba_obj;
            try {
                corba_obj = (org.omg.CORBA.Object) PortableRemoteObject
                        .toStub(ro);
            } catch (java.rmi.NoSuchObjectException ex) {
                throw (org.omg.CORBA.MARSHAL) new org.omg.CORBA.MARSHAL(
                        "object not exported " + ro).initCause(ex);
            }

            any.insert_Object((org.omg.CORBA.Object) corba_obj);

        } else if (obj instanceof Serializable || obj instanceof Externalizable) {

            any.insert_Value((Serializable) obj);

        } else {
            throw new MARSHAL("cannot write as " + obj.getClass()
                    + " to an Any");
        }

        out.write_any(any);
    }

    public Object readAny(org.omg.CORBA.portable.InputStream in)
            throws org.omg.CORBA.SystemException {
        Any any = in.read_any();
        TypeCode typecode = any.type();

        switch (typecode.kind().value()) {

            case TCKind._tk_null:
            case TCKind._tk_void:
                return null;

            case TCKind._tk_value:
            case TCKind._tk_value_box:
                return any.extract_Value();

            case TCKind._tk_abstract_interface:
                org.omg.CORBA_2_3.portable.InputStream in23 = (org.omg.CORBA_2_3.portable.InputStream) any
                .create_input_stream();
                return in23.read_abstract_interface();

            case TCKind._tk_string:
                return any.extract_string();

            case TCKind._tk_objref:
                org.omg.CORBA.Object ref = any.extract_Object();
                return ref;

            case TCKind._tk_any:
                return any.extract_any();

            default:
                String id = "<unknown>";
                try {
                    id = typecode.id();
                } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
                }

                throw new MARSHAL("cannot extract " + id + " ("
                        + typecode.kind().value() + ") value from Any");
        }
    }

    /**
     * Write a remote object. It must already be exported.
     * <p/>
     * This method accepts values of org.omg.CORBA.Object (including stubs), and
     * instances of java.rmi.Remote for objects that have already been exported.
     */
    public void writeRemoteObject(org.omg.CORBA.portable.OutputStream out,
            Object obj) throws org.omg.CORBA.SystemException {
        org.omg.CORBA.Object objref = null;

        if (obj == null) {
            out.write_Object(null);
            return;

        } else if (obj instanceof org.omg.CORBA.Object) {
            objref = (org.omg.CORBA.Object) obj;

        } else if (obj instanceof Remote) {
            try {
                objref = (javax.rmi.CORBA.Stub) PortableRemoteObject
                        .toStub((java.rmi.Remote) obj);

            } catch (java.rmi.NoSuchObjectException ex) {
            }

            if (objref == null) {

                try {
                    PortableRemoteObject.exportObject((java.rmi.Remote) obj);
                    objref = (javax.rmi.CORBA.Stub) PortableRemoteObject
                            .toStub((java.rmi.Remote) obj);
                } catch (java.rmi.RemoteException ex) {
                    throw (MARSHAL) new MARSHAL("cannot convert Remote to Object").initCause(ex);
                }
            }

        } else {
            throw new MARSHAL(
                    "object is neither Remote nor org.omg.CORBA.Object: "
                            + obj.getClass().getName());
        }

        out.write_Object(objref);
    }

    public void writeAbstractObject(org.omg.CORBA.portable.OutputStream out, Object obj) {
        logger.finer("writeAbstractObject.1 " + " out=" + out);

        if (obj instanceof org.omg.CORBA.Object || obj instanceof Serializable) {

            // skip //

        } else if (obj instanceof Remote) {
            org.omg.CORBA.Object objref = null;

            try {
                objref = (org.omg.CORBA.Object) PortableRemoteObject
                        .toStub((Remote) obj);

            } catch (java.rmi.NoSuchObjectException ex) {
            }

            if (objref == null) {
                try {
                    PortableRemoteObject.exportObject((Remote) obj);
                    objref = (org.omg.CORBA.Object) PortableRemoteObject
                            .toStub((Remote) obj);
                } catch (RemoteException ex) {
                    throw (MARSHAL) new MARSHAL("unable to export object").initCause(ex);
                }
            }
            obj = objref;
        }

        org.omg.CORBA_2_3.portable.OutputStream out_ = (org.omg.CORBA_2_3.portable.OutputStream) out;

        logger.finer("writeAbstractObject.2 " + " out=" + out);

        out_.write_abstract_interface(obj);
    }

    @SuppressWarnings("unchecked")
    protected java.util.Map<Remote, Tie> tie_map() {
        return RMIState.current().tie_map;
    }

    public void registerTarget(Tie tie, Remote obj) {
        if (obj == null)
            throw new IllegalArgumentException("remote object is null");

        tie.setTarget(obj);
        tie_map().put(obj, tie);

        // log.info("exported instance of "+obj.getClass()+" in
        // "+RMIState.current().getName());
    }

    public Tie getTie(Remote obj) {
        if (obj == null)
            return null;

        return tie_map().get(obj);
    }

    public ValueHandler createValueHandler() {
        return RMIState.current().createValueHandler();
        // return new ValueHandlerImpl (null);
    }

    public String getCodebase(@SuppressWarnings("rawtypes") Class clz) {
        if (clz == null)
            return null;

        if (clz.isArray())
            return getCodebase(clz.getComponentType());

        if (clz.isPrimitive())
            return null;

        ClassLoader theLoader = clz.getClassLoader();

        // ignore system classes
        if (theLoader == null)
            return null;

        // ignore J2SE base class loader
        if (theLoader == (Object.class).getClassLoader())
            return null;

        // ignore standard extensions
        if (theLoader == BEST_GUESS_AT_EXTENSION_CLASS_LOADER)
            return null;

        RMIState state = RMIState.current();
        ClassLoader stateLoader = state.getClassLoader();

        try {
            // is the class loaded with the stateLoader?
            if (clz.equals(stateLoader.loadClass(clz.getName()))) {
                java.net.URL codebaseURL = state.getCodeBase();

                if (codebaseURL != null) {
                    logger.finer("class " + clz.getName() + " => "
                            + codebaseURL);

                    // System.out.println ("class "+clz.getName()+" =>
                    // "+codebaseURL);
                    return codebaseURL.toString();
                }
            }
        } catch (ClassNotFoundException ex) {
            // ignore
        }

        return AccessController.doPrivileged(new GetSystemPropertyAction("java.rmi.server.codebase"));
    }

    static class SecMan extends java.rmi.RMISecurityManager {
        @SuppressWarnings("rawtypes")
        public Class[] getClassContext() {
            return super.getClassContext();
        }
    }

    private static SecMan getSecMan() {
        try {
            return AccessController.doPrivileged(new PrivilegedExceptionAction<SecMan>() {
                public SecMan run() {
                    return new SecMan();
                }
            });
        } catch (PrivilegedActionException e) {
            throw new RuntimeException(e);
        }

    }

    @SuppressWarnings("rawtypes")
    public Class loadClass(String name, String codebase, ClassLoader loader)
            throws ClassNotFoundException {
        try {
            return loadClass0(name, codebase, loader);
        } catch (ClassNotFoundException ex) {
            logger.log(Level.FINER, "cannot load from " + codebase + " " +
                    ex.getMessage(), ex);
            throw ex;
        }
    }

    static public Class<?> loadClass0(String name, String codebase, ClassLoader loader)
            throws ClassNotFoundException {

        try {
            return ProviderLocator.loadClass(name, null, loader);
        } catch (ClassNotFoundException e) {
            //skip
        }
        Class<?> result = null;

        ClassLoader stackLoader = null;
        ClassLoader thisLoader = Util.class.getClassLoader();
        Class<?>[] stack = _secman.getClassContext();
        for (int i = 1; i < stack.length; i++) {
            ClassLoader testLoader = stack[i].getClassLoader();
            if (testLoader != null && testLoader != thisLoader) {
                stackLoader = thisLoader;
                break;
            }
        }

        if (stackLoader != null) {
            try {
                result = stackLoader.loadClass(name);
            } catch (ClassNotFoundException ex) {
                // skip //
            }

            if (result != null) {
                return result;
            }
        }

        // try loading using our loader, just in case we really were loaded
        // using the same classloader the delegate is in.
        if (thisLoader != null) {
            try {
                result = thisLoader.loadClass(name);
            } catch (ClassNotFoundException ex) {
                // skip //
            }

            if (result != null) {
                return result;
            }
        }

        if (codebase != null && !"".equals(codebase)
                && !Boolean.getBoolean("java.rmi.server.useCodeBaseOnly")) {
            logger.finer("trying RMIClassLoader");
            try (URLClassLoader url_loader = new URLClassLoader(new URL[]{new URL(codebase)}, loader)) {
                result = url_loader.loadClass(name);
            } catch (ClassNotFoundException ex) {
                logger.log(Level.FINER, "RMIClassLoader says " + ex.getMessage(), ex);
            } catch (MalformedURLException ex) {
                logger.log(Level.FINER, "RMIClassLoader says " + ex.getMessage(), ex);
                logger.finer("FAILED class download " + name + " from " + codebase + " " + ex.getMessage());
            } catch (RuntimeException ex) {
                logger.log(Level.FINER, "FAILED class download " + name + " from " + codebase + " " + ex.getMessage(), ex);
            } catch (IOException unimportant) {
            }

            if (result != null) {
                return result;
            }

        } else {

            codebase = (String) AccessController.doPrivileged(new GetSystemPropertyAction("java.rmi.server.codebase"));

            if (codebase != null) {
                try {
                    result = java.rmi.server.RMIClassLoader.loadClass(codebase,
                            name);
                } catch (ClassNotFoundException ex) {
                    // skip //
                } catch (MalformedURLException ex) {
                    // skip //
                }

                if (result != null) {
                    return result;
                }
            }
        }

        if (loader == null) {
            loader = getContextClassLoader();
        }

        try {
            result = loader.loadClass(name);
        } catch (ClassNotFoundException ex) {
            logger.log(Level.FINER, "LocalLoader says " + ex.getMessage(), ex);
        }

        if (result != null) {
            return result;
        }

        throw new ClassNotFoundException(name);
    }

    public boolean isLocal(Stub stub) throws RemoteException {
        try {
            if (stub instanceof RMIStub) {
                return true;
            } else {
                return stub._is_local();
            }
        } catch (org.omg.CORBA.SystemException ex) {
            throw mapSystemException(ex);
        }
    }

    public RemoteException wrapException(Throwable ex) {
        if (ex instanceof Error) {
            return new java.rmi.ServerError(ex.getMessage(), (Error) ex);

        } else if (ex instanceof RemoteException) {
            return new java.rmi.ServerException(ex.getMessage(), (Exception) ex);

        } else if (ex instanceof org.omg.CORBA.portable.UnknownException) {
            org.omg.CORBA.portable.UnknownException uex = (org.omg.CORBA.portable.UnknownException) ex;

            return new java.rmi.ServerError(
                    ex.getMessage(),
                    (uex.originalEx instanceof Error ? (Error) uex.originalEx
                            : new Error("[OTHER EXCEPTION] " + ex.getMessage())));

        } else if (ex instanceof org.omg.CORBA.SystemException) {
            return mapSystemException((org.omg.CORBA.SystemException) ex);

        } else if (ex instanceof RuntimeException) {
            throw (RuntimeException) ex;

        } else {
            return new java.rmi.RemoteException(ex.getMessage(), ex);
        }
    }

    static ClassLoader getContextClassLoader() {
        return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
            public ClassLoader run() {
                return Thread.currentThread().getContextClassLoader();
            }
        });
    }

    static ClassLoader getClassLoader(final Class<?> clz) {
        if (System.getSecurityManager() == null) {
            return clz.getClassLoader();
        } else {
            return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
                public ClassLoader run() {
                    return clz.getClassLoader();
                }
            });
        }
    }

    static Object copyRMIStub(RMIStub stub) throws RemoteException {
        ClassLoader loader = getContextClassLoader();

        if (getClassLoader(stub._descriptor.type) == loader) {
            return stub;
        }

        RemoteDescriptor desc = stub._descriptor;

        Class<?> targetClass;

        try {
            targetClass = Util.loadClass(desc.type.getName(), stub
                    ._get_codebase(), loader);
        } catch (ClassNotFoundException ex) {
            logger.log(Level.FINER, "copyRMIStub exception (current loader is: " + loader
                    + ") " + ex.getMessage(), ex);
            throw new RemoteException("Class not found", ex);
        }

        return PortableRemoteObjectImpl.narrow1(RMIState.current(), stub,
                targetClass);
    }

    static boolean copy_with_corba = false;

    /**
     * Copy a single object, maintaining internal reference integrity.
     * <p/>
     * This is done by writing and reading the object to/from a temporary
     * stream. As such, this should be called after the receiving context's
     * class-loaders etc. have been set up.
     */
    public Object copyObject(Object obj, org.omg.CORBA.ORB orb)
            throws RemoteException {
        if (obj == null)
            return null;

        if (orb == null)
            throw new NullPointerException();

        if (obj instanceof String || obj instanceof Number)
            return obj;

        if (obj instanceof RMIStub) {
            return copyRMIStub((RMIStub) obj);
        }

        /*
         * try { org.omg.CORBA_2_3.portable.OutputStream out =
         * (org.omg.CORBA_2_3.portable.OutputStream) orb.create_output_stream
         * ();
         *
         * out.write_value ((java.io.Serializable) obj);
         *
         * org.omg.CORBA_2_3.portable.InputStream in =
         * (org.omg.CORBA_2_3.portable.InputStream) out.create_input_stream ();
         *
         * return in.read_value ();
         *  } catch (org.omg.CORBA.SystemException ex) { throw
         * mapSystemException (ex); }
         */
        try {
            TypeRepository rep = RMIState.current().getTypeRepository();
            CopyState state = new CopyState(rep);
            return state.copy(obj);
        } catch (CopyRecursionException ex) {
            throw new MarshalException("unable to resolve recursion", ex);
        } catch (org.omg.CORBA.SystemException ex) {
            throw mapSystemException(ex);
        }

    }

    static final Object READ_SERIALIZABLE_KEY = new Object();

    /**
     * Copy an array of objects, maintaining internal reference integrity.
     * <p/>
     * This is done by writing and reading the object array to/from a temporary
     * stream. As such, this should be called after the receiving context's
     * class-loaders etc. have been set up.
     */
    public Object[] copyObjects(Object[] objs, org.omg.CORBA.ORB orb)
            throws RemoteException {

        if (objs == null || orb == null)
            throw new NullPointerException();

        if (objs.length == 0)
            return objs;

        try {

            TypeRepository rep = RMIState.current().getTypeRepository();
            CopyState state = new CopyState(rep);
            try {
                return (Object[]) state.copy(objs);
            } catch (CopyRecursionException ex) {
                throw new MarshalException("unable to resolve recursion", ex);
            }

            /*
             * int length = objs.length;
             *
             * for (int i = 0; i < length; i++) {
             *
             * Object val = objs[i];
             *
             * if (val == null || val instanceof String || val instanceof
             * Number) { // do nothing, just leave the object in place //
             *  } else if (val instanceof RMIStub) { objs[i] =
             * copyRMIStub((RMIStub)val);
             *  } else { if (orb == null) { orb = RMIState.current().getORB(); }
             *
             * if (out == null) { out =
             * (org.omg.CORBA_2_3.portable.OutputStream) orb
             * .create_output_stream(); }
             *
             * out.write_value((java.io.Serializable) val); objs[i] =
             * READ_SERIALIZABLE_KEY; }
             *  }
             *
             * if (out != null) {
             *
             * org.omg.CORBA_2_3.portable.InputStream in =
             * (org.omg.CORBA_2_3.portable.InputStream) out
             * .create_input_stream();
             *
             * for (int i = 0; i < length; i++) { if (objs[i] ==
             * READ_SERIALIZABLE_KEY) { objs[i] = in.read_value(); } } }
             *
             * return objs;
             */

        } catch (org.omg.CORBA.SystemException ex) {
            throw mapSystemException(ex);
        }
    }

    public void unexportObject(Remote obj)
            throws java.rmi.NoSuchObjectException {
        if (obj == null)
            return;

        java.util.Map<Remote, Tie> tie_map = tie_map();

        if (tie_map == null)
            return;

        Tie tie = tie_map.remove(obj);

        if (tie == null) {
            logger.fine("unexporting unknown instance of "
                    + obj.getClass().getName() + " from "
                    + RMIState.current().getName());
            return;
        } else {
            logger.finer("unexporting instance of " + obj.getClass().getName()
                    + " from " + RMIState.current().getName());
        }

        tie.deactivate();
    }
}
