Hi,

I recently worked on getting a JDBC connection pool/DataSource working on
Tomcat 4.0b7.  I was interested in trying out the OracleConnectionCacheImpl
which Oracle provides in their JDBC drivers.

I eventually found out that the only way to make an instance of this class
available from JNDI was to create my own Factory class for it.  It seemed
to me like there should be a simpler way to do something like this so I
created a factory class (BeanFactory) which can instantiate any class which
conforms to the JavaBeans spec (i.e. most classes...).

What would I have to do to contribute this class so it ships as a standard
part of Tomcat?  The class has worked out well for my purposes but I am not
sure if the ClassLoader portion of the code is doing the right thing, I copied
it from one of the other factory classes in org.apache.naming.factory.

Using this class, I am able to make the Oracle DataSource implementation
available to all my servlets using the following xml fragment in server.xml

<DefaultContext>
  <Resource name="jdbc/myDataSource" auth="SERVLET"
    type="oracle.jdbc.pool.OracleConnectionCacheImpl"/>
  <ResourceParams name="jdbc/myDataSource">
    <parameter>
      <name>factory</name>
      <value>org.apache.naming.factory.BeanFactory</value>
    </parameter>
    <parameter><name>driverType</name><value>thin</value></parameter>
    <parameter><name>serverName</name><value>hue</value></parameter>
    <parameter><name>networkProtocol</name><value>tcp</value></parameter> 
    <parameter><name>databaseName</name><value>XXXX</value></parameter>
    <parameter><name>portNumber</name><value>NNNN</value></parameter>
    <parameter><name>user</name><value>XXXX</value></parameter>
    <parameter><name>password</name><value>XXXX</value></parameter>
    <parameter><name>maxLimit</name><value>5</value></parameter>
  </ResourceParams>
</DefaultContext>

Similarly, you could make ANY JavaBean available from jndi using this factory.

I have attached my implementation to this message if anybody is interested in
getting it incorporated into Tomcat.

Thanks,

        - Aner
package org.apache.naming.factory;

import java.util.Hashtable;
import java.util.Enumeration;
import javax.naming.Name;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.RefAddr;
import javax.naming.spi.ObjectFactory;
import org.apache.naming.ResourceRef;

import java.beans.Introspector;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;

import java.lang.reflect.Method;

/**
 * Object factory for any Object conforming to the JavaBean spec.
 */

public class BeanFactory
    implements ObjectFactory {

    // ----------------------------------------------------------- Constructors


    // -------------------------------------------------------------- Constants


    // ----------------------------------------------------- Instance Variables


    // --------------------------------------------------------- Public Methods


    // -------------------------------------------------- ObjectFactory Methods


    /**
     * Create a new Bean instance.
     * 
     * @param obj The reference object describing the Bean
     */
    public Object getObjectInstance(Object obj, Name name, Context nameCtx,
                                    Hashtable environment)
        throws NamingException {
System.out.println("BeanFactory.getObjectInstance()");
        if (obj instanceof ResourceRef) {
                        try {
                                
                                Reference ref = (Reference) obj;
                                String beanClassName = ref.getClassName();
                                Class beanClass = null;
                                ClassLoader tcl = 
Thread.currentThread().getContextClassLoader();
                                if (tcl != null) {
                                        try {
                                                beanClass = 
tcl.loadClass(beanClassName);
                                        } catch(ClassNotFoundException e) {            
                                 }
                                } else {
                                        try {
                                                beanClass = 
Class.forName(beanClassName);
                                        } catch(ClassNotFoundException e) {
e.printStackTrace();
                                        }
                                }
                                if(beanClass == null)
                                        throw new NamingException("Class not found: "
                                                + beanClassName);

                                BeanInfo bi = Introspector.getBeanInfo(beanClass);
                                PropertyDescriptor[] pda = bi.getPropertyDescriptors();

                                Object bean = beanClass.newInstance();

                                Enumeration e = ref.getAll();
                                while(e.hasMoreElements()) {
                                        RefAddr ra = (RefAddr) e.nextElement();
                                        String propName = ra.getType();
                                        if(propName.equals(Constants.FACTORY) ||
                                                propName.equals("scope") || 
propName.equals("auth"))
                                                continue;
                                        String value = (String)ra.getContent();

                                        Object[] valueArray = new Object[1];

                                        int i = 0;
                                        for(i=0;i<pda.length;i++) {
                                                if(pda[i].getName().equals(propName)) {
                                                        Class propType = 
pda[i].getPropertyType();
                                                        
if(propType.equals(String.class))
                                                                valueArray[0] = value;
                                                        else 
if(propType.equals(Character.class) || propType.equals(char.class))
                                                                valueArray[0] = new 
Character(value.charAt(0));
                                                        else 
if(propType.equals(Byte.class) || propType.equals(byte.class))
                                                                valueArray[0] = new 
Byte(value);
                                                        else 
if(propType.equals(Short.class) || propType.equals(short.class))
                                                                valueArray[0] = new 
Short(value);
                                                        else 
if(propType.equals(Integer.class) || propType.equals(int.class))
                                                                valueArray[0] = new 
Integer(value);
                                                        else 
if(propType.equals(Long.class) || propType.equals(long.class))
                                                                valueArray[0] = new 
Long(value);
                                                        else 
if(propType.equals(Float.class) || propType.equals(float.class))
                                                                valueArray[0] = new 
Float(value);
                                                        else 
if(propType.equals(Double.class) || propType.equals(double.class))
                                                                valueArray[0] = new 
Double(value);
                                                        else
                                                                throw new 
NamingException(
                                                                        "String 
conversion for property type '"+
                                                                        
propType.getName() + "' not available");

                                                        Method setProp = 
pda[i].getWriteMethod();
                                                        if(setProp != null)
                                                                setProp.invoke(bean, 
valueArray);
                                                        else
                                                                throw new 
NamingException(
                                                                        "Write not 
allowed for property: "+propName);
                                                        break;
                                                }
                                        }
                                        if(i==pda.length)
                                                throw new NamingException("No set 
method found for property: "+propName);
                                }
                                return bean;
                        } catch (java.beans.IntrospectionException ie) {
                                throw new NamingException(ie.getMessage());
                        } catch (java.lang.IllegalAccessException iae) {
                                throw new NamingException(iae.getMessage());
                        } catch (java.lang.InstantiationException ie2) {
                                throw new NamingException(ie2.getMessage());
                        } catch (java.lang.reflect.InvocationTargetException ite) {
                                throw new NamingException(ite.getMessage());
                        }
        } else {
            return null;
        }
    }
}

Reply via email to