package jacorb.orb;

/*
 *        JacORB  - a free Java ORB
 *
 *   Copyright (C) 1997-98  Gerald Brose.
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Library General Public
 *   License as published by the Free Software Foundation; either
 *   version 2 of the License, or (at your option) any later version.
 *
 *   This library 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
 *   Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this library; if not, write to the Free
 *   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

import java.util.*;
import org.omg.CORBA.TypeCode;
import jacorb.imr.*;
import org.omg.CORBA.ORBPackage.InvalidName;
import jacorb.orb.portableInterceptor.*;
import org.omg.PortableInterceptor.*;
import org.omg.IOP.*;

/**
 * @author Gerald Brose, FU Berlin
 * @version $Id: ORB.java,v 1.78 2000/04/03 16:31:13 brose Exp $
 */

public final class ORB
    extends ORBSingleton
    implements jacorb.poa.POAListener
{

  /** "initial" references */
  private Hashtable initial_references = new Hashtable();

    private jacorb.poa.POA rootpoa;
    private jacorb.poa.Current poaCurrent;
    private BasicAdapter basicAdapter;
    private Current current;
    private jacorb.util.net.SocketFactory defaultSSLSocketFactory;

  /** interceptor handling */
  private Vector interceptor_chain = new Vector();
  private Vector serverRequestInterceptorChain = new Vector();
  // CORBA.Object -> interceptor
  private Hashtable perObjectClientRequestInterceptors = new Hashtable();
  // impl -> interceptor
  private  Hashtable perObjectServerRequestInterceptors = new Hashtable();
  private  Vector clientMessageInterceptorChain = new Vector();
  private  Vector serverMessageInterceptorChain = new Vector();
  // CORBA.Object -> interceptor
  private  Hashtable perObjectClientMessageInterceptors = new Hashtable();

  private jacorb.orb.portableInterceptor.InterceptorManager interceptor_manager = null;

  /** reference caching */
  private Hashtable knownReferences = new Hashtable();

  /** connection mgmt. */
  private Hashtable connections = new Hashtable();

  /** buffer mgmt. */
  private BufferManager bufferManager = new BufferManager();

  /** properties */ 
  private java.util.Properties _props;

  /** command like args */
  public String[] _args;
	
  // devik: default IIOP version used to generate IORs
  protected org.omg.IIOP.Version IIOPVersion=new org.omg.IIOP.Version((byte)1,(byte)1);

  public  java.applet.Applet applet;

  /* for run() and shutdown()  */
  private Object orb_synch = new java.lang.Object();
  private boolean run = true;
  private boolean wait = true;
  private boolean shutdown_in_progress = false;
  private Object shutdown_synch = new Object();

  /** for proxy */
  private  jacorb.proxy.Forwarder     proxyObj = null;
  private  boolean                    proxyConnectDirectly = false;
  private  Hashtable                  unproxyTable = null;
  private  boolean                    applet_properties_read = false;
  private  Vector			proxyEntries=new Vector();

  // for registering POAs with the ImR
  private Registration imr = null;
  private ImRInfo imr_info = null;
  private int persistentPOACount;

  public static String orb_id = "jacorb:1.0";

  //policy factories, from portable interceptor spec
  private Hashtable policy_factories = null;
  
  private IORInterceptor[] ior_interceptors = null;

  public ORB()
  {

  }

  /**
   * Lookup operation for existing connections to destinations, <br>
   * opens a new one if no connection exists
   *
   * @param <code>String host_and_port</code> - in "host:xxx" notation
   * @return <code>Connection</code>
   */

  public final Connection _getConnection( String host_and_port )
  {
    int retries = jacorb.util.Environment.noOfRetries();

    if( host_and_port.indexOf('/') > 0)
      host_and_port = host_and_port.substring( host_and_port.indexOf('/') + 1 );
    String host = host_and_port.substring(0,host_and_port.indexOf(":"));
    String port = host_and_port.substring(host_and_port.indexOf(":")+1);
    try
      {
	/** make sure we have a raw IP address here */
	java.net.InetAddress inet_addr = java.net.InetAddress.getByName( host );
	host_and_port = inet_addr.getHostAddress() + ":" + port;
      }
    catch( java.net.UnknownHostException uhe )
      {
	throw new org.omg.CORBA.COMM_FAILURE("Unknown host " + host);
      }

    Connection e = (Connection)connections.get( host_and_port );

    if( e != null )
      {
	e.incUsers();
	return e;
      } 

    while( retries+1 > 0 )  // +1 for initial connection
      {
	try 
	  {
	    int _port = new Integer(host_and_port.substring(host_and_port.indexOf(":")+1)).intValue();
	    if( _port <0)
	      _port += 65536;
			
	    java.net.Socket s=null;
	    try
	      {		
		s = new java.net.Socket(host_and_port.substring(0,host_and_port.indexOf(":")), 
					_port );
	      }
	    catch(SecurityException ace)
	      {
		//could only happen, if called by applet
		//->connect must goto applethost
		s = new java.net.Socket( applet.getCodeBase().getHost(),
					 _port );			
	      }
	    s.setTcpNoDelay(true);
	    String prop = jacorb.util.Environment.getProperty("jacorb.connection.client_timeout");
	    if( prop != null )
	      {
		try
		  {
		    s.setSoTimeout(Integer.parseInt(prop));
		  } 
		catch ( java.lang.NumberFormatException nfe )
		  {
		    // just ignore
		  }
	      }
	    Connection c = new Connection( this, s, false );
	    connections.put( c.getInfo(), c );
	    return c;
	  } 
	catch ( java.io.IOException c ) 
	  { 
	    // debug :c.printStackTrace();
	    jacorb.util.Debug.output(1,"Retrying connection to " + host_and_port);
	    try 
	      {
		Thread.sleep( jacorb.util.Environment.retryInterval() );
	      } 
	    catch ( InterruptedException i ){}
	    retries--;
	  }
      }
    if( retries < 0 )
      throw new org.omg.CORBA.COMM_FAILURE("Retries exceeded, couldn't connect to " + 
					   host_and_port);
    return e;
  }


  /**
   * bnv: For SSL connections
   * Lookup operation for existing connections to destinations, <br>
   * it is an error if the connection is not an SSL one
   * opens a new SSL one if no connection exists
   *
   * @param <code>String host_and_port</code> - in "host:xxx" notation
   * @return <code>Connection</code>
   * @except <code>org.omg.CORBA.NO_PERMISSION</code>
   */

  public final Connection _getSSLConnection( String host_and_port )
    throws org.omg.CORBA.NO_PERMISSION
  {
    // System.out.println ( "_getSSLConnection, adport = " + host_and_port );
    int retries = jacorb.util.Environment.noOfRetries();
	
    if( host_and_port.indexOf('/') > 0)
      host_and_port = host_and_port.substring( host_and_port.indexOf('/') + 1 );
    String host = host_and_port.substring(0,host_and_port.indexOf(":"));
    String port = host_and_port.substring(host_and_port.indexOf(":")+1);
    try
      {
	/** make sure we have a raw IP address here */
	java.net.InetAddress inet_addr = java.net.InetAddress.getByName( host );
	host_and_port = inet_addr.getHostAddress() + ":" + port;
      }
    catch( java.net.UnknownHostException uhe )
      {
	throw new org.omg.CORBA.COMM_FAILURE("Unknown host " + host);
      }

    Connection e = (Connection)connections.get( host_and_port );

    if( e != null )
      {
	if ( e.isSSL ()) 
	  {
	    e.incUsers();
	    return e;
	  } 
	else throw new org.omg.CORBA.NO_PERMISSION ( 0,  // NO_CLEAR
						     org.omg.CORBA.CompletionStatus.COMPLETED_NO
						     );
      } 
    else
      {
	// System.out.println ( "connections.get( host_and_port ) == null" );
	if ( !jacorb.util.Environment.supportSSL ()) 
	  {
	    throw new org.omg.CORBA.NO_PERMISSION ( 1,  // NO_CONTEXT
						    org.omg.CORBA.CompletionStatus.COMPLETED_NO
						    );
	  }
      }

    while( retries+1 > 0 )  // +1 for initial connection
      {
	try 
	  {
	    int _port = new Integer(host_and_port.substring(host_and_port.indexOf(":")+1)).intValue();
	    if( _port <0)
	      _port += 65536;

	    if ( defaultSSLSocketFactory == null )
	      //bnv: if you don't use Credentials to setup your default SSL contexts
	      //defaultSSLSocketFactory = jacorb.security.ssl.SSLSetup.getDefaultSSLSocketFactory ();
	      //orb reference needed to access securityCurrent and then own_credentials
	      defaultSSLSocketFactory = jacorb.security.ssl.SSLSetup.getDefaultSSLSocketFactory ( this );
	    java.net.Socket ssl = defaultSSLSocketFactory.createSocket ( 
									host_and_port.substring(0,host_and_port.indexOf(":")), 
									_port
									);
	    ssl.setTcpNoDelay(false);
	    Connection c = new Connection( this, ssl, false );
	    connections.put( c.getInfo(), c );
	    return c;
	  } 
	catch ( java.io.IOException c ) 
	  { 
	    // debug : c.printStackTrace();
	    jacorb.util.Debug.output ( 1, "Retrying connection to "
				       + " over SSL "
				       + host_and_port
				       );
	    try 
	      {
		Thread.sleep( jacorb.util.Environment.retryInterval());
	      } 
	    catch ( InterruptedException i ){}
	    retries--;
	  }
      }
    if( retries == 0 )
      throw new org.omg.CORBA.COMM_FAILURE("Retries exceeded, couldn't connect to " + 
					   host_and_port);
    return e;
  }

  /**
   *  we look at profile body components for an SSL tagged component
   *  @author bnv
   */
  public org.omg.SSLIOP.SSL getSSLTaggedComponent ( org.omg.IIOP.ProfileBody_1_1 profileBody )
  {
    if ( profileBody == null
	 || ( char )profileBody.iiop_version.minor == (( char ) 0 )
	 || profileBody.components == null
         )
      return null;
    boolean found_ssl = false;
    for ( int i = 0; i < profileBody.components.length; i++ )
      {
	if( profileBody.components[i].tag == 20 ) //TAG_SSL_SEC_TRANS
	  {
            found_ssl = true;
            jacorb.orb.CDRInputStream in =
	      new jacorb.orb.CDRInputStream( this, profileBody.components[ i ].component_data );
            try
	      {
		in.setLittleEndian( in.read_boolean ());
		return org.omg.SSLIOP.SSLHelper.read( in );
	      } catch ( Exception ex ) { return null; }
	  }
      }
    return null;
  }
    
  public void removeConnection( Connection e )
  {
    connections.remove( e.getInfo() );
  }

  public void addConnection( Connection e )
  {
    connections.put( e.getInfo(), e );
  }

  public void initProxy()
  {
    if (proxyObj==null)
      { 
	// proxy not known yet
	jacorb.util.Debug.output(2,"ORB:Applet-Proxy Init");
	java.net.URL proxyURL=null;
			
	try
	  {
	    if (!applet_properties_read)
	      {
		jacorb.util.Environment.readFromURL( new java.net.URL(applet.getCodeBase().toString()+"jacorb.properties"));
		applet_properties_read = true;
	      }
	  }
	catch (java.net.MalformedURLException mue)
	  {
	    throw new RuntimeException("Bad URL for default context.");
	  }		
		    

	/* try to get location of URL with proxy's IOR from applet parameter */
	try
	  {
	    proxyURL = new java.net.URL(applet.getParameter("JacorbProxyServerURL"));
	    jacorb.util.Debug.output(2,"ORB:Trying address (applet param):"+proxyURL.toString());
	    readProxyIOR(proxyURL);
	  }
	catch(java.net.MalformedURLException murle)
	  {
	    jacorb.util.Debug.output(2,"ORB:Malformed proxyaddress in parametertags");
	  }
	catch(java.lang.Exception e)
	  {
	    jacorb.util.Debug.output(2,"ORB:No proxy ior found in"+proxyURL.toString());
	  }

	if (proxyObj==null)
	  {

	    /* try to get location of URL with proxy"s IOR from local properties */

	    try
	      {
		proxyURL = new java.net.URL(jacorb.util.Environment.proxyURL());
		jacorb.util.Debug.output(2,"ORB:Trying address (Environment):"+proxyURL.toString());
		readProxyIOR(proxyURL);
		return;
	      }
	    catch(java.net.MalformedURLException murle)
	      {
		jacorb.util.Debug.output(2,"ORB:No proxyaddress in local properties set");
	      }
	    catch(java.lang.Exception e)
	      {
		jacorb.util.Debug.output(2,"ORB:No proxy ior found in (Environment) "+proxyURL.toString());
	      }
	  }
				
	if (proxyObj==null)
	  {
	    try
	      {
		/* try to get location of URL with proxy's IOR from remote
		   properties file at the applet's code base*/

		String codebase = applet.getCodeBase().toString();
		proxyURL = 
		  new java.net.URL(codebase.substring(codebase.lastIndexOf("/"))+"proxy.ior");
		jacorb.util.Debug.output(2,"ORB:Trying address (Magic):"+proxyURL.toString());
		readProxyIOR(proxyURL);
		return;
	      }
	    catch(java.net.MalformedURLException murle)
	      {
		jacorb.util.Debug.output(2,"ORB:Malformed Applet-Codebase URL");
	      }
	    catch(java.lang.Exception e)
	      {
		jacorb.util.Debug.output(2,"ORB:No proxy ior found in"+proxyURL.toString());
	      }				       
	  }
	if (proxyObj==null)
	  {
	    try
	      {
		/* try to get location of URL with proxy's IOR from a file
		   called proxy.ior at the applet's code base*/

		String codebase=applet.getCodeBase().getHost();
		proxyURL=new java.net.URL("http:////"+codebase+"/proxy.ior");
		jacorb.util.Debug.output(2,"ORB:Trying address (MagicHome):"+proxyURL.toString());
		readProxyIOR(proxyURL);
		return;
	      }
	    catch(java.net.MalformedURLException murle)
	      {
		jacorb.util.Debug.output(2,"ORB:Malformed Host URL");
	      }
	    catch(java.lang.Exception e)
	      {
		jacorb.util.Debug.output(2,"ORB:No proxy ior found in "+proxyURL.toString());
	      }
	  }
	if (proxyObj == null)
	  {
	    jacorb.util.Debug.output(1,"ORB:Proxy server NOT found");
	    if( applet != null )
	      {
		throw new RuntimeException("Appligator not reachable! Check configuration");
	      }
	  }

      }
    else
      jacorb.util.Debug.output(2,"ORB:Tried to initialize proxy a second time -- ignored");
  }

  public jacorb.orb.Connection getConnection(jacorb.orb.Delegate delegate)
    {
        if( (applet == null) || proxyConnectDirectly )
	{
            if ( delegate.port_is_ssl ()) 
		return _getSSLConnection ( delegate.get_adport());
            else 
		return _getConnection ( delegate.get_adport());
	}
        else
	{
	    //the forward call must not diverted
	    proxyConnectDirectly=true;
	    if (proxyObj==null)
		initProxy();	


	    //divert connection to the proxy
	    jacorb.util.Debug.output(2,"ORB:Applet-Proxy diverting");	     
	    org.omg.CORBA.StringHolder proxyEntryId = new org.omg.CORBA.StringHolder();
	    String newIORString = 
		proxyObj.forward(delegate.getParsedIOR().getIORString(),proxyEntryId);
	    proxyEntries.addElement(proxyEntryId.value);
	    jacorb.orb.ParsedIOR divpior = new jacorb.orb.ParsedIOR(newIORString);
	    //put in unproxyTable
	    unproxyTable.put(divpior.getIORString(),delegate.getParsedIOR().getIORString());
	    delegate.setIOR(divpior.getIOR());              
	    delegate.set_adport_and_key( divpior.getProfileBody().host + 
					 ":"+divpior.getProfileBody().port,divpior.getProfileBody().object_key );
	    proxyConnectDirectly = false;                     
	    jacorb.util.Debug.output(2,"ORB:Applet-Proxy new address set");

	    if (delegate.port_is_ssl())
	    {
		return _getSSLConnection ( divpior.getProfileBody().host+":" +
					   divpior.getProfileBody().port);			
	    }
	    else
	    {
	     	return _getConnection( divpior.getProfileBody().host+":"+divpior.getProfileBody().port);
	    }
	}        
    }

  /** this version of _getObject is used for references that have arrived over the
      network and is called from CDRInputStream. It removes stale cache entries */

  org.omg.CORBA.Object _getObject(ParsedIOR pior)
  {
    String key = new String(pior.getIORString());
    org.omg.CORBA.portable.ObjectImpl o = 
      (org.omg.CORBA.portable.ObjectImpl)knownReferences.get( key );

    if( o != null )
      {
	jacorb.util.Debug.output(5,"Found a reference for key " + key + " in cache ");
	jacorb.orb.Delegate del = (jacorb.orb.Delegate) o._get_delegate();
	if (del != null)
	  {
	    ParsedIOR delpior= del.getParsedIOR();
	    if (delpior == null)
	      {
		knownReferences.remove(key);
		jacorb.util.Debug.output(4,"Removing an invalid reference from cache.");
	      }
	    else if( pior.getAddress().equals(delpior.getAddress()))
	      {
		return o._duplicate();
	      }
	  }
	else
	  {		
	    jacorb.util.Debug.output(3,"remove stale reference for key " + key + " from cache ");
	    knownReferences.remove( key );
	  }
      }
	
    jacorb.orb.Delegate d = new Delegate(this, pior );
    o = d.getReference(null);
    if( jacorb.util.Environment.cacheReferences() )
      {
	jacorb.util.Debug.output(5,"Caching reference for key " + key + " in cache ");
	knownReferences.put( key, o );
      }
    return o;
  }

  public BufferManager getBufferManager()
  {
    return bufferManager;
  }


  void _release( org.omg.CORBA.Object o )
  {
    String key = 
      new String( ((jacorb.orb.Delegate)((org.omg.CORBA.portable.ObjectImpl)o)._get_delegate()).getObjectKey() );
    knownReferences.remove(key);
  }

  /*
   *	Message-level Interceptors
   *
   */ 


  /**
   *	add per-process interceptor (client-side)
   */

  public void addInterceptor( jacorb.orb.ClientMessageInterceptor intc )
  {
    clientMessageInterceptorChain.addElement( intc );
  }

  /**
   *	add per-process interceptor (client-side)
   */

  public void addInterceptor( jacorb.orb.ClientRequestInterceptor intc )
  {
    interceptor_chain.addElement( intc );
  }

  /**
   *	add per-object interceptor (client-side)
   */

  public void addInterceptor( org.omg.CORBA.Object o, jacorb.orb.ClientMessageInterceptor intc )
  {
    Vector perObjectChain = (Vector)perObjectClientMessageInterceptors.get( o );
    if( perObjectChain == null )
      {
	perObjectChain = new Vector();
	perObjectClientMessageInterceptors.put( o, perObjectChain );
      }
    perObjectChain.addElement( intc );
  }

  /**
   *	add per-process interceptor (server-side)
   */

  public void addServerInterceptor( jacorb.orb.ServerMessageInterceptor intc )
  {
    serverMessageInterceptorChain.addElement( intc );
  }

  /**
   *	add per-process interceptor (server-side)
   */

  public void addServerInterceptor( jacorb.orb.ServerRequestInterceptor intc )
  {
    serverRequestInterceptorChain.addElement( intc );
  }


  /**
   *	add per-object interceptor (server-side)
   */

  public void addServerInterceptor( org.omg.CORBA.Object o, 
				    jacorb.orb.ServerRequestInterceptor intc )
  {
    Vector perObjectChain = 
      (Vector)perObjectServerRequestInterceptors.get( o );
    if( perObjectChain == null )
      {
	perObjectChain = new Vector();
	perObjectServerRequestInterceptors.put( o, perObjectChain );
      }
    perObjectChain.addElement( intc );
  }


  /**
   *	call interceptor (client-side) after invocation
   */

  public byte [] client_messageIntercept_post (org.omg.CORBA.Object o, byte [] buf )
  {
    byte [] tmp_buf = buf;
    for( Enumeration e = clientMessageInterceptorChain.elements(); e.hasMoreElements(); )
      tmp_buf = ((ClientMessageInterceptor)e.nextElement()).post_invoke(o,tmp_buf);

    // per object interceptors (if any)
    if( o != null )
      {
	Vector perObjectChain = (Vector)perObjectClientMessageInterceptors.get( o );
	if( perObjectChain != null )
	  for( Enumeration e = perObjectChain.elements(); e.hasMoreElements(); )
	    tmp_buf = ((ClientMessageInterceptor)e.nextElement()).
	      post_invoke(o,tmp_buf);
      }
    return tmp_buf;
  }


  /**
   *	call interceptor (client-side) before invocation
   */

  public byte [] client_messageIntercept_pre (org.omg.CORBA.Object o, byte [] buf )
  {
    byte [] tmp_buf = buf;
    for( Enumeration e = clientMessageInterceptorChain.elements(); e.hasMoreElements(); )
      {
	tmp_buf = ((ClientMessageInterceptor)e.nextElement()).pre_invoke(o,tmp_buf);

      }
	
    // per object interceptors (if any)
    if( o != null )
      {
	Vector perObjectChain = (Vector)perObjectClientMessageInterceptors.get( o );
	if( perObjectChain != null )
	  {
	    for( Enumeration e = perObjectChain.elements(); e.hasMoreElements(); )
	      {
		tmp_buf = ((ClientMessageInterceptor)e.nextElement()).
		  pre_invoke(o,tmp_buf);
	      }
	  }
      }
    return tmp_buf;
  }

  public void client_requestIntercept_post( jacorb.orb.dii.Request r )
  {
    Vector perObjectChain = (Vector)perObjectClientRequestInterceptors.get( r.target );

    // per object interceptors (if any)

    if( perObjectChain != null )
      {
	for( int i = perObjectChain.size(); i-- > 0; )
	  {
	    ((jacorb.orb.ClientRequestInterceptor)perObjectChain.elementAt(i)).
	      post_invoke(r);
	  }
      }

    // per process interceptors

    for( int i = interceptor_chain.size(); i-- > 0; )
      {
	((jacorb.orb.ClientRequestInterceptor)interceptor_chain.elementAt(i)).post_invoke(r);
      }    
  }
  /**
   *	generic operation invocation on objects (using the DII)
   * 
   * 	before and after invocation, the client-side interceptors
   *	are given access to the request. First, per-process
   *	interceptors are contacted, then per-object interceptors.
   *	This is done vice versa on return of the invocation
   */
 
  public void client_requestIntercept_pre( jacorb.orb.dii.Request r )
  {

    // per process interceptors

    for( Enumeration e = interceptor_chain.elements(); e.hasMoreElements(); )
      ((jacorb.orb.ClientRequestInterceptor)e.nextElement()).pre_invoke(r);

    // per object interceptors (if any)

    Vector perObjectChain = (Vector)perObjectClientRequestInterceptors.get( r.target );
    if( perObjectChain != null )
      for( Enumeration e = perObjectChain.elements(); e.hasMoreElements(); )
	((jacorb.orb.ClientRequestInterceptor)e.nextElement()).
	  pre_invoke(r);
  }

  /**
   * This method creates a policy with the given type
   * and the given value. A PolicyFactory for the type
   * has to be present. PolicyFactories can be registered using
   * the ORBInitializer mechanism.
   *
   * @param type The policies type.
   * @param value The policies value.
   * @exception org.omg.CORBA.PolicyError There is no PolicyFactory for the 
   * given type or the policy creation failed.
   */
  public org.omg.CORBA.Policy create_policy(int type, org.omg.CORBA.Any value)
    throws org.omg.CORBA.PolicyError{

    Integer key = new Integer(type);
    if ((policy_factories == null) || (! policy_factories.containsKey(key)))
      throw new org.omg.CORBA.PolicyError();

    PolicyFactory factory = (PolicyFactory) policy_factories.get(key);
    
    return factory.create_policy(type, value);
  }
    

  /**
   * Tests, if a policy factory is present for the given type.
   * This method is (right now) only called by the Info-Objects
   * of the portableInterceptor implementation to avoid running
   * into exceptions.
   */
  public boolean hasPolicyFactoryForType(int type){
    return (policy_factories != null) && 
      policy_factories.containsKey(new Integer(type));
  }

  public  org.omg.CORBA.ContextList create_context_list()
  {
    return null;
  }

  public  org.omg.CORBA.Environment create_environment()
  {
    return null;
  }

  public org.omg.CORBA.portable.OutputStream create_output_stream()
  {
    return new CDROutputStream(this);
  }
  public TypeCode create_struct_tc(String id, 
				   String name, org.omg.CORBA.StructMember[] members)
  {
    jacorb.orb.TypeCode tc = new jacorb.orb.TypeCode(org.omg.CORBA.TCKind._tk_struct,id,name,members);
    tc.resolve_recursion(0, tc);
    return tc;
  }
  public TypeCode create_union_tc(String id, 
				  String name, TypeCode discriminator_type, 
				  org.omg.CORBA.UnionMember[] members)
  {
    return new
      jacorb.orb.TypeCode(org.omg.CORBA.TCKind._tk_union,id,name,discriminator_type,members);
  }
  public TypeCode create_wstring_tc(int bound)
  {
    return new jacorb.orb.TypeCode(org.omg.CORBA.TCKind._tk_wstring,bound);
  }
  /**
   * Called by the POA. 
   * Generates IOR 1.0 and 1.1, 1.1 contains also 1.0 profile. Only 1.1 and 
   * greater profiles contain codeset information about this server. <br>
   * If present, IORInterceptors will be invoked.
   */

  protected org.omg.IOP.IOR createIOR( String repId, byte[] key, 
				       boolean _transient, jacorb.poa.POA poa )
  {
    boolean endianness = false;
    jacorb.orb.CDROutputStream profileDataStream;
	
    // up to two profiles will be written
    TaggedProfile[] tps = null;
    String address = basicAdapter.getAddress();
    int port = basicAdapter.getPort();

    if( !_transient && jacorb.util.Environment.useImR() )
      {
	try
	  {
	    if (imr == null)
	      {
		// we're first to consult ImR
		ImplementationRepository _imr_impl = ImplementationRepositoryImpl.getImR(this);
		imr = RegistrationHelper.narrow(_imr_impl);
	      }
	    if (imr_info == null)
	      // we're first to get ImRInfo
	      imr_info = imr.get_imr_info();
		
	    // set host and port to ImR's values
	    address = imr_info.host;
	    port =  imr_info.port;
	    jacorb.util.Debug.output(2,"New persistent IOR created with ImR at " + address + ":" + port );
		
	  }
	catch (Exception _e)
	  {
	    jacorb.util.Debug.output(6, _e);
	    // sth went wrong,  host and port values of this ORB as set above are use
	  }
      }

    // additional multiple tagged components profile, used often for codeset
    // information ( bnv plus the SSL tagged component.)
    boolean useMulti = jacorb.util.Environment.charsetUpdateMulti();

    TaggedComponent[] components = null;

    Vector components_iiop_profile = new Vector();
    Vector components_multi_profile = new Vector();

    //if IORInterceptors are present, invoke them
    if (ior_interceptors != null){
      IORInfo info = new IORInfoImpl(this, poa, components_iiop_profile,
				     components_multi_profile);

      for (int i = 0; i < ior_interceptors.length; i++)
	try{
	  jacorb.util.Debug.output(2, "Invoking IORInterceptor " + ior_interceptors[i].name());
	  ior_interceptors[i].establish_components(info);
	}catch(Exception e){
	  jacorb.util.Debug.output(2, e);
	}
    }

    //all components for the profiles have to be present by now.
    switch( IIOPVersion.minor )
      {
      case 1: // create 1.1 profile  
	components = new TaggedComponent[components_iiop_profile.size()];
	for( int i = 0; i < components_iiop_profile.size(); i++)
	  components[i] = (TaggedComponent)components_iiop_profile.elementAt(i);
	      
	org.omg.IIOP.ProfileBody_1_1 pb1 = 
	  new org.omg.IIOP.ProfileBody_1_1(IIOPVersion, address, (short)port, 
					   key, components);
		
	// serialize the profile id 1, leave idx 0 for v.1.0 profile
	profileDataStream = new jacorb.orb.CDROutputStream(this);
	profileDataStream.write_boolean(endianness);
	org.omg.IIOP.ProfileBody_1_1Helper.write( profileDataStream, pb1);
	tps = new TaggedProfile[useMulti ? 3:2];
	tps[1] = new TaggedProfile(TAG_INTERNET_IOP.value, 
				    profileDataStream.getBufferCopy());
	// fall thru
      case 0: // create 1.0 profile
	org.omg.IIOP.ProfileBody_1_0 pb0;
	pb0 = new org.omg.IIOP.ProfileBody_1_0(new org.omg.IIOP.Version((byte)1,(byte)0),
					       address,(short)port,key);

	// serialize the profile id 1, leave idx 0 for v.1.0 profile
	profileDataStream = new jacorb.orb.CDROutputStream(this);
	profileDataStream.write_boolean(endianness);
	org.omg.IIOP.ProfileBody_1_0Helper.write( profileDataStream, pb0);
	if (tps == null) 
	  tps = new TaggedProfile[useMulti ? 2:1];

	tps[0] = new TaggedProfile(TAG_INTERNET_IOP.value, 
				   profileDataStream.getBufferCopy());

	// now optionally fill the last IOR profile with multicomponent
	if(useMulti)
	  {
	    components = new TaggedComponent[components_multi_profile.size()];
	    for( int i = 0; i < components_multi_profile.size(); i++)
	      components[i] = (TaggedComponent)components_multi_profile.elementAt(i);

	    profileDataStream = new jacorb.orb.CDROutputStream(this);
	    profileDataStream.write_boolean(endianness);
	    MultipleComponentProfileHelper.write(profileDataStream, components);
	    tps[tps.length-1] = new TaggedProfile(TAG_MULTIPLE_COMPONENTS.value,
						  profileDataStream.getBufferCopy());
	  }      
      }
	
    IOR _ior = new IOR( repId, tps);

    if (isApplet()) 
      {
	jacorb.orb.CDROutputStream out = new jacorb.orb.CDROutputStream(this);

	out.write_boolean(endianness);
	org.omg.IOP.IORHelper.write(out, _ior);
	byte bytes[] = out.getBufferCopy();


	StringBuffer sb = new StringBuffer("IOR:");
	for (int i=0; i<bytes.length; i++)
	  {
	    int b = bytes[i];
	    if(b<0) b+= 256;
	    int n1 = (b & 0xff) / 16;
	    int n2 = (b & 0xff) % 16;
	    int c1 = (n1 < 10) ? ('0' + n1) : ('a' + (n1 - 10));
	    int c2 = (n2 < 10) ? ('0' + n2) : ('a' + (n2 - 10));
	    sb.append((char)c1);
	    sb.append((char)c2);
	  }
	String ior_str = sb.toString();
	// IORTable.put( _ior, ior_str );
	//if applet, return proxified IOR
	
	jacorb.util.Debug.output(4,"ORB.createIOR, proxifying original ior " + _ior.hashCode());

	org.omg.CORBA.StringHolder proxyEntryId = new org.omg.CORBA.StringHolder();
	org.omg.IOP.IOR proxy_ior = new ParsedIOR(proxyObj.forward(ior_str,proxyEntryId)).getIOR();
	String proxy_ior_str = new ParsedIOR(proxyObj.forward(ior_str,proxyEntryId)).getIORString();

	proxyEntries.addElement(proxyEntryId.value);
	unproxyTable.put( proxy_ior_str, (new ParsedIOR(_ior)).getIORString() );

	jacorb.util.Debug.output(4,"ORB.createIOR, returning proxifyed ior " + proxy_ior.hashCode());

	return proxy_ior;
      }
    return _ior;
  }

  /** called by Delegate to retrieve an unproxyified, local IOR */
  org.omg.IOP.IOR unproxyfy(org.omg.IOP.IOR proxy_ior)
  {
    jacorb.util.Debug.output(3,"ORB.unproxyfy ior with oid: " + 
			     new String(new ParsedIOR(proxy_ior).get_object_key()));

    String iorString=(String)unproxyTable.get( (new ParsedIOR(proxy_ior)).getIORString());
	if( iorString == null )
	{
	    jacorb.util.Debug.output(3,"ORB.unproxyfy, no original ior found for " + (new ParsedIOR(proxy_ior)).getIORString());
	    return proxy_ior;
	}
	//loop until IOR is local
	String lastString=null;
	while (iorString!=null){
		jacorb.util.Debug.output(4,"ORB.unproxyfy, looping (IOR now:"+iorString+")");
		lastString=iorString;
		iorString=(String)unproxyTable.get(iorString);
	}
	jacorb.util.Debug.output(3,"ORB.unproxyfy, original ior: "+lastString);
	return  (new ParsedIOR(lastString)).getIOR();
	}

  public org.omg.CORBA.Current get_current()
  {
    return current;
  }
  public  org.omg.CORBA.Context get_default_context()
  {
    return null;
  }
  public org.omg.CORBA.Request get_next_response()
  {
    return null;
  }
  /**
   * used from the POA
   * @returns the basic adapter used by this ORB instance
   */

  public jacorb.orb.BasicAdapter getBasicAdapter()
  {
    if( basicAdapter == null )
      throw new RuntimeException("Adapters not initialized, call POA.init() first");
    return basicAdapter;
  }

  public String getDefaultContextURLString()
  {
    if( applet == null )
      return jacorb.util.Environment.rootNsURL();
    else
      return applet.getCodeBase().toString() + "_JacORB_NS";
  }
  public jacorb.poa.Current getPOACurrent()
  {
    if (poaCurrent == null)
      {
	poaCurrent = jacorb.poa.Current._Current_init();
      }
    return poaCurrent;
  }
  /** called by POA */

  public org.omg.CORBA.Object getReference(jacorb.poa.POA poa, 
					   byte[] object_key, String rep_id, 
					   boolean _transient)
  {
    try 
      {
	if( rep_id == null )
	  rep_id = "IDL:org.omg/CORBA/Object:1.0";

	org.omg.IOP.IOR ior = createIOR( rep_id, object_key, _transient, poa );
	Delegate d = new Delegate(this, ior);
	org.omg.CORBA.Object o = d.getReference(poa);

	ParsedIOR pior = new ParsedIOR( ior );
	knownReferences.put( pior.getIORString(), o );		
	return o;
      } 
    catch ( Exception e )
      {
	e.printStackTrace();
      }
    return null;
  }

  public jacorb.poa.POA getRootPOA()
  {
    if (rootpoa == null) 
      {
	rootpoa = jacorb.poa.POA._POA_init(this);
	rootpoa._addPOAEventListener( this );
	basicAdapter = new BasicAdapter( this, rootpoa );
      }
    return rootpoa;
  }

  public boolean hasClientMessageInterceptors( Object o )
  {
    return ( clientMessageInterceptorChain.size() > 0 || 
	     ( perObjectClientMessageInterceptors.get( o ) != null ));
  }

  public boolean hasServerMessageInterceptors()
  {
    return ( serverMessageInterceptorChain.size() > 0 );
  }
  public boolean isApplet()
  {
    return applet != null;
  }
  public String[] list_initial_services()
  {
    String s[] = {"NameService", "TradingService","RootPOA","POACurrent",
		  "DynAnyFactory", "DomainService", "PICurrent", "CodecFactory",
		  "TransactionCurrent"};
    return s;
  }

  /** 
   * An operation from the POAListener interface. Whenever a new POA is
   * created, the ORB is notified. 
   */

  public void poaCreated(jacorb.poa.POA poa)
  {
    /* 
     * Add this orb as the child poa's event listener. This means that the
     * ORB is always a listener to all poa events!
     */
    poa._addPOAEventListener(this);

    /* If the new POA has a persistent lifetime policy, it is registered
     * with the implementation repository if there is one and the 
     * use_imr policy is set via the "jacorb.orb.use_imr" property
     */

    if( poa.isPersistent())
      {
	persistentPOACount++;

	/* Lookup the implementation repository */

	if (imr == null && jacorb.util.Environment.useImR() )
	  {
	    ImplementationRepository _imr_impl = ImplementationRepositoryImpl.getImR(this);
	    imr = RegistrationHelper.narrow(_imr_impl);
	    if (imr == null || imr._non_existent())
	      {
		jacorb.util.Debug.output(3, "No connection to ImplementationRepository");
		return;
	      }
	  }

	if( imr != null )
	  {
	    try
	      {
		/* Register the POA  */
		    
		imr.register_poa(poa._getQualifiedName(), 
				 new String(jacorb.util.Environment.implName()), // logical server name
				 basicAdapter.getAddress(),
				 basicAdapter.getPort());
	      }
	    catch (Exception _e)
	      {
		jacorb.util.Debug.output(4, _e);
	      }
	  }
      }
  }
  public void poaStateChanged(jacorb.poa.POA poa, int new_state)
  {
    if( ( new_state == jacorb.poa.POAConstants.DESTROYED ||
	  new_state == jacorb.poa.POAConstants.INACTIVE )  && 
	poa.isPersistent() && imr != null
	)
      {
	/* if all persistent POAs in this server have gone down, unregister
	   the server */
	if( --persistentPOACount == 0 )
	  {
	    try
	      {
		imr.set_server_down(new String(jacorb.util.Environment.implName()));
	      }
	    catch (Exception _e)
	      {
		jacorb.util.Debug.output(2, _e);
	      }
	  }
      }
  }
  public  boolean poll_next_response()
  {
    return false;
  }


  public void postInterceptServerRequest( jacorb.orb.dsi.ServerRequest r )
  {
    /* no interception for locate requests/replies */
    if( r instanceof jacorb.orb.giop.LocateRequest ) return;

    if( jacorb.util.Environment.perObjectInterceptors())
      {
	Vector perObjectChain = (Vector)perObjectServerRequestInterceptors.get(r.getReference() );
	// per process interceptors

	if( perObjectChain != null )
	  {
	    for( int i = perObjectChain.size(); i > 0; i-- )
	      ((jacorb.orb.ServerRequestInterceptor)perObjectChain.elementAt(i-1)).
		post_invoke(r);
	  }
      }

    for( int i = serverRequestInterceptorChain.size(); i > 0; i-- )
      {
	((jacorb.orb.ServerRequestInterceptor)serverRequestInterceptorChain.elementAt(i-1)).post_invoke(r);
      }
	  
  }
  public void preInterceptServerRequest( jacorb.orb.dsi.ServerRequest r )
  {
    // per process interceptors

    for( Enumeration e = serverRequestInterceptorChain.elements(); e.hasMoreElements(); )
      ((ServerRequestInterceptor)e.nextElement()).pre_invoke(r);

    // per object interceptors (if any)
    if( jacorb.util.Environment.perObjectInterceptors())
      {
	Vector perObjectChain = (Vector)perObjectServerRequestInterceptors.get( r.getReference() );
	if( perObjectChain != null )
	  {
	    for( Enumeration e = perObjectChain.elements(); e.hasMoreElements(); )
	      ((ServerRequestInterceptor)e.nextElement()).
		pre_invoke(r);
	  }
      }
  }


  /**
   * service routine, opens a connection to URL and reads a string
   */

  private void readProxyIOR(java.net.URL proxyURL) 
    throws java.lang.Exception
  {
    java.io.BufferedReader in = 
      new java.io.BufferedReader(new java.io.InputStreamReader(proxyURL.openStream()) );

    String line = in.readLine();
    while (line.indexOf("IOR:") != 0)
      line = in.readLine();
    in.close();     //line contains the IOR now

    ParsedIOR pior = new ParsedIOR(line);
    org.omg.CORBA.Object po = this.string_to_object(line);
    proxyObj = jacorb.proxy.ForwarderHelper.narrow(po);
  }

  public void referenceCreated(org.omg.CORBA.Object o)
  {}

  /**
   *	remove per-process interceptor (client-side)
   */

  public void removeInterceptor( jacorb.orb.ClientMessageInterceptor intc )
  {
    clientMessageInterceptorChain.removeElement( intc );
  }
  /**
   *	remove per-process interceptor (client-side)
   */

  public void removeInterceptor( jacorb.orb.ClientRequestInterceptor intc )
  {
    interceptor_chain.removeElement( intc );
  }
  /**
   *	remove per-object interceptor (client-side)
   */

  public void removeInterceptor( Object o, 
				 jacorb.orb.ClientMessageInterceptor intc )
  {
    if( perObjectClientMessageInterceptors.containsKey( o )) 
      {
	((Vector)perObjectClientMessageInterceptors.get( o )).removeElement( intc );
      }
  }
  /**
   *	remove per-object interceptor (client-side)
   */

  public void removeInterceptor( Object o, 
				 jacorb.orb.ClientRequestInterceptor intc )
  {
    if( perObjectClientRequestInterceptors.containsKey( o )) 
      {
	((Vector)perObjectClientRequestInterceptors.get( o )).removeElement( intc );
      }
  }
  /**
   *	remove per-object interceptor (server-side)
   */

  public void removeInterceptor( Object o, jacorb.orb.ServerRequestInterceptor intc )
  {
    if( perObjectServerRequestInterceptors.containsKey( o )) 
      {
	((Vector)perObjectServerRequestInterceptors.get( o )).removeElement( intc );
      }
  }

  /**
   *	remove per-process interceptor (server-side)
   */

  public void removeServerInterceptor( jacorb.orb.ServerMessageInterceptor intc )
  {
    serverMessageInterceptorChain.removeElement( intc );
  }

  /**
   *	remove per-process interceptor (server-side)
   */

  public void removeServerInterceptor( jacorb.orb.ServerRequestInterceptor intc )
  {
    serverRequestInterceptorChain.removeElement( intc );
  }


  public org.omg.CORBA.Object resolve_initial_references(String identifier) 
    throws org.omg.CORBA.ORBPackage.InvalidName 
  {
    
    //jacorb.util.Debug.output(2, "Trying to resolve >>" + identifier + "<<");
    if (isApplet() & !applet_properties_read )
      {
	// jacorb.util.Debug.output(3,"Resolve changed (Applet)");
	initProxy();
	 
      }
    if (initial_references.containsKey(identifier))
      return (org.omg.CORBA.Object) initial_references.get(identifier);

    else{
      //jacorb.util.Debug.output(2, ">>" + identifier + "<< not set yet");
      org.omg.CORBA.Object obj = null;

//        if( identifier.equals("InterfaceRepository") )
//  	obj = jacorb.orb.ir.Repository.getRepository();      
//        else 
      if( identifier.equals("NameService") )
	{
	String ior_str = jacorb.util.ObjectUtil.readURL(jacorb.util.Environment.rootNsURL());
	obj = org.omg.CosNaming.NamingContextHelper.narrow(this.string_to_object(ior_str));
	} 
      else if( identifier.equals("TradingService") )
	{
	String trader_ior = jacorb.util.ObjectUtil.
	  readURL(jacorb.util.Environment.tradingServiceURL());
	obj = org.omg.CosTrading.TraderComponentsHelper.
	  narrow(this.string_to_object(trader_ior));
	} 
      else if( identifier.equals("RootPOA") )
	return (org.omg.CORBA.Object)getRootPOA();

      else if( identifier.equals("POACurrent") )
	return (org.omg.CORBA.Object)getPOACurrent();
      
      else if( identifier.equals("DomainService") )
	{
	  String ds_ior = jacorb.util.ObjectUtil.readURL
	    (jacorb.util.Environment.DomainServiceURL());

	  obj = jacorb.orb.domain.DomainHelper.narrow
	    (this.string_to_object(ds_ior));

	}
      else if( identifier.equals("SecurityCurrent") )
	obj = new jacorb.security.level2.Current((org.omg.CORBA.ORB)this);

      else if( identifier.equals("DynAnyFactory") )
	obj = (new jacorb.orb.dynany.DynAnyFactoryImpl( this ))._this();

      else if( identifier.equals("PICurrent") ){
	if (interceptor_manager == null)
	  return InterceptorManager.EMPTY_CURRENT;
	else
	  return interceptor_manager.getCurrent();
      }
      else if( identifier.equals("CodecFactory") )
	obj = new CodecFactoryImpl(this);

      else if( identifier.equals("TransactionCurrent") )
	obj = new jacorb.transaction.TransactionCurrentImpl();
      else
	throw new org.omg.CORBA.ORBPackage.InvalidName();
    
      if (obj != null){
	initial_references.put(identifier, obj);
	return obj;
      }
      else
	return null;
    }
  }

  /**
   * Register a reference, that will be returned on subsequent calls
   * to resove_initial_references(id). <br>
   * The references "RootPOA", "POACurrent" and "PICurrent" can be set,
   * but will not be resolved with the passed in references.
   *
   * @param id The references human-readable id, e.g. "MyService".
   * @param obj The objects reference.
   * @exception InvalidName A reference with id has already been registered.
   */
  public void register_initial_reference(String id, org.omg.CORBA.Object obj) 
    throws InvalidName {
    if (id == null || id.length() == 0 || 
	initial_references.containsKey(id))
      throw new InvalidName();
    else
      initial_references.put(id, obj);
   }

  public void run() 
  {   
    jacorb.util.Debug.output(4,"ORB run");
    try 
      {
	synchronized( orb_synch )
	  {
	    while( run  )
	      {
		orb_synch.wait();
	      }
	  }
      } 
    catch( java.lang.InterruptedException iex )
      {
	iex.printStackTrace();
      }		  
    jacorb.util.Debug.output(4,"ORB run, exit");
  }

  public  void send_multiple_requests_deferred(org.omg.CORBA.Request[] req)
  {
  }

  public  void send_multiple_requests_oneway(org.omg.CORBA.Request[] req)
  {
  }

  /**
   *	call interceptor (server-side) after invocation
   */

  public byte [] server_messageIntercept_post (byte [] buf)
  {
    byte [] tmp_buf = buf;
    for( Enumeration e = serverMessageInterceptorChain.elements(); e.hasMoreElements(); )
      tmp_buf = ((ServerMessageInterceptor)e.nextElement()).post_invoke(tmp_buf);

    return tmp_buf;
		
  }
  /**
   *	call interceptor (server-side) after invocation
   */

  public byte [] server_messageIntercept_pre (byte [] buf)
  {
    byte [] tmp_buf = buf;
    for( Enumeration e = serverMessageInterceptorChain.elements(); e.hasMoreElements(); )
      tmp_buf = ((ServerMessageInterceptor)e.nextElement()).pre_invoke(tmp_buf);

    return tmp_buf;
  }

  protected void set_parameters(String[] args, java.util.Properties props)
  {
      
    _args = args;
    _props = props;
    jacorb.util.Environment.addProperties( props );

    interceptorInit();
  }

  protected void set_parameters(java.applet.Applet app, java.util.Properties  props)
  {
    applet = app;
    _props = props;
    jacorb.util.Environment.addProperties( props );
    unproxyTable = new Hashtable();

    interceptorInit();
  }

  /**
   * This method retrieves the ORBInitializer-Names from the Environment,
   * and runs them.
   */ 
  private void interceptorInit(){
    //get instances from Environment
    Vector orb_initializers = jacorb.util.Environment.getORBInitializers();

    if (orb_initializers.size() > 0){
      ORBInitInfoImpl info = new ORBInitInfoImpl(this);

      //call pre_init in ORBInitializers
      for (int i = 0; i < orb_initializers.size(); i++)
	try{
	  ORBInitializer init = (ORBInitializer) orb_initializers.elementAt(i);
	  init.pre_init(info);
	}catch (Exception e){
	  jacorb.util.Debug.output(0, e);
	}
     
      //call post_init on ORBInitializers
      for (int i = 0; i < orb_initializers.size(); i++)
	try{
	  ORBInitializer init = (ORBInitializer) orb_initializers.elementAt(i);
	  init.post_init(info);
	}catch (Exception e){
	  jacorb.util.Debug.output(0, e);
      } 
      
      Vector client_interceptors = info.getClientInterceptors();
      Vector server_interceptors = info.getServerInterceptors();

      if ((server_interceptors.size() > 0) || 
	  (client_interceptors.size() > 0))
	interceptor_manager = new InterceptorManager(client_interceptors,
						     server_interceptors,
						     info.getSlotCount(),
						     this);
      
      // add PolicyFactories to ORB
      policy_factories = info.getPolicyFactories();

      // add IORInterceptors to ORB
      Vector ior_intercept = info.getIORInterceptors();

      if (ior_intercept.size() > 0){
	ior_interceptors = new IORInterceptor[ior_intercept.size()];
	//selection sort
	for (int j = 0; j < ior_interceptors.length; j++){
	  String min = ((IORInterceptor) ior_intercept.elementAt(0)).name();
	  int min_index = 0;

	  for(int _i = 1; _i < ior_intercept.size(); _i++)
	    if (min.compareTo(((IORInterceptor) ior_intercept.elementAt(_i)).name()) > 0){
	      min = ((IORInterceptor) ior_intercept.elementAt(_i)).name();
	      min_index = _i;
	    }
	   
	  ior_interceptors[j] = (IORInterceptor) ior_intercept.elementAt(min_index);
	  ior_intercept.removeElementAt(min_index);
	}
      }
    }
  }

  public void shutdown(boolean wait_for_completion) 
  {    
    jacorb.util.Debug.output(2,"prepare ORB for going down...");
    //release proxy objects
    for(int i=0;i<proxyEntries.size();i++){
      proxyObj.release((String)proxyEntries.elementAt(i));
    }

    synchronized( shutdown_synch )
      {
	jacorb.util.Debug.output(2,"ORB going down...");
	if( shutdown_in_progress && wait_for_completion )
	  {
	    synchronized( shutdown_synch )
	      {
		try
		  {
		    shutdown_synch.wait();
		  }
		catch( InterruptedException ie )
		  {}
		jacorb.util.Debug.output(2,"ORB shutdown complete (1)");
		return;
	      }
	  }	
	else if( shutdown_in_progress && !wait_for_completion )
	  {
	    jacorb.util.Debug.output(2,"ORB shutdown complete (2)");
	    return;
	  }
	    
	shutdown_in_progress = true;
      }

    if( rootpoa != null )
      rootpoa.destroy(true, wait_for_completion); 


    /* release all open connections */

	    jacorb.util.Debug.output(3,"ORB shutdown (cleaning up ORB...)");

    for( Enumeration e = connections.elements(); e.hasMoreElements(); )
      {
	((Connection)e.nextElement()).releaseConnection();
      }

    jacorb.util.Debug.output(3,"ORB shutdown (all connections release)");

    connections.clear();
    knownReferences.clear();

    bufferManager.release();

    jacorb.util.Debug.output(3,"ORB shutdown (all tables cleared)");

    /* notify all threads waiting for shutdown to complete */

    synchronized( shutdown_synch )
      {
	shutdown_synch.notifyAll();
      }
    jacorb.util.Debug.output(3,"ORB shutdown (threads notified)");

    /* notify all threads waiting in orb.run() */
    synchronized( orb_synch )
      {	       
	run = false;
	orb_synch.notifyAll();
      }
    jacorb.util.Debug.output(2,"ORB shutdown complete");
  }

  public org.omg.CORBA.Object string_to_object(String str) 
  {
    if( str == null )
      return null;

    ParsedIOR pior = new ParsedIOR( str );
    if( pior.isNull() )
      return null;
    else
      {
	return _getObject(pior);
      }
  }

  public void set_delegate(java.lang.Object wrapper) 
  {
    if( ! (wrapper instanceof org.omg.PortableServer.Servant) )
      throw new org.omg.CORBA.BAD_PARAM("Argument must be of type org.omg.PortableServer.Servant");
    else
      {
	jacorb.orb.ServantDelegate delegate = new jacorb.orb.ServantDelegate(this);
	((org.omg.PortableServer.Servant)wrapper)._set_delegate(delegate);
      }
  }

  /** 
   * forces the use of a proxy (by using a dummy applet)
   */
  public void useProxy()
  {
    applet=new java.applet.Applet();
  }

  public String object_to_string( org.omg.CORBA.Object obj)
  {
    return obj.toString();
  }

  public void perform_work() 
  {     
  }

  public boolean work_pending() 
  {     
    return false;
  }

  /**
   * Test, if the ORB has ClientRequestInterceptors <br>
   * Called by Delegate.
   */
  public boolean hasClientRequestInterceptors(){
    return (interceptor_manager != null) &&
      interceptor_manager.hasClientRequestInterceptors();
  }

  /**
   * Test, if the ORB has ServerRequestInterceptors <br>
   * Called by poa.RequestProcessor.
   */
  public boolean hasServerRequestInterceptors(){
    return (interceptor_manager != null) &&
      interceptor_manager.hasServerRequestInterceptors();
  }
  
  /**
   * Get the InterceptorManager, if present.
   *
   * @return the InterceptorManager, or null, if none is present.
   */
  public jacorb.orb.portableInterceptor.InterceptorManager getInterceptorManager(){
    return interceptor_manager;
  }
}




















