package javax.ejbutil;

/**
 * javax.ejbutil - A collection of useful EJB utilities and objects.
 *
 *
 * Copyright 1999 by Chaeron Consulting Corporation.,
 * All rights reserved.
 * 
 * This software is the proprietary information of Chaeron Consulting
 * Corporation ("Proprietary Information").  You are granted the right
 * to use and modify this Proprietary Information provided you
 * retain this copyright notice and version/author history in the
 * source code.
 *
 * @version     1.2  jbi: Singleton to manage several servers
 * @version     1.1  jbi: JNDI/COSNaming
 * @version     1.0
 * @author      Andrzej Jan Taramina, Chaeron Consulting Corporation
 */
	
//***************************************************************************
//*
//*             Imports
//*
//***************************************************************************/

import java.rmi.*;
import java.util.*;
import java.lang.reflect.*;

import javax.ejb.*;
import javax.naming.*;


//***************************************************************************
//*
//*             EJBeanManager Class definition
//*
//***************************************************************************/

/**
 * Instances of the class </code>EJBeanManager</code> can be used to  
 * implement polymorphism of EJBHome objects and the creation/finding
 * of EJB Session or Entity beans.  The EJBeanManager will issue appropriate
 * bean creation/finder requests using an EJBHome object without the developer
 * needing to know which EJBHome object is actually being used.
 * <p> 
 * An EJBeanManager will keep track of a cache of EJBHome objects that are used
 * to create/find prior beans and will reuse a previously cached EJBHome object
 * where possible.
 * <p>
 * The following example uses a EJBeanManager object to create an arbitrary 
 * bean:
 * <p><pre><blockquote>
 * // This example uses JDNI naming for the EJBHome server product.
 *
 * EJBeanManager    bm;
 * Customer         customerBean;
 * String           customerHome    = "Customer";
 * String            customerId     = "02345";
 *
 * try {
 *    bm = new EJBeanManager( "com.ejbhome.naming.spi.rmi.RMIInitCtxFactory", "" );
 *    customer = (Customer)bm.create( customerHome, new Object[] { customerId } );
 * }
 *      	
 * catch( CreateException e ) {
 *     System.out.println( "Unable to create Customer bean: " + e.getMessage() );
 * }
 * catch( RemoteException e ) {
 *    System.out.println( "Problem creating Customer bean: " + e.getMessage() );
 * }
 *     
 * </blockquote></pre>
 *
 * @author  Andrzej Jan Taramina, Chaeron Consulting Corporation
 * @version 1.00, 02/08/99
 */
public final class EJBeanManager {

        //***************************************************************************
        //*
        //*             Constant definitions
        //*
        //***************************************************************************/

        private final static Object[] PRM_OBJECT_ARRAY_EMPTY = new Object[]{};	
        private final static Class[]  PRM_CLASS_ARRAY_EMPTY  = new Class[]{};
        private final static Class[]  PRM_CLASS_ARRAY_CORBA  = new Class[]{org.omg.CORBA.Object.class};
	
        //***************************************************************************
        //*
        //* SINGLETON
        //* This implementation allows EJBeanManager to serve clients that request
        //* proxies to EJBObjects from several EJB servers. For each server the
        //* singleton needs to know:
        //* + JNDI class
        //* + JNDI url
        //* Being a singleton several clients can reuse a single EJBeanInstance for
        //* each server, defined by the combination of JNDI class/url
        //*
        //***************************************************************************/
        /**
         * key:   jndiurl+jndiclass
         * value: javax.jndi.InitialContext instance for jndiurl+jndiclass
         */
        private static Hashtable stTblInstances = new Hashtable();

        //***************************************************************************
        //*
        //*             Attributes
        //*
        //***************************************************************************/
        private String                  namingFactory   = null;
        private String                  namingURL               = "";
        private InitialContext  namingCtx               = null;
	
        private Hashtable               homeCache               = new Hashtable();
        private Hashtable               homeHelperCache = new Hashtable();
        //***************************************************************************
        //*
        //*             CartBean methods
        //*
        //***************************************************************************/
	
        /**
        * Constructs an EJBeanManager with no JNDI naming information set.  You will need
        * to use the setNamingFactory() and setNamingURL methods() to set this information
        * or pass in a valid InitialContext before you can use the EJBeanManager to create or
        * find your beans.
        * <br>NOTE: SINGLETON private constructor
        *
        * @see     javax.ejbutil.EJBeanManager#setNamingFactory(String)
        * @see     javax.ejbutil.EJBeanManager#setNamingURL(String)
        */
        	
        private EJBeanManager() 
        {
                super();
        }    
        /**
        * Constructs an EJBeanManager specified NDI naming Factory and URL information set.
        * <br>NOTE: SINGLETON private constructor
        *
        * @param   factory   The JNDI Naming factory.
        * @param   factory   The JNDI Naming provider URL.
        */
        private EJBeanManager( String factory, String url ) 
        {
                super();
                	
                namingFactory   = factory;
                namingURL               = url;
        }    
        /**
        * Clear the cached EJBHome objects being maintained by this EJBeanManager
        */
	
        public void clearCache()
        {
                homeCache = new Hashtable();
        }
        /**
        * Create a new EJB bean (EJBObject) using an EJBHome object called <code>homeName</code>. If a 
        * prior bean was created/found with the same EJBHome object, then a cached version of the
        * EJBHome object will be used to perform the creation, otherwise a new EJBHome object
        * of the specified homeName will be created and cached for future use.
        *
        * @param   homeName   The JNDI name of the EJBHome object to be used to create the bean.
        * @return  The EJBObject that was created.  You will need to cast this to the correct type.
        * @exception  RemoteException  If there was a problem creating the bean.
        * @exception  CreateException  If the bean could not be created
        *              
        */
        public EJBObject create( String homeName ) throws RemoteException, CreateException
        {
                return create( homeName, (String)null );
        }
        /**
        * Create a new EJB bean (EJBObject) using an EJBHome object called <code>homeName</code>. If a 
        * prior bean was created/found with the same EJBHome object, then a cached version of the
        * EJBHome object will be used to perform the creation, otherwise a new EJBHome object
        * of the specified homeName will be created and cached for future use.
        *
        * @param   homeName   The JNDI name of the EJBHome object to be used to create the bean.
        * @param   parameters An Object[] array of the parameters required by the EJBHome create                      
        *                     method (as specified in the EJBHome interface).  The parameter types
        *                     must match exactly to those in the EJBHome interface otherwise the EJBHome
        *                     create method will not be correctly located and a <code>RemoteException</code>
        *                     will be thrown.
        * @return  The EJBObject that was created.  You will need to cast this to the correct type.
        * @exception  RemoteException  If there was a problem creating the bean.
        * @exception  CreateException  If the bean could not be created
        *              
        */
	
        public EJBObject create( String homeName, Object[] parameters ) throws RemoteException, CreateException
        {
                EJBObject       bean            = null;
                Method          create          = null;
                EJBHome         home        = null;
                Class[]         parmClass   = PRM_CLASS_ARRAY_EMPTY;

                // First go get the home object

                home = getHome( homeName );
        	
                // Create an array of parameter Classes
                if ( parameters != null ) {
                        parmClass       = new Class[ parameters.length ];

                        for( int i = 0; i < parameters.length; i++ ) {
                                parmClass[ i ] = parameters[ i ].getClass();
                        }
                } else {
                        parameters = PRM_OBJECT_ARRAY_EMPTY;
                }
        	
                // Lookup the create method based on input parameter classes
        	
                try {
                        create = home.getClass().getMethod( "create", parmClass );
                }
        	
                catch( NoSuchMethodException e ) {
                        throw( new RemoteException( "EJBeanManager: Unable to find create method matching passed in parameters: " + e.getMessage() ) );
                }
                catch( SecurityException e ) {
                        throw( new RemoteException( "EJBeanManager: Unable to access create method: " + e.getMessage() ) );
                }
        	
                //  If we found the right EJBHome create method, invoke it!
        	
                if( create != null ) {
                        try {
                                bean = (EJBObject)create.invoke( home, parameters );
                        }
                	
                        catch( InvocationTargetException e ) {
                                Throwable       targetException = e.getTargetException();
                        	
                                if( targetException instanceof CreateException ) {
                                        throw( (CreateException)targetException );
                                } else if( targetException instanceof RemoteException ) {
                                        throw( (RemoteException)targetException );
                                } else {
                                        throw( new RemoteException( "EJBeanManager: Exception creating EJBObject: " + targetException.getMessage() ) );
                                }
                }
                catch( IllegalAccessException e ) {
                                throw( new RemoteException( "EJBeanManager: Illegal Access exception creating EJBObject: " + e.getMessage() ) );
                }
                catch( IllegalArgumentException e ) {
                                throw( new RemoteException( "EJBeanManager: Illegal Argument exception creating EJBObject: " + e.getMessage() ) );
                }
                }
        	
                return( bean );
        }
        /**
        * Create a new EJB bean (EJBObject) using an EJBHome object called <code>homeName</code>
        * and a HomeHelper class called <code>homeHelperName</code>
        * <ul>
        * <li>
        * If a prior bean was created/found with the same EJBHome object, then a cached version of the
        * EJBHome object will be used to perform the creation, otherwise a new EJBHome object
        * of the specified homeName will be created and cached for future use.
        * <li>
        * If a prior Home bean was narrowed with the same HomeHelper object, then a cached version of the
        * HomeHelper object will be used to perform the narrow operation, otherwise a new HomeHelper object
        * of the specified homeHelperName will be created and cached for future use.
        * </ul>
        *
        * @param   homeName   The JNDI name of the EJBHome object to be used to create the bean.
        * @param   homeHelperClassName The full class name of the HomeHelper object to be used to narrow the CORBA
        *                               Object returned by COSNaming.
        * @return  The EJBObject that was created.  You will need to cast this to the correct type.
        * @exception  RemoteException  If there was a problem creating the bean.
        * @exception  CreateException  If the bean could not be created
        *              
        */
	
        public EJBObject create( String homeName, String homeHelperClassName )
                throws RemoteException, CreateException
        {
                return create( homeName, homeHelperClassName, null );
        }
        /**
        * Create a new EJB bean (EJBObject) using an EJBHome object called <code>homeName</code>
        * and a HomeHelper class called <code>homeHelperName</code>
        * <ul>
        * <li>
        * If a prior bean was created/found with the same EJBHome object, then a cached version of the
        * EJBHome object will be used to perform the creation, otherwise a new EJBHome object
        * of the specified homeName will be created and cached for future use.
        * <li>
        * If a prior Home bean was narrowed with the same HomeHelper object, then a cached version of the
        * HomeHelper object will be used to perform the narrow operation, otherwise a new HomeHelper object
        * of the specified homeHelperName will be created and cached for future use.
        * </ul>
        *
        * @param   homeName   The JNDI name of the EJBHome object to be used to create the bean.
        * @param   homeHelperClassName The full class name of the HomeHelper object to be used to narrow the CORBA
        *                               Object returned by COSNaming.
        * @param   parameters An Object[] array of the parameters required by the EJBHome create                      
        *                     method (as specified in the EJBHome interface).  The parameter types
        *                     must match exactly to those in the EJBHome interface otherwise the EJBHome
        *                     create method will not be correctly located and a <code>RemoteException</code>
        *                     will be thrown.
        * @return  The EJBObject that was created.  You will need to cast this to the correct type.
        * @exception  RemoteException  If there was a problem creating the bean.
        * @exception  CreateException  If the bean could not be created
        *              
        */
        public EJBObject create( String homeName, String homeHelperClassName, Object[] parameters )
                throws RemoteException, CreateException
        {
                EJBObject       bean            = null;
                Method          create          = null;
                EJBHome         home        = null;
                Class[]         parmClass   = PRM_CLASS_ARRAY_EMPTY;

                // First go get the home object

                home = getHome( homeName, namingCtx, homeHelperClassName );
        	
                // Create an array of parameter Classes
                if ( parameters != null ) {
                        parmClass       = new Class[ parameters.length ];

                        for( int i = 0; i < parameters.length; i++ ) {
                                parmClass[ i ] = parameters[ i ].getClass();
                        }
                } else {
                        parameters = PRM_OBJECT_ARRAY_EMPTY;
                }
        	
                // Lookup the create method based on input parameter classes
                try {
                        create = home.getClass().getMethod( "create", parmClass );
                }
                catch( NoSuchMethodException e ) {
                        throw( new RemoteException( "EJBeanManager: Unable to find create method matching passed in parameters: " + e.getMessage() ) );
                }
                catch( SecurityException e ) {
                        throw( new RemoteException( "EJBeanManager: Unable to access create method: " + e.getMessage() ) );
                }
        	
                //  If we found the right EJBHome create method, invoke it!
        	
                if( create != null ) {
                        try {
                                bean = (EJBObject)create.invoke( home, parameters );
                        }
                	
                        catch( InvocationTargetException e ) {
                                Throwable       targetException = e.getTargetException();
                        	
                                if( targetException instanceof CreateException ) {
                                        throw( (CreateException)targetException );
                                } else if( targetException instanceof RemoteException ) {
                                        throw( (RemoteException)targetException );
                                } else {
                                        throw( new RemoteException( "EJBeanManager: Exception creating EJBObject: " + targetException.getMessage() ) );
                                }
                }
                catch( IllegalAccessException e ) {
                                throw( new RemoteException( "EJBeanManager: Illegal Access exception creating EJBObject: " + e.getMessage() ) );
                }
                catch( IllegalArgumentException e ) {
                                throw( new RemoteException( "EJBeanManager: Illegal Argument exception creating EJBObject: " + e.getMessage() ) );
                }
                }
        	
                return( bean );
        }
        //***************************************************************************
        //*
        //*             JDNI Methods
        //*
        //***************************************************************************/
	
        /**
        * Create a new JNDI Naming InitialContext using the current Naming Factory and Provider URL.
        *                   
        * @return  The IntialContext that was created.
        * @exception  RemoteException  If there was a problem creating the InitialContext.
        */
	
        private InitialContext createNamingContext() throws RemoteException
        {
                Properties              props;
                InitialContext  ctx             = null;
        	
                if( namingFactory == null || namingURL == null ) {
                        throw( new RemoteException( "EJBeanManager: Cannot create JDNI Naming Context, factory or URL = null" ) );
                }
        	
                props = new Properties();
        	
                props.put( "java.naming.factory.initial", namingFactory );
                props.put( "java.naming.provider.url", namingURL );
        	
                try {
                        ctx = new InitialContext( props );
                }
        	
                catch( NamingException e ) {
                        throw( new RemoteException( "EJBeanManager: JNDI Exception getting InitialContext: " + e.getMessage() ) );
                }
        	
                return( ctx );
        }
        /**
        * Find an EJB bean (EJBObject) using an EJBHome object called <code>homeName</code>. If a 
        * prior bean was created/found with the same EJBHome object, then a cached version of the
        * EJBHome object will be used to perform the creation, otherwise a new EJBHome object
        * of the specified homeName will be created and cached for future use.
        *
        * @param   findMethodName   The name of the finder method to use as defined in the EJBHome interface.
        * @param   homeName             The JNDI name of the EJBHome object to be used to find the bean.
        * @param   primaryKey           The primary key value.
        * @return  The object(s) that were found.  This could be a single EJBObject or an Enumeration depending
        *          on what finder method is being called. You will need to cast this to the correct type.
        * @exception  RemoteException  If there was a problem finding the bean.
        * @exception  FinderException  If the bean could not be found
        *              
        */
	
        public Object find( String findMethodName, String homeName, Object[] parameters ) throws RemoteException, FinderException
        {
                Object          bean            = null;
                Method          finder          = null;
                EJBHome         home;
                Class[]         parmClass;
        	
                // Validate the find method name
        	
                if( !findMethodName.startsWith( "find" ) ) {
                        throw( new RemoteException( "EJBeanManager: Invalid Find Method Name: " + findMethodName ) );
                }

                // First go get the home object
        	
                home = getHome( homeName );
        	
                // Create an array of parameter Classes
        	
                parmClass       = new Class[ parameters.length ];
        	
                for( int i = 0; i < parameters.length; i++ ) {
                        parmClass[ i ] = parameters[ i ].getClass();
                }
        	
                // Lookup the finder method based on input parameter classes
        	
                try {
                        finder = home.getClass().getMethod( findMethodName, parmClass );
                }
        	
                catch( NoSuchMethodException e ) {
                        throw( new RemoteException( "EJBeanManager: Unable to get find method matching passed in parameters: " + e.getMessage() ) );
                }
                catch( SecurityException e ) {
                        throw( new RemoteException( "EJBeanManager: Unable to access find method: " + e.getMessage() ) );
                }
        	
                //  If we found the right EJBHome finder method, invoke it!
        	
                if( finder != null ) {
                        try {
                                bean = finder.invoke( home, parameters );
                        }
                	
                        catch( InvocationTargetException e ) {
                                Throwable       targetException = e.getTargetException();
                        	
                                if( targetException instanceof FinderException ) {
                                        throw( (FinderException)targetException );
                                } else if( targetException instanceof RemoteException ) {
                                        throw( (RemoteException)targetException );
                                } else {
                                        throw( new RemoteException( "EJBeanManager: Exception finding EJBObject: " + targetException.getMessage() ) );
                                }
                }
                catch( IllegalAccessException e ) {
                                throw( new RemoteException( "EJBeanManager: Illegal Access exception finding EJBObject: " + e.getMessage() ) );
                }
                catch( IllegalArgumentException e ) {
                                throw( new RemoteException( "EJBeanManager: Illegal Argument exception finding EJBObject: " + e.getMessage() ) );
                }
                }
        	
                return( bean );
        }
        //***************************************************************************
        //*
        //*             find Methods
        //*
        //***************************************************************************/
	
        /**
        * Find an EJB bean (EJBObject) by primary key, using an EJBHome object called <code>homeName</code>. 
        * If a prior bean was created/found with the same EJBHome object, then a cached version of the
        * EJBHome object will be used to perform the creation, otherwise a new EJBHome object
        * of the specified homeName will be created and cached for future use.
        *
        * @param   homeName     The JNDI name of the EJBHome object to be used to find the bean.
        * @param   primaryKey   The primary key value.
        * @return  The EJBObject that was found matching the primary key. You will need to cast this to the correct type.
        * @exception  RemoteException  If there was a problem finding the bean.
        * @exception  FinderException  If the bean could not be found
        *              
        */
	
        public EJBObject findByPrimaryKey( String homeName, Object primaryKey ) throws RemoteException, FinderException
        {
                EJBObject       bean            = null;
        	
                return( (EJBObject)find( "findByPrimaryKey", homeName, new Object[] { primaryKey } ) );	
        }
        /**
        * Get an EJBHome object from an <code>org.omg.CORBA.Object</code>. 
        * If the EJBHome object was previously created then a cached copy will be used.
        *                   
        * @param   pobj  The CORBA object we got from COSNaming
        * @param   phome The Home JNDI name
        * @param   phelperclass The HomeHelper class name
        * @return  The EJBHome that was created or cached previously.
        * @exception  RemoteException  If there was a problem getting the EJBHome.
        */
        private EJBHome getCOSNamingHome(org.omg.CORBA.Object pobj, String phome, String phhelperclass)
                throws RemoteException
        {
                Object         hhelper = null;
                EJBHome            home    = null;
        	
                // Go lookup a generic HomeHelper object based on the Home name
                hhelper = (EJBHome)homeHelperCache.get( phome );              // Is it already cached?
        	
                if( hhelper != null ) {
                        System.out.println( "EJBeanManager - Using cached EJBHomeHelper" );
                } else {
                        System.out.println( "EJBeanManager - Creating new EJBHomeHelper" );
                }
        	
                if( hhelper == null ) {
                        try {
                                Class  helperclass = Class.forName(phhelperclass);
                                Method mnarrow     = helperclass.getMethod("narrow",PRM_CLASS_ARRAY_CORBA);
                                home = (EJBHome)mnarrow.invoke(null,new Object[]{ pobj });
                                homeHelperCache.put( phome, home );

                        } catch(Throwable th) {
                                StringBuffer sb = new StringBuffer(this.getClass().getName());
                                sb.append(": getCOSNamingHome ");
                                sb.append(th.getClass().getName()).append(" : ");
                                sb.append(th.getMessage());
                                throw new RemoteException(sb.toString());
                        }
                }
                return home;
        }
/**
 * Gets an EJBeanManager for a given server
 * @return EJBeanManager
 * @param pjndiclass String JNDI provider class name
 * @param pjndiurl   String JNDI provider URL
 * @exception RemoteException
 */
public static EJBeanManager getEJBeanManager( String pjndiclass, String pjndiurl )
        throws RemoteException
{
        // IF we are the very first
        if ( stTblInstances == null ) {
                stTblInstances = new Hashtable();
        }
        // Check parameters
        if (( pjndiurl == null ) || ( pjndiclass == null)) {
                StringBuffer sb = new StringBuffer("getEJBeanManager: <");
                sb.append(pjndiurl).append("><").append(pjndiclass).append(">");
                sb.append(" bad parameter(s)");
                throw new RemoteException( sb.toString() );
        }
        String key = pjndiurl.trim().toUpperCase();

        EJBeanManager bm = (EJBeanManager)stTblInstances.get( key );

        // IF we are the first for this server
        if ( bm == null ) {
                bm = new EJBeanManager( pjndiclass, pjndiurl );
                stTblInstances.put( key, bm );
        }
        return bm;
}
        //***************************************************************************
        //*
        //*             EJBHome Methods
        //*
        //***************************************************************************/
	
        /**
        * Get an EJBHome object with the name <code>homeName</code>.  If the EJBHome object
        * was previously created then a cached copy will be used.  The current JNDI Naming context
        * will be used to find the EJBHome object.
        *                   
        * @param   homeName   The JNDI name of the EJBHome.
        * @return  The EJBHome that was created or cached previously.
        * @exception  RemoteException  If there was a problem getting the EJBHome.
        */
	
        private EJBHome getHome( String homeName ) throws RemoteException
        {
                return( getHome( homeName, namingCtx ) );
        }
        /**
        * Get an EJBHome object with the name <code>homeName</code> and the passed in JNDI naming context. 
        * If the EJBHome object was previously created then a cached copy will be used.
        *                   
        * @param   homeName   The JNDI name of the EJBHome.
        * @param   ctx   The JNDI Naming context to use for the lookup.
        * @return  The EJBHome that was created or cached previously.
        * @exception  RemoteException  If there was a problem getting the EJBHome.
        */
	
        private EJBHome getHome( String homeName, InitialContext ctx ) throws RemoteException
        {
                InitialContext          context;
                EJBHome                         home;
        	
                // Go lookup a generic EJBHome object based on it's name
        	
                home = (EJBHome)homeCache.get( homeName );            // Is it already cached?
        	
                if( home != null ) {
                        System.out.println( "EJBeanManager - Using cached EJBHome" );
                } else {
                        System.out.println( "EJBeanManager - Creating new EJBHome" );
                }
        	
                if( home == null ) {
                        if( ctx == null ) {
                                if( namingCtx == null ) {
                                        namingCtx       = createNamingContext();
                                }
                        	
                                context         = namingCtx;
                        } else {
                                context = ctx;
                        }
                	
                        try {
                                home = (EJBHome)context.lookup( homeName );
                                homeCache.put( homeName, home );
                        }
                        	
                        catch( NamingException e ) {
                                throw( new RemoteException( "EJBeanManager: JNDI Exception getting EJBHome: " + e.getMessage() ) );
                        }
                }
        	
                return( home );
        }
        /**
        * Get an EJBHome object with the name <code>homeName</code> and the passed in JNDI naming context. 
        * If the EJBHome object was previously created then a cached copy will be used.
        *                   
        * @param   homeName     The JNDI name of the EJBHome.
        * @param   ctx          The JNDI Naming context to use for the lookup.
        * @param   phelperclass The HomeHelper class name
        * @return  The EJBHome that was created or cached previously.
        * @exception  RemoteException  If there was a problem getting the EJBHome.
        */
	
        private EJBHome getHome( String homeName, InitialContext ctx, String phelperclass )
                throws RemoteException
        {
                Object         obj;
                InitialContext context;
                EJBHome            home;
        	
                // Go lookup a generic EJBHome object based on it's name
                home = (EJBHome)homeCache.get( homeName );            // Is it already cached?
        	
                if( home != null ) {
                        System.out.println( "EJBeanManager - Using cached EJBHome" );
                } else {
                        System.out.println( "EJBeanManager - Creating new EJBHome" );
                }
        	
                if( home == null ) {
                        if( ctx == null ) {
                                if( namingCtx == null ) {
                                        namingCtx = createNamingContext();
                                }
                                context = namingCtx;
                        } else {
                                context = ctx;
                        }
                	
                        try {
                                //home = (EJBHome)context.lookup( homeName );
                                obj = context.lookup( homeName );
                                // COSNaming Service
                                if (obj instanceof org.omg.CORBA.Object) {
                                        home = getCOSNamingHome((org.omg.CORBA.Object)obj, homeName, phelperclass);
                                }
                                homeCache.put( homeName, home );
                        }
                        	
                        catch( NamingException e ) {
                                throw( new RemoteException( "EJBeanManager: JNDI Exception getting EJBHome: " + e.getMessage() ) );
                        }
                }
        	
                return( home );
        }
        /**
        * Get the JNDI Naming IntialContext used by this EJBeanManager
        *
        * @see     javax.ejbutil.EJBeanManager#setNamingContext(InitialContext)
        */
	
        public InitialContext getNamingContext()
        {
                return( namingCtx );
        }
        //***************************************************************************
        //*
        //*             Accessor Methods
        //*
        //***************************************************************************/
	
        /**
        * Get the JNDI Naming Factory being used by this EJBeanManager
        *
        * @see     javax.ejbutil.EJBeanManager#setNamingFactory(String)
        */
	
        public String getNamingFactory()
        {
                return( namingFactory );
        }
        /**
        * Get the JNDI Naming Provider URL being used by this EJBeanManager
        *
        * @see     javax.ejbutil.EJBeanManager#setNamingURL(String)
        */
	
        public String getNamingURL()
        {
                return( namingURL );
        }
/**
 * Test
 * @param args java.lang.String[]
 */
public static void main(String args[]) {
        try {
                String jndiname  = "WfacBDCacheSession";
                String jndiurl   = "iiop:///";
                String jndiclass = "com.ibm.jndi.CosNaming.CNInitialContextFactory";
                String helperclass = "wfac.ejb.bd.IWfacBDCacheSessionHomeHelper";

                EJBeanManager  bm   = null;
                InitialContext ctx  = null;
                EJBHome        home = null;
                Object         obj  = null;

                bm   = new EJBeanManager( jndiclass, jndiurl );
                ctx  = bm.createNamingContext();
                home = bm.getHome( jndiname, ctx, helperclass );
                System.out.println(" 1: getHome <"+home.getClass().getName()+">");

                obj = bm.create( jndiname, helperclass, new Object[]{} );
                // String consultaDescripcion(String ptbl, String pclv)
                Class cls = obj.getClass();
                Method md = cls.getMethod("consultaDescripcion", new Class[]{String.class,String.class});
                String res = (String)md.invoke( obj, new Object[]{"WACO_MIGA_T_AUX_EST_ORD","F"} );

                System.out.println(" 2: create <"+obj.getClass().getName()+">");
                System.out.println("           <"+obj+">");
                System.out.println("    Result <"+res+">");

                obj = bm.create( jndiname, helperclass );
                System.out.println(" 3: create <"+obj.getClass().getName()+">");
                System.out.println("           <"+obj+">");

                // Use Singleton
                bm   = EJBeanManager.getEJBeanManager( jndiclass, jndiurl );
                ctx  = bm.createNamingContext();
                home = bm.getHome( jndiname, ctx, helperclass );
                System.out.println(" 4: getHome <"+home.getClass().getName()+">");

                obj = bm.create( jndiname, helperclass, new Object[]{} );
                System.out.println(" 5: create <"+obj.getClass().getName()+">");
                System.out.println("           <"+obj+">");

                obj = bm.create( jndiname, helperclass );
                System.out.println(" 6: create <"+obj.getClass().getName()+">");
                System.out.println("           <"+obj+">");

        } catch(Throwable th) {
                System.out.println("Error! "+th.getClass().getName()+"/"+th.getMessage());
        }
}
        /**
        * Set the JNDI IntialContext being used by this EJBeanManager
        *
        * @param   ctx   The JNDI InitialContext to be used.
        * @see     javax.ejbutil.EJBeanManager#getNamingContext()
        */
	
        public void setNamingContext( InitialContext ctx )
        {
                namingCtx = ctx;
        }
        /**
        * Set the JNDI Naming Factory being used by this EJBeanManager
        *
        * @param   factory   The JNDI Naming factory.
        * @see     javax.ejbutil.EJBeanManager#getNamingFactory()
        */
	
        public void setNamingFactory( String factory )
        {
                namingFactory   = factory;
        }
        /**
        * Set the JNDI Naming Provider URL being used by this EJBeanManager
        *
        * @param   factory   The JNDI provider URL.
        * @see     javax.ejbutil.EJBeanManager#getNamingURL()
        */
	
        public void setNamingURL( String url )
        {
                namingURL               = url;
        }
}