/*
 * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.corba.se.impl.oa.poa ;

import java.util.Collection;
import java.util.Enumeration ;

import org.omg.PortableServer.Servant ;
import org.omg.PortableServer.ForwardRequest ;
import org.omg.PortableServer.POAPackage.WrongPolicy ;

import com.sun.corba.se.spi.extension.ServantCachingPolicy ;
import com.sun.corba.se.spi.orb.ORB ;
import com.sun.corba.se.spi.transport.SocketOrChannelAcceptor;

import com.sun.corba.se.impl.orbutil.ORBConstants ;
import com.sun.corba.se.impl.orbutil.ORBUtility ;
import com.sun.corba.se.impl.orbutil.concurrent.SyncUtil ;


/** Implementation of POARequesHandler that provides policy specific
 * operations on the POA.
 */
public abstract class POAPolicyMediatorBase implements POAPolicyMediator {
    protected POAImpl poa ;
    protected ORB orb ;

    private int sysIdCounter ;
    private Policies policies ;
    private DelegateImpl delegateImpl ;

    private int serverid ;
    private int scid ;

    protected boolean isImplicit ;
    protected boolean isUnique ;
    protected boolean isSystemId ;

    public final Policies getPolicies()
    {
        return policies ;
    }

    public final int getScid()
    {
        return scid ;
    }

    public final int getServerId()
    {
        return serverid ;
    }

    POAPolicyMediatorBase( Policies policies, POAImpl poa )
    {
        if (policies.isSingleThreaded())
            throw poa.invocationWrapper().singleThreadNotSupported() ;

        POAManagerImpl poam = (POAManagerImpl)(poa.the_POAManager()) ;
        POAFactory poaf = poam.getFactory() ;
        delegateImpl = (DelegateImpl)(poaf.getDelegateImpl()) ;
        this.policies = policies ;
        this.poa = poa ;
        orb = (ORB)poa.getORB() ;

        switch (policies.servantCachingLevel()) {
            case ServantCachingPolicy.NO_SERVANT_CACHING :
                scid = ORBConstants.TRANSIENT_SCID ;
                break ;
            case ServantCachingPolicy.FULL_SEMANTICS :
                scid = ORBConstants.SC_TRANSIENT_SCID ;
                break ;
            case ServantCachingPolicy.INFO_ONLY_SEMANTICS :
                scid = ORBConstants.IISC_TRANSIENT_SCID ;
                break ;
            case ServantCachingPolicy.MINIMAL_SEMANTICS :
                scid = ORBConstants.MINSC_TRANSIENT_SCID ;
                break ;
        }

        if ( policies.isTransient() ) {
            serverid = orb.getTransientServerId();
        } else {
            serverid = orb.getORBData().getPersistentServerId();
            scid = ORBConstants.makePersistent( scid ) ;
        }

        isImplicit = policies.isImplicitlyActivated() ;
        isUnique = policies.isUniqueIds() ;
        isSystemId = policies.isSystemAssignedIds() ;

        sysIdCounter = 0 ;
    }

    public final java.lang.Object getInvocationServant( byte[] id,
        String operation ) throws ForwardRequest
    {
        java.lang.Object result = internalGetServant( id, operation ) ;

        return result ;
    }

    // Create a delegate and stick it in the servant.
    // This delegate is needed during dispatch for the ObjectImpl._orb()
    // method to work.
    protected final void setDelegate(Servant servant, byte[] id)
    {
        //This new servant delegate no longer needs the id for
        // its initialization.
        servant._set_delegate(delegateImpl);
    }

    public synchronized byte[] newSystemId() throws WrongPolicy
    {
        if (!isSystemId)
            throw new WrongPolicy() ;

        byte[] array = new byte[8];
        ORBUtility.intToBytes(++sysIdCounter, array, 0);
        ORBUtility.intToBytes( poa.getPOAId(), array, 4);
        return array;
    }

    protected abstract  java.lang.Object internalGetServant( byte[] id,
        String operation ) throws ForwardRequest ;
}
