You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by "Durfee, Bernard" <Be...@suny.edu> on 2005/01/05 22:00:34 UTC

Bug Fix - Sort of...

Hello,
 This is my first post to the list, so I am not sure of the protocol for
making contributions to the project. I had some problems getting a data
source configured in Tomcat 5. My data source factory was not being
used. After some struggle I found that I needed to put the factory name
as an attribute on the &nbsp;Resource> element. So the
&nbsp;ResourceParams> element seems to be ignored. 

HOWEVER! In the process of pulling out my hair to figure out what was
going on I 'fixed' the org.apache.naming.factory.ResourceFactory by
refactoring, commenting, and enhancing the exception messages to spit
out some information instead of just a one liner! These modifications
are below. I also added some comments to the code so that future
developers can figure out what the heck is going on. I would love to
contribute this to the project, I've read about 10 other threads on
various web-sites of people frustrated by the lack of error messages
related to this bug.

==============================
/*
 * Copyright 1999,2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.naming.factory;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;

/**
 * Object factory for Resources.
 * 
 * @author Remy Maucherat
 * @version $Revision: 1.3 $ $Date: 2004/02/27 14:58:54 $
 */
public class ResourceFactory implements ObjectFactory {

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

  // --------------------------------------------------------------
Constants
  private static final String DATASOURCE = "javax.sql.DataSource";

  private static final String MAIL_SESSION = "javax.mail.Session";

  private static final String DATASOURCE_FACTORY_PROPERTY =
"javax.sql.DataSource.Factory";

  private static final String MAIL_SESSION_FACTORY_PROPERTY =
"javax.mail.Session.Factory";

  private static final String MAIL_SESSION_FACTORY =
"org.apache.naming.factory.MailSessionFactory";

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

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

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

  /**
   * Creates a new object using the specified factory
   * 
   * <ol>
   *   <li>The factory class name is determined</li>
   *   <ol>
   *     <li>The class name is retrieved from the Reference object</li>
   *     <li>If the class name is not found, a default factory is
created for the desired object</li>
   *     <li>If the class name is still not found, an exception is
thrown</li>
   *   </ol>
   *   </li>
   *   <li>Once the factory class name is determined, an instance is
created and used to create the desired object</li> 
   * </ol>
   * 
   * @param resourceRefObject The reference object describing the
DataSource
   * @param name Passed to factory
   * @param nameCtx Passed to factory
   * @param environment Passed to factory
   * @return The object instance; null if the 'referenceObject'
parameter is not an instance of Reference
   * @throws NamingException When the factory could not be created
   * @throws Exception When the factory could not create the obect
   */
  public Object getObjectInstance(Object referenceObject, Name name,
Context nameCtx, Hashtable environment)
      throws Exception {
    // Make sure the Reference was passed in
    if(!(referenceObject instanceof Reference)) {
      return null;
    }

    // Cast the incoming resource reference
    Reference reference = (Reference) referenceObject;

    // We need to create the factory class
    final Class factoryClass;

    // First check to see if a factory name has been supplied with the
reference
    RefAddr factoryRefAddr = reference.get(Constants.FACTORY);
    if(factoryRefAddr != null) {
      // If so, get the classname of the specified factory
      String factoryClassName = factoryRefAddr.getContent().toString();

      // Get the context class loader; may not be available
      ClassLoader tcl = Thread.currentThread().getContextClassLoader();
      if(tcl != null) {
        // Use the context class loader 
        try {
          factoryClass = tcl.loadClass(factoryClassName);
        }
        catch(ClassNotFoundException exception) {
          NamingException namingException = new NamingException("Could
not load resource factory class '"
              + factoryClassName + "' using the context class loader,
ClassNotFoundException:" + exception.getMessage());
          namingException.setRootCause(exception);
          throw namingException;
        }
      }
      else {
        // No context class loader; so try the standard class loader
        try {
          factoryClass = Class.forName(factoryClassName);
        }
        catch(ClassNotFoundException exception) {
          NamingException namingException = new NamingException("Could
not load resource factory class '"
              + factoryClassName + "' using the JVM class loader,
ClassNotFoundException:" + exception.getMessage());
          namingException.setRootCause(exception);
          throw namingException;
        }
      }
    }
    else {
      // Determine the requested class name
      String objectClassName = reference.getClassName();

      // No factory classname was supplied, so check to see if we know
of the default factory
      final String factoryClassName;
      if(objectClassName.equals(DATASOURCE)) {
        factoryClassName =
System.getProperty(DATASOURCE_FACTORY_PROPERTY,
Constants.DBCP_DATASOURCE_FACTORY);
      }
      else if(objectClassName.equals(MAIL_SESSION)) {
        factoryClassName =
System.getProperty(MAIL_SESSION_FACTORY_PROPERTY, MAIL_SESSION_FACTORY);
      }
      else {
        throw new NamingException(
            "Unable to determine class name of factory for objects of
type '"
                + objectClassName
                + "', the factory class name was not defined in the
resource reference. Default factories are only known for objects of type
["
                + DATASOURCE + ", " + MAIL_SESSION + "]");
      }

      // Instantiate the default factory
      try {
        factoryClass = Class.forName(factoryClassName);
      }
      catch(Throwable throwable) {
        NamingException namingException = new NamingException("Could not
instantiate factory class '"
            + factoryClassName + "': " + throwable.getMessage());
        namingException.setRootCause(throwable);
        throw namingException;
      }
    }

    // Create an instance of the factory
    final ObjectFactory factory;
    try {
      factory = (ObjectFactory) factoryClass.newInstance();
    }
    catch(Throwable throwable) {
      NamingException namingException = new NamingException("Could not
instantiate factory class '"
          + factoryClass.toString() + "': " + throwable.getMessage());
      namingException.setRootCause(throwable);
      throw namingException;
    }

    // Use the factory to create the desired object
    Object newObject = factory.getObjectInstance(reference, name,
nameCtx, environment);

    return newObject;
  }
}
===============================

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org