/*
 * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.corba.se.spi.orb;

import java.util.Map ;
import java.util.HashMap ;
import java.util.Properties ;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger ;

import java.security.AccessController ;
import java.security.PrivilegedAction ;

import org.omg.CORBA.TCKind ;

import com.sun.corba.se.pept.broker.Broker ;
import com.sun.corba.se.pept.transport.ByteBufferPool;

import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry ;
import com.sun.corba.se.spi.protocol.ClientDelegateFactory ;
import com.sun.corba.se.spi.protocol.CorbaServerRequestDispatcher ;
import com.sun.corba.se.spi.protocol.CorbaMessageMediator ;
import com.sun.corba.se.spi.protocol.PIHandler ;
import com.sun.corba.se.spi.resolver.LocalResolver ;
import com.sun.corba.se.spi.resolver.Resolver ;
import com.sun.corba.se.spi.transport.CorbaContactInfoListFactory ;
import com.sun.corba.se.spi.legacy.connection.LegacyServerSocketEndPointInfo;
import com.sun.corba.se.spi.legacy.connection.LegacyServerSocketManager;
import com.sun.corba.se.spi.monitoring.MonitoringConstants;
import com.sun.corba.se.spi.monitoring.MonitoringManager;
import com.sun.corba.se.spi.monitoring.MonitoringManagerFactory;
import com.sun.corba.se.spi.monitoring.MonitoringFactories;

import com.sun.corba.se.spi.ior.IdentifiableFactoryFinder ;
import com.sun.corba.se.spi.ior.TaggedComponentFactoryFinder ;
import com.sun.corba.se.spi.ior.ObjectKey ;
import com.sun.corba.se.spi.ior.ObjectKeyFactory ;
import com.sun.corba.se.spi.ior.IOR ;

import com.sun.corba.se.spi.orbutil.closure.Closure ;

import com.sun.corba.se.spi.orb.Operation ;
import com.sun.corba.se.spi.orb.ORBData ;
import com.sun.corba.se.spi.orb.ORBVersion ;
import com.sun.corba.se.spi.orbutil.threadpool.ThreadPoolManager;

import com.sun.corba.se.spi.oa.OAInvocationInfo ;
import com.sun.corba.se.spi.transport.CorbaTransportManager;

import com.sun.corba.se.spi.logging.LogWrapperFactory ;
import com.sun.corba.se.spi.logging.LogWrapperBase ;
import com.sun.corba.se.spi.logging.CORBALogDomains ;

import com.sun.corba.se.spi.copyobject.CopierManager ;

import com.sun.corba.se.spi.presentation.rmi.PresentationManager ;
import com.sun.corba.se.spi.presentation.rmi.PresentationDefaults ;

import com.sun.corba.se.spi.servicecontext.ServiceContextRegistry ;

// XXX needs an SPI or else it does not belong here
import com.sun.corba.se.impl.corba.TypeCodeImpl ;
import com.sun.corba.se.impl.corba.TypeCodeFactory ;

// XXX Should there be a SPI level constants ?
import com.sun.corba.se.impl.orbutil.ORBConstants ;

import com.sun.corba.se.impl.oa.poa.BadServerIdHandler ;

import com.sun.corba.se.impl.transport.ByteBufferPoolImpl;

import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
import com.sun.corba.se.impl.logging.OMGSystemException ;

import com.sun.corba.se.impl.presentation.rmi.PresentationManagerImpl ;

import sun.awt.AppContext;
import sun.corba.SharedSecrets;

public abstract class ORB extends com.sun.corba.se.org.omg.CORBA.ORB
    implements Broker, TypeCodeFactory
{
    // As much as possible, this class should be stateless.  However,
    // there are a few reasons why it is not:
    //
    // 1. The ORB debug flags are defined here because they are accessed
    //    frequently, and we do not want a cast to the impl just for that.
    // 2. typeCodeMap and primitiveTypeCodeConstants are here because they
    //    are needed in both ORBImpl and ORBSingleton.
    // 3. Logging support is here so that we can avoid problems with
    //    incompletely initialized ORBs that need to perform logging.

    // Flag set at compile time to debug flag processing: this can't
    // be one of the xxxDebugFlags because it is used to debug the mechanism
    // that sets the xxxDebugFlags!
    public static boolean ORBInitDebug = false;

    // Currently defined debug flags.  Any additions must be called xxxDebugFlag.
    // All debug flags must be public boolean types.
    // These are set by passing the flag -ORBDebug x,y,z in the ORB init args.
    // Note that x,y,z must not contain spaces.
    public boolean transportDebugFlag = false ;
    public boolean subcontractDebugFlag = false ;
    public boolean poaDebugFlag = false ;
    public boolean poaConcurrencyDebugFlag = false ;
    public boolean poaFSMDebugFlag = false ;
    public boolean orbdDebugFlag = false ;
    public boolean namingDebugFlag = false ;
    public boolean serviceContextDebugFlag = false ;
    public boolean transientObjectManagerDebugFlag = false ;
    public boolean giopVersionDebugFlag = false;
    public boolean shutdownDebugFlag = false;
    public boolean giopDebugFlag = false;
    public boolean invocationTimingDebugFlag = false ;

    // SystemException log wrappers.  Protected so that they can be used in
    // subclasses.
    protected static ORBUtilSystemException staticWrapper ;
    protected ORBUtilSystemException wrapper ;
    protected OMGSystemException omgWrapper ;

    // This map is needed for resolving recursive type code placeholders
    // based on the unique repository id.
    // XXX Should this be a WeakHashMap for GC?
    private Map typeCodeMap ;

    private TypeCodeImpl[] primitiveTypeCodeConstants ;

    // ByteBufferPool - needed by both ORBImpl and ORBSingleton
    ByteBufferPool byteBufferPool;

    // Local testing
    // XXX clean this up, probably remove these
    public abstract boolean isLocalHost( String hostName ) ;
    public abstract boolean isLocalServerId( int subcontractId, int serverId ) ;

    // Invocation stack manipulation
    public abstract OAInvocationInfo peekInvocationInfo() ;
    public abstract void pushInvocationInfo( OAInvocationInfo info ) ;
    public abstract OAInvocationInfo popInvocationInfo() ;

    public abstract CorbaTransportManager getCorbaTransportManager();
    public abstract LegacyServerSocketManager getLegacyServerSocketManager();

    // wrapperMap maintains a table of LogWrapper instances used by
    // different classes to log exceptions.  The key is a StringPair
    // representing LogDomain and ExceptionGroup.
    private Map wrapperMap ;

    static class Holder {
        static final PresentationManager defaultPresentationManager =
            setupPresentationManager();
    }
    private static final Object pmLock = new Object();

    private static Map staticWrapperMap = new ConcurrentHashMap();

    protected MonitoringManager monitoringManager;

    private static PresentationManager setupPresentationManager() {
        staticWrapper = ORBUtilSystemException.get(
            CORBALogDomains.RPC_PRESENTATION ) ;

        boolean useDynamicStub =
            ((Boolean)AccessController.doPrivileged(
                new PrivilegedAction() {
                    public java.lang.Object run() {
                        return Boolean.valueOf( Boolean.getBoolean (
                            ORBConstants.USE_DYNAMIC_STUB_PROPERTY ) ) ;
                    }
                }
            )).booleanValue() ;

        PresentationManager.StubFactoryFactory dynamicStubFactoryFactory =
            (PresentationManager.StubFactoryFactory)AccessController.doPrivileged(
                new PrivilegedAction() {
                    public java.lang.Object run() {
                        PresentationManager.StubFactoryFactory sff =
                            PresentationDefaults.getProxyStubFactoryFactory() ;

                        String className = System.getProperty(
                            ORBConstants.DYNAMIC_STUB_FACTORY_FACTORY_CLASS,
                            "com.sun.corba.se.impl.presentation.rmi.bcel.StubFactoryFactoryBCELImpl" ) ;

                        try {
                            // First try the configured class name, if any
                            Class<?> cls = SharedSecrets.getJavaCorbaAccess().loadClass( className ) ;
                            sff = (PresentationManager.StubFactoryFactory)cls.newInstance() ;
                        } catch (Exception exc) {
                            // Use the default. Log the error as a warning.
                            staticWrapper.errorInSettingDynamicStubFactoryFactory(
                                exc, className ) ;
                        }

                        return sff ;
                    }
                }
            ) ;

        PresentationManager pm = new PresentationManagerImpl( useDynamicStub ) ;
        pm.setStubFactoryFactory( false,
            PresentationDefaults.getStaticStubFactoryFactory() ) ;
        pm.setStubFactoryFactory( true, dynamicStubFactoryFactory ) ;
        return pm;
    }

    public void destroy() {
        wrapper = null;
        omgWrapper = null;
        typeCodeMap = null;
        primitiveTypeCodeConstants = null;
        byteBufferPool = null;
    }

    /**
     * Returns the Presentation Manager for the current thread group, using the ThreadGroup-specific
     * AppContext to hold it. Creates and records one if needed.
     */
    public static PresentationManager getPresentationManager()
    {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null && AppContext.getAppContexts().size() > 0) {
            AppContext ac = AppContext.getAppContext();
            if (ac != null) {
                synchronized (pmLock) {
                    PresentationManager pm =
                        (PresentationManager) ac.get(PresentationManager.class);
                    if (pm == null) {
                        pm = setupPresentationManager();
                        ac.put(PresentationManager.class, pm);
                    }
                    return pm;
                }
            }
        }

        // No security manager or AppContext
        return Holder.defaultPresentationManager;
    }

    /** Get the appropriate StubFactoryFactory.  This
     * will be dynamic or static depending on whether
     * com.sun.CORBA.ORBUseDynamicStub is true or false.
     */
    public static PresentationManager.StubFactoryFactory
        getStubFactoryFactory()
    {
        PresentationManager gPM = getPresentationManager();
        boolean useDynamicStubs = gPM.useDynamicStubs() ;
        return gPM.getStubFactoryFactory( useDynamicStubs ) ;
    }

    protected ORB()
    {
        // Initialize logging first, since it is needed nearly
        // everywhere (for example, in TypeCodeImpl).
        wrapperMap = new ConcurrentHashMap();
        wrapper = ORBUtilSystemException.get( this,
            CORBALogDomains.RPC_PRESENTATION ) ;
        omgWrapper = OMGSystemException.get( this,
            CORBALogDomains.RPC_PRESENTATION ) ;

        typeCodeMap = new HashMap();

        primitiveTypeCodeConstants = new TypeCodeImpl[] {
            new TypeCodeImpl(this, TCKind._tk_null),
            new TypeCodeImpl(this, TCKind._tk_void),
            new TypeCodeImpl(this, TCKind._tk_short),
            new TypeCodeImpl(this, TCKind._tk_long),
            new TypeCodeImpl(this, TCKind._tk_ushort),
            new TypeCodeImpl(this, TCKind._tk_ulong),
            new TypeCodeImpl(this, TCKind._tk_float),
            new TypeCodeImpl(this, TCKind._tk_double),
            new TypeCodeImpl(this, TCKind._tk_boolean),
            new TypeCodeImpl(this, TCKind._tk_char),
            new TypeCodeImpl(this, TCKind._tk_octet),
            new TypeCodeImpl(this, TCKind._tk_any),
            new TypeCodeImpl(this, TCKind._tk_TypeCode),
            new TypeCodeImpl(this, TCKind._tk_Principal),
            new TypeCodeImpl(this, TCKind._tk_objref),
            null,       // tk_struct
            null,       // tk_union
            null,       // tk_enum
            new TypeCodeImpl(this, TCKind._tk_string),
            null,       // tk_sequence
            null,       // tk_array
            null,       // tk_alias
            null,       // tk_except
            new TypeCodeImpl(this, TCKind._tk_longlong),
            new TypeCodeImpl(this, TCKind._tk_ulonglong),
            new TypeCodeImpl(this, TCKind._tk_longdouble),
            new TypeCodeImpl(this, TCKind._tk_wchar),
            new TypeCodeImpl(this, TCKind._tk_wstring),
            new TypeCodeImpl(this, TCKind._tk_fixed),
            new TypeCodeImpl(this, TCKind._tk_value),
            new TypeCodeImpl(this, TCKind._tk_value_box),
            new TypeCodeImpl(this, TCKind._tk_native),
            new TypeCodeImpl(this, TCKind._tk_abstract_interface)
        } ;

        monitoringManager =
            MonitoringFactories.getMonitoringManagerFactory( ).
                createMonitoringManager(
                MonitoringConstants.DEFAULT_MONITORING_ROOT,
                MonitoringConstants.DEFAULT_MONITORING_ROOT_DESCRIPTION);
    }

    // Typecode support: needed in both ORBImpl and ORBSingleton
    public TypeCodeImpl get_primitive_tc(int kind)
    {
        synchronized (this) {
            checkShutdownState();
        }
        try {
            return primitiveTypeCodeConstants[kind] ;
        } catch (Throwable t) {
            throw wrapper.invalidTypecodeKind( t, new Integer(kind) ) ;
        }
    }

    public synchronized void setTypeCode(String id, TypeCodeImpl code)
    {
        checkShutdownState();
        typeCodeMap.put(id, code);
    }

    public synchronized TypeCodeImpl getTypeCode(String id)
    {
        checkShutdownState();
        return (TypeCodeImpl)typeCodeMap.get(id);
    }

    public MonitoringManager getMonitoringManager( ) {
        synchronized (this) {
            checkShutdownState();
        }
        return monitoringManager;
    }

    // Special non-standard set_parameters method for
    // creating a precisely controlled ORB instance.
    // An ORB created by this call is affected only by
    // those properties passes explicitly in props, not by
    // the system properties and orb.properties files as
    // with the standard ORB.init methods.
    public abstract void set_parameters( Properties props ) ;

    // ORB versioning
    public abstract ORBVersion getORBVersion() ;
    public abstract void setORBVersion( ORBVersion version ) ;

    // XXX This needs a better name
    public abstract IOR getFVDCodeBaseIOR() ;

    /**
     * Handle a bad server id for the given object key.  This should
     * always through an exception: either a ForwardException to
     * allow another server to handle the request, or else an error
     * indication.  XXX Remove after ORT for ORBD work is integrated.
     */
    public abstract void handleBadServerId( ObjectKey okey ) ;
    public abstract void setBadServerIdHandler( BadServerIdHandler handler ) ;
    public abstract void initBadServerIdHandler() ;

    public abstract void notifyORB() ;

    public abstract PIHandler getPIHandler() ;

    public abstract void checkShutdownState();

    // Dispatch support: in the ORB because it is needed for shutdown.
    // This is used by the first level server side subcontract.
    public abstract boolean isDuringDispatch() ;
    public abstract void startingDispatch();
    public abstract void finishedDispatch();

    /** Return this ORB's transient server ID.  This is needed for
     * initializing object adapters.
     */
    public abstract int getTransientServerId();

    public abstract ServiceContextRegistry getServiceContextRegistry() ;

    public abstract RequestDispatcherRegistry getRequestDispatcherRegistry();

    public abstract ORBData getORBData() ;

    public abstract void setClientDelegateFactory( ClientDelegateFactory factory ) ;

    public abstract ClientDelegateFactory getClientDelegateFactory() ;

    public abstract void setCorbaContactInfoListFactory( CorbaContactInfoListFactory factory ) ;

    public abstract CorbaContactInfoListFactory getCorbaContactInfoListFactory() ;

    // XXX These next 7 methods should be moved to a ResolverManager.

    /** Set the resolver used in this ORB.  This resolver will be used for list_initial_services
     * and resolve_initial_references.
     */
    public abstract void setResolver( Resolver resolver ) ;

    /** Get the resolver used in this ORB.  This resolver will be used for list_initial_services
     * and resolve_initial_references.
     */
    public abstract Resolver getResolver() ;

    /** Set the LocalResolver used in this ORB.  This LocalResolver is used for
     * register_initial_reference only.
     */
    public abstract void setLocalResolver( LocalResolver resolver ) ;

    /** Get the LocalResolver used in this ORB.  This LocalResolver is used for
     * register_initial_reference only.
     */
    public abstract LocalResolver getLocalResolver() ;

    /** Set the operation used in string_to_object calls.  The Operation must expect a
     * String and return an org.omg.CORBA.Object.
     */
    public abstract void setURLOperation( Operation stringToObject ) ;

    /** Get the operation used in string_to_object calls.  The Operation must expect a
     * String and return an org.omg.CORBA.Object.
     */
    public abstract Operation getURLOperation() ;

    /** Set the ServerRequestDispatcher that should be used for handling INS requests.
     */
    public abstract void setINSDelegate( CorbaServerRequestDispatcher insDelegate ) ;

    // XXX The next 5 operations should be moved to an IORManager.

    /** Factory finders for the various parts of the IOR: tagged components, tagged
     * profiles, and tagged profile templates.
     */
    public abstract TaggedComponentFactoryFinder getTaggedComponentFactoryFinder() ;
    public abstract IdentifiableFactoryFinder getTaggedProfileFactoryFinder() ;
    public abstract IdentifiableFactoryFinder getTaggedProfileTemplateFactoryFinder() ;

    public abstract ObjectKeyFactory getObjectKeyFactory() ;
    public abstract void setObjectKeyFactory( ObjectKeyFactory factory ) ;

    // Logging SPI

    /**
     * Returns the logger based on the category.
     */
    public Logger getLogger( String domain )
    {
        synchronized (this) {
            checkShutdownState();
        }
        ORBData odata = getORBData() ;

        // Determine the correct ORBId.  There are 3 cases:
        // 1. odata is null, which happens if we are getting a logger before
        //    ORB initialization is complete.  In this case we cannot determine
        //    the ORB ID (it's not known yet), so we set the ORBId to
        //    _INITIALIZING_.
        // 2. odata is not null, so initialization is complete, but ORBId is set to
        //    the default "".  To avoid a ".." in
        //    the log domain, we simply use _DEFAULT_ in this case.
        // 3. odata is not null, ORBId is not "": just use the ORBId.
        String ORBId ;
        if (odata == null)
            ORBId = "_INITIALIZING_" ;
        else {
            ORBId = odata.getORBId() ;
            if (ORBId.equals(""))
                ORBId = "_DEFAULT_" ;
        }

        return getCORBALogger( ORBId, domain ) ;
    }

    public static Logger staticGetLogger( String domain )
    {
        return getCORBALogger( "_CORBA_", domain ) ;
    }

    private static Logger getCORBALogger( String ORBId, String domain )
    {
        String fqLogDomain = CORBALogDomains.TOP_LEVEL_DOMAIN + "." +
            ORBId + "." + domain;

        return Logger.getLogger( fqLogDomain, ORBConstants.LOG_RESOURCE_FILE );
    }

    /** get the log wrapper class (its type is dependent on the exceptionGroup) for the
     * given log domain and exception group in this ORB instance.
     */
    public LogWrapperBase getLogWrapper( String logDomain,
        String exceptionGroup, LogWrapperFactory factory )
    {
        StringPair key = new StringPair( logDomain, exceptionGroup ) ;

        LogWrapperBase logWrapper = (LogWrapperBase)wrapperMap.get( key );
        if (logWrapper == null) {
            logWrapper = factory.create( getLogger( logDomain ) );
            wrapperMap.put( key, logWrapper );
        }

        return logWrapper;
    }

    /** get the log wrapper class (its type is dependent on the exceptionGroup) for the
     * given log domain and exception group in this ORB instance.
     */
    public static LogWrapperBase staticGetLogWrapper( String logDomain,
        String exceptionGroup, LogWrapperFactory factory )
    {
        StringPair key = new StringPair( logDomain, exceptionGroup ) ;

        LogWrapperBase logWrapper = (LogWrapperBase)staticWrapperMap.get( key );
        if (logWrapper == null) {
            logWrapper = factory.create( staticGetLogger( logDomain ) );
            staticWrapperMap.put( key, logWrapper );
        }

        return logWrapper;
    }

    // get a reference to a ByteBufferPool, a pool of NIO ByteBuffers
    // NOTE: ByteBuffer pool must be unique per ORB, not per process.
    //       There can be more than one ORB per process.
    //       This method must also be inherited by both ORB and ORBSingleton.
    public ByteBufferPool getByteBufferPool()
    {
        synchronized (this) {
            checkShutdownState();
        }
        if (byteBufferPool == null)
            byteBufferPool = new ByteBufferPoolImpl(this);

        return byteBufferPool;
    }

    public abstract void setThreadPoolManager(ThreadPoolManager mgr);

    public abstract ThreadPoolManager getThreadPoolManager();

    public abstract CopierManager getCopierManager() ;
}

// End of file.
