You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by fh...@apache.org on 2009/12/18 19:12:51 UTC

svn commit: r892330 - in /tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc: naming/ naming/GenericNamingResourcesFactory.java pool/DataSourceFactory.java

Author: fhanik
Date: Fri Dec 18 18:12:50 2009
New Revision: 892330

URL: http://svn.apache.org/viewvc?rev=892330&view=rev
Log:
Add in support to link up the connection pool to a DataSource or XADataSource through JNDI


Added:
    tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/
    tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java   (with props)
Modified:
    tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java

Added: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java?rev=892330&view=auto
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java (added)
+++ tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java Fri Dec 18 18:12:50 2009
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.tomcat.jdbc.naming;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import javax.naming.spi.ObjectFactory;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+/**
+ * Simple way of configuring generic resources by using reflection.
+ * Example usage:
+ * <pre><code>
+ * &lt;Resource factory=&quot;org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory&quot;
+ *              name=&quot;jdbc/test&quot;
+ *              type=&quot;org.apache.derby.jdbc.ClientXADataSource&quot;
+ *              databaseName=&quot;sample&quot;
+ *              createDatabase=&quot;create&quot;
+ *              serverName=&quot;localhost&quot;
+ *              port=&quot;1527&quot;/&gt;
+ * </code></pre>
+ * 
+ */
+public class GenericNamingResourcesFactory implements ObjectFactory {
+    private static final Log log = LogFactory.getLog(GenericNamingResourcesFactory.class);
+    @Override
+    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
+        if ((obj == null) || !(obj instanceof Reference)) {
+            return null;
+        }
+        Reference ref = (Reference) obj;
+        Enumeration<RefAddr> refs = ref.getAll();
+        
+        String type = ref.getClassName();
+        Object o = Class.forName(type).newInstance();
+        
+        while (refs.hasMoreElements()) {
+            RefAddr addr = refs.nextElement();
+            String param = addr.getType();
+            String value = null;
+            if (addr.getContent()!=null) {
+                value = addr.getContent().toString();
+            }
+            if (setProperty(o, param, value,false)) {
+                
+            } else {
+                log.debug("Property not configured["+param+"]. No setter found on["+o+"].");
+            }
+        }
+        return o;
+    }
+
+    public static boolean setProperty(Object o, String name, String value,boolean invokeSetProperty) {
+        if (log.isDebugEnabled())
+            log.debug("IntrospectionUtils: setProperty(" +
+                    o.getClass() + " " + name + "=" + value + ")");
+
+        String setter = "set" + capitalize(name);
+
+        try {
+            Method methods[] = o.getClass().getMethods();
+            Method setPropertyMethodVoid = null;
+            Method setPropertyMethodBool = null;
+
+            // First, the ideal case - a setFoo( String ) method
+            for (int i = 0; i < methods.length; i++) {
+                Class<?> paramT[] = methods[i].getParameterTypes();
+                if (setter.equals(methods[i].getName()) && paramT.length == 1
+                        && "java.lang.String".equals(paramT[0].getName())) {
+
+                    methods[i].invoke(o, new Object[] { value });
+                    return true;
+                }
+            }
+
+            // Try a setFoo ( int ) or ( boolean )
+            for (int i = 0; i < methods.length; i++) {
+                boolean ok = true;
+                if (setter.equals(methods[i].getName())
+                        && methods[i].getParameterTypes().length == 1) {
+
+                    // match - find the type and invoke it
+                    Class<?> paramType = methods[i].getParameterTypes()[0];
+                    Object params[] = new Object[1];
+
+                    // Try a setFoo ( int )
+                    if ("java.lang.Integer".equals(paramType.getName())
+                            || "int".equals(paramType.getName())) {
+                        try {
+                            params[0] = new Integer(value);
+                        } catch (NumberFormatException ex) {
+                            ok = false;
+                        }
+                    // Try a setFoo ( long )
+                    }else if ("java.lang.Long".equals(paramType.getName())
+                                || "long".equals(paramType.getName())) {
+                            try {
+                                params[0] = new Long(value);
+                            } catch (NumberFormatException ex) {
+                                ok = false;
+                            }
+
+                        // Try a setFoo ( boolean )
+                    } else if ("java.lang.Boolean".equals(paramType.getName())
+                            || "boolean".equals(paramType.getName())) {
+                        params[0] = new Boolean(value);
+
+                        // Try a setFoo ( InetAddress )
+                    } else if ("java.net.InetAddress".equals(paramType
+                            .getName())) {
+                        try {
+                            params[0] = InetAddress.getByName(value);
+                        } catch (UnknownHostException exc) {
+                            if (log.isDebugEnabled())
+                                log.debug("IntrospectionUtils: Unable to resolve host name:" + value);
+                            ok = false;
+                        }
+
+                        // Unknown type
+                    } else {
+                        if (log.isDebugEnabled())
+                            log.debug("IntrospectionUtils: Unknown type " +
+                                    paramType.getName());
+                    }
+
+                    if (ok) {
+                        methods[i].invoke(o, params);
+                        return true;
+                    }
+                }
+
+                // save "setProperty" for later
+                if ("setProperty".equals(methods[i].getName())) {
+                    if (methods[i].getReturnType()==Boolean.TYPE){
+                        setPropertyMethodBool = methods[i];
+                    }else {
+                        setPropertyMethodVoid = methods[i];    
+                    }
+                    
+                }
+            }
+
+            // Ok, no setXXX found, try a setProperty("name", "value")
+            if (setPropertyMethodBool != null || setPropertyMethodVoid != null) {
+                Object params[] = new Object[2];
+                params[0] = name;
+                params[1] = value;
+                if (setPropertyMethodBool != null) {
+                    try {
+                        return (Boolean) setPropertyMethodBool.invoke(o, params);
+                    }catch (IllegalArgumentException biae) {
+                        //the boolean method had the wrong
+                        //parameter types. lets try the other
+                        if (setPropertyMethodVoid!=null) {
+                            setPropertyMethodVoid.invoke(o, params);
+                            return true;
+                        }else {
+                            throw biae;
+                        }
+                    }
+                } else {
+                    setPropertyMethodVoid.invoke(o, params);
+                    return true;
+                }
+            }
+
+        } catch (IllegalArgumentException ex2) {
+            log.warn("IAE " + o + " " + name + " " + value, ex2);
+        } catch (SecurityException ex1) {
+            if (log.isDebugEnabled())
+                log.debug("IntrospectionUtils: SecurityException for " +
+                        o.getClass() + " " + name + "=" + value + ")", ex1);
+        } catch (IllegalAccessException iae) {
+            if (log.isDebugEnabled())
+                log.debug("IntrospectionUtils: IllegalAccessException for " +
+                        o.getClass() + " " + name + "=" + value + ")", iae);
+        } catch (InvocationTargetException ie) {
+            if (log.isDebugEnabled())
+                log.debug("IntrospectionUtils: InvocationTargetException for " +
+                        o.getClass() + " " + name + "=" + value + ")", ie);
+        }
+        return false;
+    } 
+    
+    public static String capitalize(String name) {
+        if (name == null || name.length() == 0) {
+            return name;
+        }
+        char chars[] = name.toCharArray();
+        chars[0] = Character.toUpperCase(chars[0]);
+        return new String(chars);
+    }
+
+}

Propchange: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java?rev=892330&r1=892329&r2=892330&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java (original)
+++ tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java Fri Dec 18 18:12:50 2009
@@ -24,7 +24,9 @@
 
 import javax.management.ObjectName;
 import javax.naming.Context;
+import javax.naming.InitialContext;
 import javax.naming.Name;
+import javax.naming.NamingException;
 import javax.naming.RefAddr;
 import javax.naming.Reference;
 import javax.naming.spi.ObjectFactory;
@@ -207,7 +209,7 @@
             }
         }
 
-        return createDataSource(properties);
+        return createDataSource(properties,nameCtx);
     }
     
     public static PoolConfiguration parsePoolProperties(Properties properties) throws IOException{
@@ -434,7 +436,8 @@
         value = properties.getProperty(PROP_DATASOURCE);
         if (value != null) {
             //this should never happen
-            log.error("Can't set dataSource property as a string, this must be a javax.sql.DataSource object.");
+            throw new IllegalArgumentException("Can't set dataSource property as a string, this must be a javax.sql.DataSource object.");
+            
         }
         
         value = properties.getProperty(PROP_DATASOURCE_JNDI);
@@ -452,15 +455,40 @@
      * @throws Exception if an error occurs creating the data source
      */
     public static DataSource createDataSource(Properties properties) throws Exception {
+        return createDataSource(properties,null);
+    }
+    public static DataSource createDataSource(Properties properties,Context context) throws Exception {
         PoolConfiguration poolProperties = DataSourceFactory.parsePoolProperties(properties);
+        if (poolProperties.getDataSourceJNDI()!=null && poolProperties.getDataSource()==null) {
+            javax.sql.DataSource jndiDS = null;
+            try {
+                if (context!=null) {
+                    jndiDS = (javax.sql.DataSource)context.lookup(poolProperties.getDataSourceJNDI());
+                } else {
+                    log.warn("dataSourceJNDI property is configued, but local JNDI context is null.");
+                }
+            } catch (NamingException e) {
+                log.debug("The name \""+poolProperties.getDataSourceJNDI()+"\" can not be found in the local context.");
+            }
+            if (jndiDS==null) {
+                try {
+                    context = (Context) (new InitialContext());
+                    jndiDS = (javax.sql.DataSource)context.lookup(poolProperties.getDataSourceJNDI());
+                } catch (NamingException e) {
+                    log.warn("The name \""+poolProperties.getDataSourceJNDI()+"\" can not be found in the InitialContext.");
+                }
+            }
+            if (jndiDS!=null) {
+                poolProperties.setDataSource(jndiDS);
+            }
+        }
         org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);
-        
-        //initialize the pool itself
+        //initialise the pool itself
         dataSource.createPool();
         // Return the configured DataSource instance
         return dataSource;
     }
-
+    
     /**
      * <p>Parse properties from the string. Format of the string must be [propertyName=property;]*<p>
      * @param propText



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