/*
 * @(#)POAPolicyMediatorBase.java	1.42 03/12/19
 *
 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
 * SUN 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 ;
}
