2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2016 - 2017 AT&T
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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 * ============LICENSE_END=========================================================
22 * Licensed to the Apache Software Foundation (ASF) under one or more
23 * contributor license agreements. See the NOTICE file distributed with
24 * this work for additional information regarding copyright ownership.
25 * The ASF licenses this file to You under the Apache License, Version 2.0
26 * (the "License"); you may not use this file except in compliance with
27 * the License. You may obtain a copy of the License at
29 * http://www.apache.org/licenses/LICENSE-2.0
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
37 package org.apache.tomcat.jdbc.naming;
39 import java.lang.reflect.InvocationTargetException;
40 import java.lang.reflect.Method;
41 import java.net.InetAddress;
42 import java.net.UnknownHostException;
43 import java.util.Enumeration;
44 import java.util.Hashtable;
46 import javax.naming.Context;
47 import javax.naming.Name;
48 import javax.naming.RefAddr;
49 import javax.naming.Reference;
50 import javax.naming.spi.ObjectFactory;
52 import org.apache.juli.logging.Log;
53 import org.apache.juli.logging.LogFactory;
54 import org.apache.tomcat.jdbc.pool.ClassLoaderUtil;
57 * Simple way of configuring generic resources by using reflection.
60 * <Resource factory="org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory"
61 * name="jdbc/test"
62 * type="org.apache.derby.jdbc.ClientXADataSource"
63 * databaseName="sample"
64 * createDatabase="create"
65 * serverName="localhost"
66 * port="1527"/>
70 public class GenericNamingResourcesFactory implements ObjectFactory {
71 private static final Log log = LogFactory.getLog(GenericNamingResourcesFactory.class);
74 public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
75 if ((obj == null) || !(obj instanceof Reference)) {
78 Reference ref = (Reference) obj;
79 Enumeration<RefAddr> refs = ref.getAll();
81 String type = ref.getClassName();
83 ClassLoaderUtil.loadClass(
85 GenericNamingResourcesFactory.class.getClassLoader(),
86 Thread.currentThread().getContextClassLoader())
89 while (refs.hasMoreElements()) {
90 RefAddr addr = refs.nextElement();
91 String param = addr.getType();
93 if (addr.getContent()!=null) {
94 value = addr.getContent().toString();
96 if (setProperty(o, param, value)) {
99 log.debug("Property not configured["+param+"]. No setter found on["+o+"].");
105 @SuppressWarnings("null") // setPropertyMethodVoid can't be null when used
106 private static boolean setProperty(Object o, String name, String value) {
107 if (log.isDebugEnabled())
108 log.debug("IntrospectionUtils: setProperty(" +
109 o.getClass() + " " + name + "=" + value + ")");
111 String setter = "set" + capitalize(name);
114 Method methods[] = o.getClass().getMethods();
115 Method setPropertyMethodVoid = null;
116 Method setPropertyMethodBool = null;
118 // First, the ideal case - a setFoo( String ) method
119 for (int i = 0; i < methods.length; i++) {
120 Class<?> paramT[] = methods[i].getParameterTypes();
121 if (setter.equals(methods[i].getName()) && paramT.length == 1
122 && "java.lang.String".equals(paramT[0].getName())) {
124 methods[i].invoke(o, new Object[] { value });
129 // Try a setFoo ( int ) or ( boolean )
130 for (int i = 0; i < methods.length; i++) {
132 if (setter.equals(methods[i].getName())
133 && methods[i].getParameterTypes().length == 1) {
135 // match - find the type and invoke it
136 Class<?> paramType = methods[i].getParameterTypes()[0];
137 Object params[] = new Object[1];
139 // Try a setFoo ( int )
140 if ("java.lang.Integer".equals(paramType.getName())
141 || "int".equals(paramType.getName())) {
143 params[0] = new Integer(value);
144 } catch (NumberFormatException ex) {
147 // Try a setFoo ( long )
148 }else if ("java.lang.Long".equals(paramType.getName())
149 || "long".equals(paramType.getName())) {
151 params[0] = new Long(value);
152 } catch (NumberFormatException ex) {
156 // Try a setFoo ( boolean )
157 } else if ("java.lang.Boolean".equals(paramType.getName())
158 || "boolean".equals(paramType.getName())) {
159 params[0] = Boolean.valueOf(value);
161 // Try a setFoo ( InetAddress )
162 } else if ("java.net.InetAddress".equals(paramType
165 params[0] = InetAddress.getByName(value);
166 } catch (UnknownHostException exc) {
167 if (log.isDebugEnabled())
168 log.debug("IntrospectionUtils: Unable to resolve host name:" + value);
174 if (log.isDebugEnabled())
175 log.debug("IntrospectionUtils: Unknown type " +
176 paramType.getName());
180 methods[i].invoke(o, params);
185 // save "setProperty" for later
186 if ("setProperty".equals(methods[i].getName())) {
187 if (methods[i].getReturnType()==Boolean.TYPE){
188 setPropertyMethodBool = methods[i];
190 setPropertyMethodVoid = methods[i];
196 // Ok, no setXXX found, try a setProperty("name", "value")
197 if (setPropertyMethodBool != null || setPropertyMethodVoid != null) {
198 Object params[] = new Object[2];
201 if (setPropertyMethodBool != null) {
203 return ((Boolean) setPropertyMethodBool.invoke(o, params)).booleanValue();
204 }catch (IllegalArgumentException biae) {
205 //the boolean method had the wrong
206 //parameter types. lets try the other
207 if (setPropertyMethodVoid!=null) {
208 setPropertyMethodVoid.invoke(o, params);
215 setPropertyMethodVoid.invoke(o, params);
220 } catch (IllegalArgumentException ex2) {
221 log.warn("IAE " + o + " " + name + " " + value, ex2);
222 } catch (SecurityException ex1) {
223 if (log.isDebugEnabled())
224 log.debug("IntrospectionUtils: SecurityException for " +
225 o.getClass() + " " + name + "=" + value + ")", ex1);
226 } catch (IllegalAccessException iae) {
227 if (log.isDebugEnabled())
228 log.debug("IntrospectionUtils: IllegalAccessException for " +
229 o.getClass() + " " + name + "=" + value + ")", iae);
230 } catch (InvocationTargetException ie) {
231 Throwable cause = ie.getCause();
232 if (cause instanceof ThreadDeath) {
233 throw (ThreadDeath) cause;
235 if (cause instanceof VirtualMachineError) {
236 throw (VirtualMachineError) cause;
238 if (log.isDebugEnabled())
239 log.debug("IntrospectionUtils: InvocationTargetException for " +
240 o.getClass() + " " + name + "=" + value + ")", ie);
245 public static String capitalize(String name) {
246 if (name == null || name.length() == 0) {
249 char chars[] = name.toCharArray();
250 chars[0] = Character.toUpperCase(chars[0]);
251 return new String(chars);