You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by dj...@apache.org on 2006/02/21 18:12:58 UTC

svn commit: r379536 - in /db/derby/code/trunk/java: client/org/apache/derby/client/ client/org/apache/derby/jdbc/ testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/

Author: djd
Date: Tue Feb 21 09:12:57 2006
New Revision: 379536

URL: http://svn.apache.org/viewcvs?rev=379536&view=rev
Log:
DERBY-446 (partial) Make ClientDataSource use public setter and getter methods as standard
for its Java bean properties. Avoids security exceptions or requiring extreme security
permissions in order to create a Reference from the data source. Staged development, subsequent
commits will clean up some of the remants of the old code, by removing or moving the "propertyKey_*" fields.


Modified:
    db/derby/code/trunk/java/client/org/apache/derby/client/ClientDataSourceFactory.java
    db/derby/code/trunk/java/client/org/apache/derby/jdbc/ClientBaseDataSource.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/dataSourceReference_app.properties

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/ClientDataSourceFactory.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/client/org/apache/derby/client/ClientDataSourceFactory.java?rev=379536&r1=379535&r2=379536&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/ClientDataSourceFactory.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/ClientDataSourceFactory.java Tue Feb 21 09:12:57 2006
@@ -20,6 +20,12 @@
 
 package org.apache.derby.client;
 
+import java.lang.reflect.Method;
+import java.util.Enumeration;
+
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+
 import org.apache.derby.jdbc.ClientConnectionPoolDataSource;
 import org.apache.derby.jdbc.ClientDataSource;
 import org.apache.derby.jdbc.ClientXADataSource;
@@ -85,8 +91,65 @@
         }
 
         // Fill in the data source object shell with values from the jndi reference.
-        ds.hydrateFromReference(ref);
+        ClientDataSourceFactory.setBeanProperties(ds, ref);
 
         return ds;
+    }
+    
+    /** Reflect lookup for Java bean method taking a single String arg */
+    private static final Class[] STRING_ARG = { "".getClass() };
+    /** Reflect lookup for Java bean method taking a single int arg */
+    private static final Class[] INT_ARG = { Integer.TYPE };
+    /** Reflect lookup for Java bean method taking a single boolean arg */
+    private static final Class[] BOOLEAN_ARG = { Boolean.TYPE };
+    /** Reflect lookup for Java bean method taking a single short arg */
+    private static final Class[] SHORT_ARG = { Short.TYPE };
+    
+    /*
+     * Set the Java bean properties for an object from its Reference. The
+     * Reference contains a set of StringRefAddr values with the key being the
+     * bean name and the value a String representation of the bean's value. This
+     * code looks for setXXX() method where the set method corresponds to the
+     * standard bean naming scheme and has a single parameter of type String,
+     * int, boolean or short.
+     */
+    private static void setBeanProperties(Object ds, Reference ref)
+            throws Exception {
+
+        for (Enumeration e = ref.getAll(); e.hasMoreElements();) {
+
+            RefAddr attribute = (RefAddr) e.nextElement();
+
+            String propertyName = attribute.getType();
+
+            String value = (String) attribute.getContent();
+
+            String methodName = "set"
+                    + propertyName.substring(0, 1).toUpperCase(
+                            java.util.Locale.ENGLISH)
+                    + propertyName.substring(1);
+
+            Method m;
+
+            Object argValue;
+            try {
+                m = ds.getClass().getMethod(methodName, STRING_ARG);
+                argValue = value;
+            } catch (NoSuchMethodException nsme) {
+                try {
+                    m = ds.getClass().getMethod(methodName, INT_ARG);
+                    argValue = Integer.valueOf(value);
+                } catch (NoSuchMethodException nsme2) {
+                    try {
+                        m = ds.getClass().getMethod(methodName, BOOLEAN_ARG);
+                        argValue = Boolean.valueOf(value);
+                    } catch (NoSuchMethodException nsme3) {
+                        m = ds.getClass().getMethod(methodName, SHORT_ARG);
+                        argValue = Short.valueOf(value);
+                    }
+                }
+            }
+            m.invoke(ds, new Object[] { argValue });
+        }
     }
 }

Modified: db/derby/code/trunk/java/client/org/apache/derby/jdbc/ClientBaseDataSource.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/client/org/apache/derby/jdbc/ClientBaseDataSource.java?rev=379536&r1=379535&r2=379536&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/jdbc/ClientBaseDataSource.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/jdbc/ClientBaseDataSource.java Tue Feb 21 09:12:57 2006
@@ -26,20 +26,17 @@
 import java.util.StringTokenizer;
 import java.util.NoSuchElementException;
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.sql.SQLException;
 import javax.naming.Referenceable;
 import javax.naming.Reference;
 import javax.naming.NamingException;
 import javax.naming.StringRefAddr;
-import javax.naming.RefAddr;
 
 import org.apache.derby.client.am.Configuration;
 import org.apache.derby.client.am.LogWriter;
 import org.apache.derby.client.am.SqlException;
-import org.apache.derby.client.am.SetAccessibleAction;
 import org.apache.derby.client.am.Connection;
 import org.apache.derby.client.net.NetConfiguration;
 import org.apache.derby.client.net.NetLogWriter;
@@ -50,7 +47,7 @@
  */
 public abstract class ClientBaseDataSource implements Serializable, Referenceable {
     private static final long serialVersionUID = -7660172643035173692L;
-
+    
     // The loginTimeout jdbc 2 data source property is not supported as a jdbc 1 connection property,
     // because loginTimeout is set by the jdbc 1 api via java.sql.DriverManager.setLoginTimeout().
     // The databaseName, serverName, and portNumber data source properties are also not supported as connection properties
@@ -72,7 +69,7 @@
      *
      * @serial
      */
-    protected int loginTimeout = propertyDefault_loginTimeout;
+    private int loginTimeout = propertyDefault_loginTimeout;
     public final static String propertyKey_loginTimeout = "loginTimeout";
     public static final int propertyDefault_loginTimeout = 0;
 
@@ -108,7 +105,7 @@
     // and therefore may throw an SQLException.
     //
     //
-    protected String databaseName;
+    private String databaseName;
     public final static String propertyKey_databaseName = "databaseName";
 
     // databaseName is not permitted in a properties object
@@ -116,7 +113,7 @@
 
     // ---------------------------- description ------------------------------
     // A description of this data source.
-    protected String description;
+    private String description;
     public final static String propertyKey_description = "description";
 
     // ---------------------------- dataSourceName -----------------------------------
@@ -125,19 +122,19 @@
     // used to name an underlying XADataSource,
     // or ConnectionPoolDataSource when pooling of connections is done.
     //
-    protected String dataSourceName;
+    private String dataSourceName;
     public final static String propertyKey_dataSourceName = "dataSourceName";
 
     // ---------------------------- portNumber -----------------------------------
     //
-    protected int portNumber = propertyDefault_portNumber;
+    private int portNumber = propertyDefault_portNumber;
     public final static int propertyDefault_portNumber = 1527;
     public final static String propertyKey_portNumber = "portNumber";
 
     // ---------------------------- serverName -----------------------------------
     //
     // Derby-410 fix.
-    protected String serverName = propertyDefault_serverName;
+    private String serverName = propertyDefault_serverName;
     public final static String propertyDefault_serverName = "localhost";
     public final static String propertyKey_serverName = "serverName";
 
@@ -155,7 +152,7 @@
     // This password property may or may not be declared transient, and therefore may be serialized
     // to a file in clear-text, care must taken by the user to prevent security breaches.
     // Derby-406 fix
-    protected String user = propertyDefault_user;
+    private String user = propertyDefault_user;
     public final static String propertyKey_user = "user";
     public final static String propertyDefault_user = "APP";
 
@@ -224,7 +221,7 @@
 
     // ---------------------------- getServerMessageTextOnGetMessage -----------------------------------
     //
-    protected boolean retrieveMessageText = propertyDefault_retrieveMessageText;
+    private boolean retrieveMessageText = propertyDefault_retrieveMessageText;
     public final static boolean propertyDefault_retrieveMessageText = true;
     public final static String propertyKey_retrieveMessageText = "retrieveMessageText";
 
@@ -236,7 +233,7 @@
 
     // ---------------------------- traceFile -----------------------------------
     //
-    protected String traceFile;
+    private String traceFile;
     public final static String propertyKey_traceFile = "traceFile";
 
     public static String getTraceFile(Properties properties) {
@@ -247,7 +244,7 @@
     // For the suffix of the trace file when traceDirectory is enabled.
     private transient int traceFileSuffixIndex_ = 0;
     //
-    protected String traceDirectory;
+    private String traceDirectory;
     public final static String propertyKey_traceDirectory = "traceDirectory";
 
     public static String getTraceDirectory(Properties properties) {
@@ -256,7 +253,7 @@
 
     // ---------------------------- traceFileAppend -----------------------------------
     //
-    protected boolean traceFileAppend = propertyDefault_traceFileAppend;
+    private boolean traceFileAppend = propertyDefault_traceFileAppend;
     public final static boolean propertyDefault_traceFileAppend = false;
     public final static String propertyKey_traceFileAppend = "traceFileAppend";
 
@@ -276,7 +273,7 @@
         return properties.getProperty("password");
     }
 
-    protected String password;
+    private String password;
 
     synchronized public final void setPassword(String password) {
         this.password = password;
@@ -309,126 +306,64 @@
 
         Reference ref = new Reference(this.getClass().getName(), ClientDataSourceFactory.class.getName(), null);
 
-        Class clz = getClass();
-        Field[] fields = clz.getFields();
-        for (int i = 0; i < fields.length; i++) {
-            String name = fields[i].getName();
-            if (name.startsWith("propertyKey_")) {
-                if (Modifier.isTransient(fields[i].getModifiers())) {
-                    continue; // if it is transient, then skip this propertyKey.
-                }
-                try {
-                    String propertyKey = fields[i].get(this).toString();
-                    // search for property field.
-                    Field propertyField;
-                    clz = getClass(); // start from current class.
-                    while (true) {
-                        try {
-                            propertyField = clz.getDeclaredField(name.substring(12));
-                            break; // found the property field, so break the while loop.
-                        } catch (NoSuchFieldException nsfe) {
-                            // property field is not found at current level of class, so continue to super class.
-                            clz = clz.getSuperclass();
-                            if (clz == Object.class) {
-                                throw new NamingException("bug check: corresponding property field does not exist");
-                            }
-                            continue;
-                        }
-                    }
-
-                    if (!Modifier.isTransient(propertyField.getModifiers())) {
-                        // if the property is not transient:
-                        // get the property.
-                        AccessController.doPrivileged(new SetAccessibleAction(propertyField, true));
-                        //propertyField.setAccessible (true);
-                        Object propertyObj = propertyField.get(this);
-                        String property = (propertyObj == null) ? null : String.valueOf(propertyObj);
-                        // add into reference.
-                        ref.add(new StringRefAddr(propertyKey, property));
-                    }
-                } catch (IllegalAccessException e) {
-                    throw new NamingException("bug check: property cannot be accessed");
-                } catch (PrivilegedActionException e) {
-                    throw new NamingException("Privileged action exception occurred.");
-                }
-            }
-        }
+        addBeanProperties(ref);
         return ref;
     }
-
+    
     /**
-     * Not an external.  Do not document in pubs. Populates member data for this data source given a JNDI reference.
-     */
-    public void hydrateFromReference(Reference ref) throws SqlException {
-    	
-        RefAddr address;
-
-        Class clz = getClass();
-        Field[] fields = clz.getFields();
-        for (int i = 0; i < fields.length; i++) {
-            String name = fields[i].getName();
-            if (name.startsWith("propertyKey_")) {
-                if (Modifier.isTransient(fields[i].getModifiers())) {
-                    continue; // if it is transient, then skip this propertyKey.
-                }
+     * Add Java Bean properties to the reference using
+     * StringRefAddr for each property. List of bean properties
+     * is defined from the public getXXX() methods on this object
+     * that take no arguments and return short, int, boolean or String.
+     * The StringRefAddr has a key of the Java bean property name,
+     * converted from the method name. E.g. traceDirectory for
+     * traceDirectory.
+     * 
+      */
+    private void addBeanProperties(Reference ref)
+    {
+        // Look for all the getXXX methods in the class that take no arguments.
+        Method[] methods = this.getClass().getMethods();
+        
+        for (int i = 0; i < methods.length; i++) {
+
+            Method m = methods[i];
+
+            // only look for simple getter methods.
+            if (m.getParameterTypes().length != 0)
+                continue;
+
+            // only non-static methods
+            if (Modifier.isStatic(m.getModifiers()))
+                continue;
+
+            // Only getXXX methods
+            String methodName = m.getName();
+            if ((methodName.length() < 5) || !methodName.startsWith("get"))
+                continue;
+
+            Class returnType = m.getReturnType();
+
+            if (Integer.TYPE.equals(returnType)
+                    || Short.TYPE.equals(returnType)
+                    || String.class.equals(returnType)
+                    || Boolean.TYPE.equals(returnType)) {
+
+                // setSomeProperty
+                // 01234
+
+                String propertyName = methodName.substring(3, 4).toLowerCase(
+                        java.util.Locale.ENGLISH).concat(
+                        methodName.substring(4));
+
                 try {
-                    String propertyKey = fields[i].get(this).toString();
-                    // search for property field.
-                    Field propertyField;
-                    clz = getClass(); // start from current class.
-                    while (true) {
-                        try {
-                            propertyField = clz.getDeclaredField(name.substring(12));
-                            break; // found the property field, so break the while loop.
-                        } catch (NoSuchFieldException nsfe) {
-                            // property field is not found at current level of class, so continue to super class.
-                            clz = clz.getSuperclass();
-                            if (clz == Object.class) {
-                                throw new SqlException(new LogWriter(logWriter, traceLevel), "bug check: corresponding property field does not exist");
-                            }
-                            continue;
-                        }
-                    }
-
-                    if (!Modifier.isTransient(propertyField.getModifiers())) {
-                        // if the property is not transient:
-                        // set the property.
-                        address = ref.get(propertyKey);
-                        if (address != null) {
-                            propertyField.setAccessible(true);
-                            String type = propertyField.getType().toString();
-                            if (type.equals("boolean")) {
-                                boolean value = ((String) address.getContent()).equalsIgnoreCase("true");
-                                propertyField.setBoolean(this, value);
-                            } else if (type.equals("byte")) {
-                                byte value = Byte.parseByte((String) address.getContent());
-                                propertyField.setByte(this, value);
-                            } else if (type.equals("short")) {
-                                short value = Short.parseShort((String) address.getContent());
-                                propertyField.setShort(this, value);
-                            } else if (type.equals("int")) {
-                                int value = Integer.parseInt((String) address.getContent());
-                                propertyField.setInt(this, value);
-                            } else if (type.equals("long")) {
-                                long value = Long.parseLong((String) address.getContent());
-                                propertyField.setLong(this, value);
-                            } else if (type.equals("float")) {
-                                float value = Float.parseFloat((String) address.getContent());
-                                propertyField.setFloat(this, value);
-                            } else if (type.equals("double")) {
-                                double value = Double.parseDouble((String) address.getContent());
-                                propertyField.setDouble(this, value);
-                            } else if (type.equals("char")) {
-                                char value = ((String) address.getContent()).charAt(0);
-                                propertyField.setChar(this, value);
-                            } else {
-                                propertyField.set(this, address.getContent());
-                            }
-                        }
-                    }
-                } catch (IllegalAccessException e) {
-                    throw new SqlException(new LogWriter(this.logWriter, this.traceLevel), "bug check: property cannot be accessed");
+                    Object ov = m.invoke(this, null);
+                    String value = ov == null ? null : ov.toString();
+                    ref.add(new StringRefAddr(propertyName, value));
+                } catch (IllegalAccessException iae) {
+                } catch (InvocationTargetException ite) {
                 }
+
             }
         }
     }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/dataSourceReference_app.properties
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/dataSourceReference_app.properties?rev=379536&r1=379535&r2=379536&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/dataSourceReference_app.properties (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/dataSourceReference_app.properties Tue Feb 21 09:12:57 2006
@@ -4,5 +4,3 @@
 # Referencable interface not available in CDC/Foundation
 runwithfoundation=false
 
-# DERBY-446
-noSecurityManager=true