/*
 * Copyright (c) 2000, 2001, 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.
 */

#include "Interceptors.idl"

module PortableActivationIDL {
    /** Possible values for endpointType argument on Server.getEndpoint()
    * If you change the value of this constant then update
    * core.EndPoint accordingly.  It has a duplicate definition
    * to avoid a compilation dependency.
    */
    const string IIOP_CLEAR_TEXT = "IIOP_CLEAR_TEXT";

    /** Raised if getEndpoint is called on a server callback object for
    * an invalid endpoint type
    */
    exception NoSuchEndPoint {} ;

    /** Raised if an attempt is made to retrieve ports corresponding to
    * non-registered ORB
    */
    exception InvalidORBid {} ;

    /** Raised if an operation is attempted against an invalid server ID.
    */
    exception ServerNotRegistered {
	PortableInterceptor::ServerId serverId ;
    };

    /** Raised if an operation is attempted for a server that is not running,
    * and the server is required to be running for the operation.
    */
    exception ServerNotActive {
	PortableInterceptor::ServerId serverId ;
    };

    /** Raised if an operation is attempted against a server that is in a 
    * hold down state.  A server becomes held down if it fails to activate
    * within 10 seconds.
    */
    exception ServerHeldDown {
	PortableInterceptor::ServerId serverId ;
    };

    /** Raised if an attempt is made to activate a server that is already 
    * running.
    */
    exception ServerAlreadyActive{
	PortableInterceptor::ServerId serverId ;
    };

    /** Raised if an attempt is made to register a serverdef with the
    * same applicationName as an existing serverdef.
    */
    exception ServerAlreadyRegistered {
	PortableInterceptor::ServerId serverId;
    };

    /** Raised if an attempt is made to install a server that is currently 
    * installed.  Note that a newly created server starts out in an uninstalled
    * state.
    */
    exception ServerAlreadyInstalled {
	PortableInterceptor::ServerId serverId;
    } ;

    /** Raised if an attempt is made to uninstall a server that is currently 
    * uninstalled.  Note that a newly created server starts out in an 
    * uninstalled
    * state.
    */
    exception ServerAlreadyUninstalled {
	PortableInterceptor::ServerId serverId;
    } ;

    /** Raised if an attempt is made to register an invalid serverdef.
    */
    exception BadServerDefinition {
	string reason;
    };

    /** Raised if an attempt is made to register endpoints for the
     * same ORB again
     */
    exception ORBAlreadyRegistered {
	PortableInterceptor::ORBId orbId;
    };

    /** Type of TCP port number, used in structures that describe 
    * transport endpoints.  The valid range is actually 0-65535, but
    * we use a long here to avoid signed/unsigned conversion headaches
    * in Java.
    */
    typedef long TCPPort ;

    /** Sequence of server Ids, used for queries about servers.
    */
    typedef sequence<PortableInterceptor::ServerId> ServerIds;

    /** End point information for one particular kind of port associated with an 
    * an ORB.  This is only used in the
    * Activator interface, which must always run on the same host as the daemon,
    * therefore we do not need the host name here.
    */
    struct EndPointInfo {
	string endpointType;
	TCPPort port;
    };

    /** A list of endpoint information for a particular ORB.  
    */
    typedef sequence<EndPointInfo> EndpointInfoList;

    /** struct contain ORB and port info for a particular type of endpoint.
    * This is only used in the
    * Activator interface, which must always run on the same host as the daemon,
    * therefore we do not need the host name here.
    */
    struct ORBPortInfo {
	PortableInterceptor::ORBId orbId;
	TCPPort port;
    };

    /** A list of ORB and port information for a particular endpoint type.
    */
    typedef sequence<ORBPortInfo> ORBPortInfoList;

    /** A list of ORB IDs.
    */
    typedef sequence<PortableInterceptor::ORBId> ORBidList;

    /** Server callback interface, passed to Activator in registerServer method.
    */
    interface ServerProxy {
	/** Shutdown this server.  Returns after orb.shutdown() completes.
	*/
	void shutdown();

	/** Install the server.  Returns after the install hook completes
	* execution in the server.
	*/
	void install();

	/** Uninstall the server.  Returns after the uninstall hook
	* completes execution.
	*/
	void uninstall();
    };

    /** ORB callback interface, passed to Activator in registerORB method.
    */
    interface ORBProxy {
	/** Method used to cause ORB to activate the named adapter, if possible.
	* This will cause the named POA to register itself with the activator as
	* a side effect.  This should always happen before this call can complete.
	* This method returns true if adapter activation succeeded, otherwise it
	* returns false.
	*/
	boolean activate_adapter( in PortableInterceptor::AdapterName name ) ;
    } ;
    
    interface Activator {
	/*******************************************************
	*		    Server State Change Methods
	********************************************************/

    	/** A new ORB started server registers itself with the Activator
	*/
    	void registerServer(in PortableInterceptor::ServerId serverId, in ServerProxy serverObj) 
	    raises (ServerNotRegistered);

	/** A server is shutting down that was started by this activator.
	* Complete termination of the server is detected by the death of the
	* process implementing the server.
	*/
	void serverGoingDown( in PortableInterceptor::ServerId serverId ) ;

	/** Called whenever an ORB instance is created.  This registers
	* the transport endpoints and the ORB proxy callback object.
	* Note that we cannot detect when an ORB shuts down, although
	* all of the POA shutdowns should still be reported.
	*/
	void registerORB( in PortableInterceptor::ServerId serverId, in PortableInterceptor::ORBId orbId, 
	    in ORBProxy orb, in EndpointInfoList endPointInfo) 
	    raises (ServerNotRegistered,NoSuchEndPoint, ORBAlreadyRegistered) ;

	/** Construct or find an ORBD object template corresponding to the 
	* server's object template and return it.  Called whenever a 
	* persistent POA is created.
	*/
	PortableInterceptor::ObjectReferenceTemplate registerPOA( 
	    in PortableInterceptor::ServerId serverId, in PortableInterceptor::ORBId orbId, 
	    in PortableInterceptor::ObjectReferenceTemplate poaTemplate ) ;
 
	/** Called whenever a POA is destroyed.
	*/
	void poaDestroyed( 
	    in PortableInterceptor::ServerId serverId, in PortableInterceptor::ORBId orbId, 
	    in PortableInterceptor::ObjectReferenceTemplate poaTemplate ) ;       

	/*******************************************************
	*		    Server Control Methods
	********************************************************/

	/** If the server is not running, start it up.  This is allowed
	* whether or not the server has been installed.
	*/
	void activate(in PortableInterceptor::ServerId serverId) 
	    raises (ServerAlreadyActive, ServerNotRegistered, ServerHeldDown);

	/** If the server is running, shut it down
	*/
	void shutdown(in PortableInterceptor::ServerId serverId) 
	    raises (ServerNotActive, ServerNotRegistered);

	/** Invoke the server install hook.  If the server is not 
	* currently running, this method will activate it.
	*/
	void install(in PortableInterceptor::ServerId serverId) 
	    raises (ServerNotRegistered, ServerHeldDown, 
		ServerAlreadyInstalled);

	/** Invoke the server uninstall hook.  If the server is not
	* currently running, this method will activate it.
	* After this hook completes, the server may still be running.
	*/
	void uninstall(in PortableInterceptor::ServerId serverId) 
	    raises (ServerNotRegistered, ServerHeldDown, 
		ServerAlreadyUninstalled);

	/*******************************************************
	*		    Accessors
	********************************************************/

	/** list active servers
	*/
	ServerIds getActiveServers();

	/** list all registered ORBs for a server
	*/
	ORBidList getORBNames(in PortableInterceptor::ServerId serverId)
	    raises (ServerNotRegistered);

	/** Find the server template that corresponds to the ORBD's
	* adapter id.
	*/
	PortableInterceptor::ObjectReferenceTemplate lookupPOATemplate( 
	    in PortableInterceptor::ServerId serverId, in PortableInterceptor::ORBId orbId, 
	    in PortableInterceptor::AdapterName orbAdapterName ) ;
    };

    interface Locator {
	/** struct to return the list of endpoints for a server for a specific
	* endpoint type.  
	*/
	struct ServerLocationPerType {
	    string hostname;
	    ORBPortInfoList ports;
        };

	/** struct to return the list of endpoints for a server for a specific
	* ORB
	*/
	struct ServerLocationPerORB {
	    string hostname;
	    EndpointInfoList ports;
        };

	/** locate server - returns the port with a specific type for all registered
	* ORBs of an active server.
	* Starts the server if it is not already running.
	*/
	ServerLocationPerType locateServer(
	    in PortableInterceptor::ServerId serverId,
	    in string endPoint) 
	    raises(NoSuchEndPoint, ServerNotRegistered, ServerHeldDown);

	/** locate server - returns all ports registered with a specified ORB for
	* an active server
	* Starts the server if it is not already running.
	*/
	ServerLocationPerORB locateServerForORB(
	    in PortableInterceptor::ServerId serverId,
	    in PortableInterceptor::ORBId orbId) 
	    raises(InvalidORBid, ServerNotRegistered, ServerHeldDown);

	/** get the port for the endpoint of the locator
	*/
	TCPPort getEndpoint(in string endPointType)
	    raises(NoSuchEndPoint);

	/** Useful from external BadServerIdHandlers which need
	* to pick a particular port type.
	*/
	TCPPort getServerPortForType(
            in ServerLocationPerORB location,
	    in string endPointType)
	    raises(NoSuchEndPoint);
    };

    /** Interface used to combine the Activator and Locator when both are
    * implemented together in the same process, as is currently the case
    * for our implementation.
    */
    interface ServerManager : Activator, Locator { };

    /** Interface used to support binding references in the bootstrap name
    * service.
    */
    interface InitialNameService {
	exception NameAlreadyBound {};

	/** bind initial name
	*/
	void bind (
	    in string name,
	    in Object obj,
	    in boolean isPersistant) raises (NameAlreadyBound);
    };

    interface Repository {
	/** server program definition.  
	*/
	struct ServerDef {
	    string  applicationName;	// alias used for servers with identical
					// serverName values.
	    string  serverName;		// Class name of server's main class.
	    string  serverClassPath;	// class path used to run the server.
	    string  serverArgs;		// arguments passed to the server
	    string  serverVmArgs;	// arguments passed to the server's Java VM1
	    boolean isInstalled;	// Whether or not the server has been installed
	};
	
	/** register server definition.
	* This returns the serverId of the server.  A newly created server is
	* always uninstalled.
	*/
	PortableInterceptor::ServerId registerServer (in ServerDef serverDef) 
	    raises (ServerAlreadyRegistered, BadServerDefinition);
	
	/** unregister server definition
	*/
	void unregisterServer (in PortableInterceptor::ServerId serverId) 
	    raises (ServerNotRegistered);

	/** get server definition
	*/
	ServerDef getServer(in PortableInterceptor::ServerId serverId) 
	    raises (ServerNotRegistered);

	/** Return whether the server has been installed
	*/
	boolean isInstalled( in PortableInterceptor::ServerId serverId ) 
	    raises (ServerNotRegistered);

	/** Mark the server as being installed.  Raises ServerAlreadyInstalled
	* if the server is currently marked as installed.
	*/
	void install( in PortableInterceptor::ServerId serverId ) 
	    raises (ServerNotRegistered, ServerAlreadyInstalled) ;

	/** Mark the server as being uninstalled.  Raises ServerAlreadyUninstalled
	* if the server is currently marked as uninstalled.
	*/
	void uninstall( in PortableInterceptor::ServerId serverId ) 
	    raises (ServerNotRegistered, ServerAlreadyUninstalled) ;

	/** list registered servers
	*/
	ServerIds listRegisteredServers ();

	/** Type used for a list of application names
	*/
	typedef sequence<string>    AppNames ;

	/** Returns list of ALL applicationNames defined in ServerDefs of registered 
	* servers.
	*/
	AppNames   getApplicationNames();

	/** Find the ServerID associated with the given application name.
	*/
	PortableInterceptor::ServerId getServerID( in string applicationName ) 
		raises (ServerNotRegistered) ;
    };
};
