/**
*
* 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.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.logging.Logger;
import java.util.logging.Level;

import javax.rmi.CORBA.Stub;
import javax.rmi.CORBA.ValueHandler;

import org.apache.yoko.rmi.api.PortableRemoteObjectExt;
import org.apache.yoko.rmi.api.PortableRemoteObjectState;
import org.apache.yoko.rmi.util.NodeleteSynchronizedMap;
import org.omg.CORBA.BAD_INV_ORDER;
import org.omg.CORBA.Policy;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
import org.omg.PortableServer.POAPackage.AdapterAlreadyExists;
import org.omg.PortableServer.POAPackage.InvalidPolicy;


public class RMIState implements PortableRemoteObjectState {
    static final Logger logger = Logger.getLogger(RMIState.class.getName());

    private boolean isShutdown;

    final private org.omg.CORBA.ORB _orb;

    private String _name;

    final TypeRepository repo = TypeRepository.get();
    
    private POA poa;
    
    POA getPOA() {
	return poa;
    }

    RMIState(org.omg.CORBA.ORB orb, String name) {
        if (orb == null) {
            throw new NullPointerException("ORB is null");
        }
        
        try {
            POA rootPoa = (POA) orb.resolve_initial_references("RootPOA");
	    poa = rootPoa.create_POA(name, null, new Policy[0]);
	    poa.the_POAManager().activate();
	} catch (AdapterAlreadyExists e) {
        logger.log(Level.WARNING, "Adapter already exists", e);
	} catch (InvalidPolicy e) {
        logger.log(Level.WARNING, "Invalid policy", e);
	} catch (InvalidName e) {
        logger.log(Level.WARNING, "Invalid name", e);
	} catch (AdapterInactive e) {
        logger.log(Level.WARNING, "Adapter inactive", e);
	}

        _orb = orb;
        _name = name;
    }

    void checkShutDown() {
        if (isShutdown) {
            BAD_INV_ORDER ex = new BAD_INV_ORDER(
                    "RMIState has already been shut down");
            logger.fine("RMIState has already been shut down " + ex);
            throw ex;
        }
    }

    public void shutdown() {
        logger.finer("RMIState shutdown requested; name = " + _name);

        checkShutDown();

        isShutdown = true;
    }

    public org.omg.CORBA.ORB getORB() {
        return _orb;
    }


    org.omg.CORBA.portable.Delegate createDelegate(RMIServant servant) {
        checkShutDown();

        byte[] id = servant._id;
        RemoteDescriptor desc = servant._descriptor;

        String repid = desc.getRepositoryID();
        
        org.omg.CORBA.portable.ObjectImpl ref;
        org.omg.PortableServer.POA poa;

        try {
            poa = getPOA();
            ref = (org.omg.CORBA.portable.ObjectImpl) poa
                    .create_reference_with_id(id, repid);
        } catch (org.omg.CORBA.BAD_PARAM ex) {
            throw (InternalError)new InternalError("wrong policy: " + ex.getMessage()).initCause(ex);
        }

        return ref._get_delegate();
    }

    static RMIState current() {
        return (RMIState) PortableRemoteObjectExt.getState();
    }

    public ClassLoader getClassLoader() {
        ClassLoader loader  = Thread.currentThread().getContextClassLoader();
        return loader;
    }

    //
    // data for use in PortableRemoteObjectImpl
    //

    java.util.Map stub_map = new NodeleteSynchronizedMap() {
        public java.util.Map initialValue() {
            return new HashMap();
        }
    };

    //
    // data for use in UtilImpl
    //
    java.util.Map tie_map = java.util.Collections
            .synchronizedMap(new IdentityHashMap());

    private java.util.Map static_stub_map = new NodeleteSynchronizedMap() {
        public java.util.Map initialValue() {
            return new HashMap();
        }
    };

    private URL _codebase;

    //
    //
    //
    public void setCodeBase(URL codebase) {
        _codebase = codebase;
    }

    public URL getCodeBase() {
        return _codebase;
    }

    void clearState() {
        stub_map = null;
        tie_map = null;

        static_stub_map = null;
    }

    static class StaticStubEntry {
        java.lang.reflect.Constructor stub_constructor;
    }

    /**
     * Method getStaticStub.
     * 
     * @param codebase
     * @param type
     * @return Stub
     */
    public Stub getStaticStub1(String codebase, Class type) {
        return null;
    }

    public Stub getStaticStub(String codebase, Class type) {

        StaticStubEntry ent = (StaticStubEntry) static_stub_map.get(type);
        if (ent == null) {
            ent = new StaticStubEntry();

            java.lang.reflect.Constructor cons = findConstructor(codebase,
                    getNewStubClassName(type));

            if (cons != null
                    && !javax.rmi.CORBA.Stub.class.isAssignableFrom(cons
                            .getDeclaringClass())) {
                logger.fine("class " + cons.getDeclaringClass()
                        + " is not a javax.rmi.CORBA.Stub");
                cons = null;
            }

            if (cons == null) {
                cons = findConstructor(codebase, getOldStubClassName(type));
            }

            if (cons != null
                    && !javax.rmi.CORBA.Stub.class.isAssignableFrom(cons
                            .getDeclaringClass())) {
                logger.fine("class " + cons.getDeclaringClass()
                        + " is not a javax.rmi.CORBA.Stub");
                cons = null;
            }

            ent.stub_constructor = cons;

            static_stub_map.put(type, ent);
        }

        if (ent.stub_constructor == null) {
            return null;
        }

        try {
            return (Stub) ent.stub_constructor
                    .newInstance(PortableRemoteObjectImpl.NO_ARG);
        } catch (ClassCastException ex) {
            logger.log(Level.FINE, "loaded class "
                    + ent.stub_constructor.getDeclaringClass()
                    + " is not a proper stub", ex);
        } catch (IllegalAccessException ex) {
            logger.log(Level.FINE, "cannot instantiate stub class for " + type + " :: "
                    + ex.getMessage(), ex);
        } catch (InstantiationException ex) {
            logger.log(Level.FINE, "cannot instantiate stub class for " + type + " :: "
                    + ex.getMessage(), ex);
        } catch (InvocationTargetException ex) {
            logger.log(Level.FINE, "cannot instantiate stub class for " + type + " :: "
                    + ex.getCause(), ex.getCause());
        }

        return null;
    }

    private java.lang.reflect.Constructor findConstructor(String codebase,
            String stubName) {
        try {
            Class stubClass = javax.rmi.CORBA.Util.loadClass(stubName,
                    codebase, getClassLoader());
            return stubClass.getConstructor(new Class[0]);

        } catch (NoSuchMethodException ex) {
            logger.log(Level.WARNING, "stub class " + stubName
                    + " has no default constructor", ex);

        } catch (ClassNotFoundException ex) {
            logger.log(Level.FINE, "failed to load remote class " + stubName + " from "
                    + codebase, ex);
            // ignore //
        }

        return null;
    }

    String getNewStubClassName(Class c) {

        String cname = c.getName();

        String pkgname = null;
        int idx = cname.lastIndexOf('.');

        if (idx == -1) {
            pkgname = "org.omg.stub";
        } else {
            pkgname = "org.omg.stub." + cname.substring(0, idx);
        }

        String cplain = cname.substring(idx + 1);

        return pkgname + "." + "_" + cplain + "_Stub";
    }

    String getOldStubClassName(Class c) {

        String cname = c.getName();

        //String pkgname = null;
        int idx = cname.lastIndexOf('.');

        if (idx == -1) {
            return "_" + cname + "_Stub";
        } else {
            return cname.substring(0, idx + 1) + "_" + cname.substring(idx + 1)
                    + "_Stub";
        }
    }

    public void exportObject(Remote remote) throws RemoteException {
        //PortableRemoteObjectExt.pushState(this);
        try {
            javax.rmi.PortableRemoteObject.exportObject(remote);
        } finally {
            //PortableRemoteObjectExt.popState();
        }
    }

    public void unexportObject(Remote remote) throws RemoteException {
        //PortableRemoteObjectExt.pushState(this);
        try {
            javax.rmi.PortableRemoteObject.unexportObject(remote);
        } finally {
            //PortableRemoteObjectExt.popState();
        }
    }

    public String getName() {
        return _name;
    }
}
