1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.naming.factory;
19
20 import java.util.Hashtable;
21 import java.util.Enumeration;
22 import javax.naming.Name;
23 import javax.naming.Context;
24 import javax.naming.NamingException;
25 import javax.naming.Reference;
26 import javax.naming.RefAddr;
27 import javax.naming.spi.ObjectFactory;
28 import org.apache.naming.ResourceRef;
29
30 import java.beans.Introspector;
31 import java.beans.BeanInfo;
32 import java.beans.PropertyDescriptor;
33
34 import java.lang.reflect.Method;
35
36 /**
37 * Object factory for any Resource conforming to the JavaBean spec.
38 *
39 * <p>This factory can be configured in a <code><DefaultContext></code>
40 * or <code><Context></code> element in your <code>conf/server.xml</code>
41 * configuration file. An example of factory configuration is:</p>
42 * <pre>
43 * <Resource name="jdbc/myDataSource" auth="SERVLET"
44 * type="oracle.jdbc.pool.OracleConnectionCacheImpl"/>
45 * <ResourceParams name="jdbc/myDataSource">
46 * <parameter>
47 * <name>factory</name>
48 * <value>org.apache.naming.factory.BeanFactory</value>
49 * </parameter>
50 * <parameter>
51 * <name>driverType</name>
52 * <value>thin</value>
53 * </parameter>
54 * <parameter>
55 * <name>serverName</name>
56 * <value>hue</value>
57 * </parameter>
58 * <parameter>
59 * <name>networkProtocol</name>
60 * <value>tcp</value>
61 * </parameter>
62 * <parameter>
63 * <name>databaseName</name>
64 * <value>XXXX</value>
65 * </parameter>
66 * <parameter>
67 * <name>portNumber</name>
68 * <value>NNNN</value>
69 * </parameter>
70 * <parameter>
71 * <name>user</name>
72 * <value>XXXX</value>
73 * </parameter>
74 * <parameter>
75 * <name>password</name>
76 * <value>XXXX</value>
77 * </parameter>
78 * <parameter>
79 * <name>maxLimit</name>
80 * <value>5</value>
81 * </parameter>
82 * </ResourceParams>
83 * </pre>
84 *
85 * @author <a href="mailto:aner at ncstech.com">Aner Perez</a>
86 */
87 public class BeanFactory
88 implements ObjectFactory {
89
90 // ----------------------------------------------------------- Constructors
91
92
93 // -------------------------------------------------------------- Constants
94
95
96 // ----------------------------------------------------- Instance Variables
97
98
99 // --------------------------------------------------------- Public Methods
100
101
102 // -------------------------------------------------- ObjectFactory Methods
103
104
105 /**
106 * Create a new Bean instance.
107 *
108 * @param obj The reference object describing the Bean
109 */
110 public Object getObjectInstance(Object obj, Name name, Context nameCtx,
111 Hashtable environment)
112 throws NamingException {
113
114 if (obj instanceof ResourceRef) {
115
116 try {
117
118 Reference ref = (Reference) obj;
119 String beanClassName = ref.getClassName();
120 Class beanClass = null;
121 ClassLoader tcl =
122 Thread.currentThread().getContextClassLoader();
123 if (tcl != null) {
124 try {
125 beanClass = tcl.loadClass(beanClassName);
126 } catch(ClassNotFoundException e) {
127 }
128 } else {
129 try {
130 beanClass = Class.forName(beanClassName);
131 } catch(ClassNotFoundException e) {
132 e.printStackTrace();
133 }
134 }
135 if (beanClass == null) {
136 throw new NamingException
137 ("Class not found: " + beanClassName);
138 }
139
140 BeanInfo bi = Introspector.getBeanInfo(beanClass);
141 PropertyDescriptor[] pda = bi.getPropertyDescriptors();
142
143 Object bean = beanClass.newInstance();
144
145 Enumeration e = ref.getAll();
146 while (e.hasMoreElements()) {
147
148 RefAddr ra = (RefAddr) e.nextElement();
149 String propName = ra.getType();
150
151 if (propName.equals(Constants.FACTORY) ||
152 propName.equals("scope") || propName.equals("auth")) {
153 continue;
154 }
155
156 String value = (String)ra.getContent();
157
158 Object[] valueArray = new Object[1];
159
160 int i = 0;
161 for (i = 0; i<pda.length; i++) {
162
163 if (pda[i].getName().equals(propName)) {
164
165 Class propType = pda[i].getPropertyType();
166
167 if (propType.equals(String.class)) {
168 valueArray[0] = value;
169 } else if (propType.equals(Character.class)
170 || propType.equals(char.class)) {
171 valueArray[0] = new Character(value.charAt(0));
172 } else if (propType.equals(Byte.class)
173 || propType.equals(byte.class)) {
174 valueArray[0] = new Byte(value);
175 } else if (propType.equals(Short.class)
176 || propType.equals(short.class)) {
177 valueArray[0] = new Short(value);
178 } else if (propType.equals(Integer.class)
179 || propType.equals(int.class)) {
180 valueArray[0] = new Integer(value);
181 } else if (propType.equals(Long.class)
182 || propType.equals(long.class)) {
183 valueArray[0] = new Long(value);
184 } else if (propType.equals(Float.class)
185 || propType.equals(float.class)) {
186 valueArray[0] = new Float(value);
187 } else if (propType.equals(Double.class)
188 || propType.equals(double.class)) {
189 valueArray[0] = new Double(value);
190 } else if (propType.equals(Boolean.class)
191 || propType.equals(boolean.class)) {
192 valueArray[0] = new Boolean(value);
193 } else {
194 throw new NamingException
195 ("String conversion for property type '"
196 + propType.getName() + "' not available");
197 }
198
199 Method setProp = pda[i].getWriteMethod();
200 if (setProp != null) {
201 setProp.invoke(bean, valueArray);
202 } else {
203 throw new NamingException
204 ("Write not allowed for property: "
205 + propName);
206 }
207
208 break;
209
210 }
211
212 }
213
214 if (i == pda.length) {
215 throw new NamingException
216 ("No set method found for property: " + propName);
217 }
218
219 }
220
221 return bean;
222
223 } catch (java.beans.IntrospectionException ie) {
224 NamingException ne = new NamingException(ie.getMessage());
225 ne.setRootCause(ie);
226 throw ne;
227 } catch (java.lang.IllegalAccessException iae) {
228 NamingException ne = new NamingException(iae.getMessage());
229 ne.setRootCause(iae);
230 throw ne;
231 } catch (java.lang.InstantiationException ie2) {
232 NamingException ne = new NamingException(ie2.getMessage());
233 ne.setRootCause(ie2);
234 throw ne;
235 } catch (java.lang.reflect.InvocationTargetException ite) {
236 NamingException ne = new NamingException(ite.getMessage());
237 ne.setRootCause(ite);
238 throw ne;
239 }
240
241 } else {
242 return null;
243 }
244
245 }
246 }