1 | /* |
2 | |
3 | Derby - Class org.apache.derby.client.ClientDataSourceFactory |
4 | |
5 | Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.client; |
22 | |
23 | import java.lang.reflect.Method; |
24 | import java.util.Enumeration; |
25 | |
26 | import javax.naming.RefAddr; |
27 | import javax.naming.Reference; |
28 | import org.apache.derby.jdbc.ClientBaseDataSource; |
29 | |
30 | import org.apache.derby.jdbc.ClientConnectionPoolDataSource; |
31 | import org.apache.derby.jdbc.ClientDataSource; |
32 | import org.apache.derby.jdbc.ClientXADataSource; |
33 | |
34 | /** |
35 | * The data source factory currrently for ClientDataSource only. This factory will support XA and pooling-enabled data |
36 | * sources in the future. |
37 | * <p/> |
38 | * This factory reconstructs a DERBY simple data source object when it is retrieved from JNDI. References are needed |
39 | * since many naming services don't have the ability to store Java objects in their serialized form. When a data source |
40 | * object is bound in this type of naming service the Reference for that object is actually stored by the JNDI |
41 | * implementation, not the data source object itself. |
42 | * <p/> |
43 | * A JNDI administrator is responsible for making sure that both the object factory and data source implementation |
44 | * classes provided by a JDBC driver vendor are accessible to the JNDI service provider at runtime. |
45 | * <p/> |
46 | * An object factory implements the javax.naming.spi.ObjectFactory interface. This interface contains a single method, |
47 | * getObjectInstance, which is called by a JNDI service provider to reconstruct an object when that object is retrieved |
48 | * from JNDI. A JDBC driver vendor should provide an object factory as part of their JDBC 2.0 product. |
49 | * |
50 | * @see ClientDataSource |
51 | */ |
52 | public class ClientDataSourceFactory implements javax.naming.spi.ObjectFactory { |
53 | |
54 | public ClientDataSourceFactory() { |
55 | } |
56 | |
57 | /** |
58 | * Reconstructs a ClientDataSource object from a JNDI data source reference. |
59 | * <p/> |
60 | * The getObjectInstance() method is passed a reference that corresponds to the object being retrieved as its first |
61 | * parameter. The other parameters are optional in the case of JDBC data source objects. The object factory should |
62 | * use the information contained in the reference to reconstruct the data source. If for some reason, a data source |
63 | * object cannot be reconstructed from the reference, a value of null may be returned. This allows other object |
64 | * factories that may be registered in JNDI to be tried. If an exception is thrown then no other object factories |
65 | * are tried. |
66 | * |
67 | * @param refObj The possibly null object containing location or reference information that can be used in |
68 | * creating an object. |
69 | * @param name The name of this object relative to nameContext, or null if no name is specified. |
70 | * @param nameContext Context relative to which the name parameter is specified, or null if name is relative to the |
71 | * default initial context. |
72 | * @param environment Possibly null environment that is used in creating the object. |
73 | * |
74 | * @return object created; null if an object cannot be created |
75 | */ |
76 | public Object getObjectInstance(Object refObj, |
77 | javax.naming.Name name, |
78 | javax.naming.Context nameContext, |
79 | java.util.Hashtable environment) throws java.lang.Exception { |
80 | javax.naming.Reference ref = (javax.naming.Reference) refObj; |
81 | |
82 | // Create the proper data source object shell. |
83 | ClientBaseDataSource ds = null; |
84 | if (ref.getClassName().equals(ClientDataSource.className__)) { |
85 | ds = new ClientDataSource(); |
86 | } else if (ref.getClassName().equals(ClientXADataSource.className__)) { |
87 | ds = new ClientXADataSource(); |
88 | } else if (ref.getClassName().equals(ClientConnectionPoolDataSource.className__)) { |
89 | ds = new ClientConnectionPoolDataSource(); |
90 | } else { |
91 | return null; |
92 | } |
93 | |
94 | // Fill in the data source object shell with values from the jndi reference. |
95 | ClientDataSourceFactory.setBeanProperties(ds, ref); |
96 | |
97 | return ds; |
98 | } |
99 | |
100 | /** Reflect lookup for Java bean method taking a single String arg */ |
101 | private static final Class[] STRING_ARG = { "".getClass() }; |
102 | /** Reflect lookup for Java bean method taking a single int arg */ |
103 | private static final Class[] INT_ARG = { Integer.TYPE }; |
104 | /** Reflect lookup for Java bean method taking a single boolean arg */ |
105 | private static final Class[] BOOLEAN_ARG = { Boolean.TYPE }; |
106 | /** Reflect lookup for Java bean method taking a single short arg */ |
107 | private static final Class[] SHORT_ARG = { Short.TYPE }; |
108 | |
109 | /* |
110 | * Set the Java bean properties for an object from its Reference. The |
111 | * Reference contains a set of StringRefAddr values with the key being the |
112 | * bean name and the value a String representation of the bean's value. This |
113 | * code looks for setXXX() method where the set method corresponds to the |
114 | * standard bean naming scheme and has a single parameter of type String, |
115 | * int, boolean or short. |
116 | */ |
117 | private static void setBeanProperties(Object ds, Reference ref) |
118 | throws Exception { |
119 | |
120 | for (Enumeration e = ref.getAll(); e.hasMoreElements();) { |
121 | |
122 | RefAddr attribute = (RefAddr) e.nextElement(); |
123 | |
124 | String propertyName = attribute.getType(); |
125 | |
126 | String value = (String) attribute.getContent(); |
127 | |
128 | String methodName = "set" |
129 | + propertyName.substring(0, 1).toUpperCase( |
130 | java.util.Locale.ENGLISH) |
131 | + propertyName.substring(1); |
132 | |
133 | Method m; |
134 | |
135 | Object argValue; |
136 | try { |
137 | m = ds.getClass().getMethod(methodName, STRING_ARG); |
138 | argValue = value; |
139 | } catch (NoSuchMethodException nsme) { |
140 | try { |
141 | m = ds.getClass().getMethod(methodName, INT_ARG); |
142 | argValue = Integer.valueOf(value); |
143 | } catch (NoSuchMethodException nsme2) { |
144 | try { |
145 | m = ds.getClass().getMethod(methodName, BOOLEAN_ARG); |
146 | argValue = Boolean.valueOf(value); |
147 | } catch (NoSuchMethodException nsme3) { |
148 | m = ds.getClass().getMethod(methodName, SHORT_ARG); |
149 | argValue = Short.valueOf(value); |
150 | } |
151 | } |
152 | } |
153 | m.invoke(ds, new Object[] { argValue }); |
154 | } |
155 | } |
156 | } |