001: /*
002:
003: Derby - Class org.apache.derby.client.ClientDataSourceFactory
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.client;
023:
024: import java.lang.reflect.Method;
025: import java.util.Enumeration;
026:
027: import javax.naming.RefAddr;
028: import javax.naming.Reference;
029: import org.apache.derby.jdbc.ClientBaseDataSource;
030:
031: import org.apache.derby.jdbc.ClientConnectionPoolDataSource;
032: import org.apache.derby.jdbc.ClientDataSource;
033: import org.apache.derby.jdbc.ClientXADataSource;
034:
035: /**
036: * The data source factory currrently for ClientDataSource only. This factory will support XA and pooling-enabled data
037: * sources in the future.
038: * <p/>
039: * This factory reconstructs a DERBY simple data source object when it is retrieved from JNDI. References are needed
040: * since many naming services don't have the ability to store Java objects in their serialized form. When a data source
041: * object is bound in this type of naming service the Reference for that object is actually stored by the JNDI
042: * implementation, not the data source object itself.
043: * <p/>
044: * A JNDI administrator is responsible for making sure that both the object factory and data source implementation
045: * classes provided by a JDBC driver vendor are accessible to the JNDI service provider at runtime.
046: * <p/>
047: * An object factory implements the javax.naming.spi.ObjectFactory interface. This interface contains a single method,
048: * getObjectInstance, which is called by a JNDI service provider to reconstruct an object when that object is retrieved
049: * from JNDI. A JDBC driver vendor should provide an object factory as part of their JDBC 2.0 product.
050: *
051: * @see ClientDataSource
052: */
053: public class ClientDataSourceFactory implements
054: javax.naming.spi.ObjectFactory {
055:
056: public ClientDataSourceFactory() {
057: }
058:
059: /**
060: * Reconstructs a ClientDataSource object from a JNDI data source reference.
061: * <p/>
062: * The getObjectInstance() method is passed a reference that corresponds to the object being retrieved as its first
063: * parameter. The other parameters are optional in the case of JDBC data source objects. The object factory should
064: * use the information contained in the reference to reconstruct the data source. If for some reason, a data source
065: * object cannot be reconstructed from the reference, a value of null may be returned. This allows other object
066: * factories that may be registered in JNDI to be tried. If an exception is thrown then no other object factories
067: * are tried.
068: *
069: * @param refObj The possibly null object containing location or reference information that can be used in
070: * creating an object.
071: * @param name The name of this object relative to nameContext, or null if no name is specified.
072: * @param nameContext Context relative to which the name parameter is specified, or null if name is relative to the
073: * default initial context.
074: * @param environment Possibly null environment that is used in creating the object.
075: *
076: * @return object created; null if an object cannot be created
077: */
078: public Object getObjectInstance(Object refObj,
079: javax.naming.Name name, javax.naming.Context nameContext,
080: java.util.Hashtable environment) throws java.lang.Exception {
081: javax.naming.Reference ref = (javax.naming.Reference) refObj;
082:
083: // Create the proper data source object shell.
084: ClientBaseDataSource ds = null;
085: if (ref.getClassName().equals(ClientDataSource.className__)) {
086: ds = new ClientDataSource();
087: } else if (ref.getClassName().equals(
088: ClientXADataSource.className__)) {
089: ds = new ClientXADataSource();
090: } else if (ref.getClassName().equals(
091: ClientConnectionPoolDataSource.className__)) {
092: ds = new ClientConnectionPoolDataSource();
093: } else {
094: return null;
095: }
096:
097: // Fill in the data source object shell with values from the jndi reference.
098: ClientDataSourceFactory.setBeanProperties(ds, ref);
099:
100: return ds;
101: }
102:
103: /** Reflect lookup for Java bean method taking a single String arg */
104: private static final Class[] STRING_ARG = { "".getClass() };
105: /** Reflect lookup for Java bean method taking a single int arg */
106: private static final Class[] INT_ARG = { Integer.TYPE };
107: /** Reflect lookup for Java bean method taking a single boolean arg */
108: private static final Class[] BOOLEAN_ARG = { Boolean.TYPE };
109: /** Reflect lookup for Java bean method taking a single short arg */
110: private static final Class[] SHORT_ARG = { Short.TYPE };
111:
112: /*
113: * Set the Java bean properties for an object from its Reference. The
114: * Reference contains a set of StringRefAddr values with the key being the
115: * bean name and the value a String representation of the bean's value. This
116: * code looks for setXXX() method where the set method corresponds to the
117: * standard bean naming scheme and has a single parameter of type String,
118: * int, boolean or short.
119: */
120: private static void setBeanProperties(Object ds, Reference ref)
121: throws Exception {
122:
123: for (Enumeration e = ref.getAll(); e.hasMoreElements();) {
124:
125: RefAddr attribute = (RefAddr) e.nextElement();
126:
127: String propertyName = attribute.getType();
128:
129: String value = (String) attribute.getContent();
130:
131: String methodName = "set"
132: + propertyName.substring(0, 1).toUpperCase(
133: java.util.Locale.ENGLISH)
134: + propertyName.substring(1);
135:
136: Method m;
137:
138: Object argValue;
139: try {
140: m = ds.getClass().getMethod(methodName, STRING_ARG);
141: argValue = value;
142: } catch (NoSuchMethodException nsme) {
143: try {
144: m = ds.getClass().getMethod(methodName, INT_ARG);
145: argValue = Integer.valueOf(value);
146: } catch (NoSuchMethodException nsme2) {
147: try {
148: m = ds.getClass().getMethod(methodName,
149: BOOLEAN_ARG);
150: argValue = Boolean.valueOf(value);
151: } catch (NoSuchMethodException nsme3) {
152: m = ds.getClass().getMethod(methodName,
153: SHORT_ARG);
154: argValue = Short.valueOf(value);
155: }
156: }
157: }
158: m.invoke(ds, new Object[] { argValue });
159: }
160: }
161: }
|