Merge "provide ready-use maven setting for easy build"
[sdnc/core.git] / dblib / common / src / main / java / org / apache / tomcat / jdbc / naming / GenericNamingResourcesFactory.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openecomp
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
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  * ============LICENSE_END=========================================================
19  */
20
21 /*
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
28  *
29  *      http://www.apache.org/licenses/LICENSE-2.0
30  *
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.
36  */
37 package org.apache.tomcat.jdbc.naming;
38
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;
45
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;
51
52 import org.apache.juli.logging.Log;
53 import org.apache.juli.logging.LogFactory;
54 import org.apache.tomcat.jdbc.pool.ClassLoaderUtil;
55
56 /**
57  * Simple way of configuring generic resources by using reflection.
58  * Example usage:
59  * <pre><code>
60  * &lt;Resource factory=&quot;org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory&quot;
61  *              name=&quot;jdbc/test&quot;
62  *              type=&quot;org.apache.derby.jdbc.ClientXADataSource&quot;
63  *              databaseName=&quot;sample&quot;
64  *              createDatabase=&quot;create&quot;
65  *              serverName=&quot;localhost&quot;
66  *              port=&quot;1527&quot;/&gt;
67  * </code></pre>
68  *
69  */
70 public class GenericNamingResourcesFactory implements ObjectFactory {
71     private static final Log log = LogFactory.getLog(GenericNamingResourcesFactory.class);
72
73     @Override
74     public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
75         if ((obj == null) || !(obj instanceof Reference)) {
76             return null;
77         }
78         Reference ref = (Reference) obj;
79         Enumeration<RefAddr> refs = ref.getAll();
80
81         String type = ref.getClassName();
82         Object o =
83             ClassLoaderUtil.loadClass(
84                 type,
85                 GenericNamingResourcesFactory.class.getClassLoader(),
86                 Thread.currentThread().getContextClassLoader())
87             .newInstance();
88
89         while (refs.hasMoreElements()) {
90             RefAddr addr = refs.nextElement();
91             String param = addr.getType();
92             String value = null;
93             if (addr.getContent()!=null) {
94                 value = addr.getContent().toString();
95             }
96             if (setProperty(o, param, value)) {
97
98             } else {
99                 log.debug("Property not configured["+param+"]. No setter found on["+o+"].");
100             }
101         }
102         return o;
103     }
104
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 + ")");
110
111         String setter = "set" + capitalize(name);
112
113         try {
114             Method methods[] = o.getClass().getMethods();
115             Method setPropertyMethodVoid = null;
116             Method setPropertyMethodBool = null;
117
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())) {
123
124                     methods[i].invoke(o, new Object[] { value });
125                     return true;
126                 }
127             }
128
129             // Try a setFoo ( int ) or ( boolean )
130             for (int i = 0; i < methods.length; i++) {
131                 boolean ok = true;
132                 if (setter.equals(methods[i].getName())
133                         && methods[i].getParameterTypes().length == 1) {
134
135                     // match - find the type and invoke it
136                     Class<?> paramType = methods[i].getParameterTypes()[0];
137                     Object params[] = new Object[1];
138
139                     // Try a setFoo ( int )
140                     if ("java.lang.Integer".equals(paramType.getName())
141                             || "int".equals(paramType.getName())) {
142                         try {
143                             params[0] = new Integer(value);
144                         } catch (NumberFormatException ex) {
145                             ok = false;
146                         }
147                     // Try a setFoo ( long )
148                     }else if ("java.lang.Long".equals(paramType.getName())
149                                 || "long".equals(paramType.getName())) {
150                             try {
151                                 params[0] = new Long(value);
152                             } catch (NumberFormatException ex) {
153                                 ok = false;
154                             }
155
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);
160
161                         // Try a setFoo ( InetAddress )
162                     } else if ("java.net.InetAddress".equals(paramType
163                             .getName())) {
164                         try {
165                             params[0] = InetAddress.getByName(value);
166                         } catch (UnknownHostException exc) {
167                             if (log.isDebugEnabled())
168                                 log.debug("IntrospectionUtils: Unable to resolve host name:" + value);
169                             ok = false;
170                         }
171
172                         // Unknown type
173                     } else {
174                         if (log.isDebugEnabled())
175                             log.debug("IntrospectionUtils: Unknown type " +
176                                     paramType.getName());
177                     }
178
179                     if (ok) {
180                         methods[i].invoke(o, params);
181                         return true;
182                     }
183                 }
184
185                 // save "setProperty" for later
186                 if ("setProperty".equals(methods[i].getName())) {
187                     if (methods[i].getReturnType()==Boolean.TYPE){
188                         setPropertyMethodBool = methods[i];
189                     }else {
190                         setPropertyMethodVoid = methods[i];
191                     }
192
193                 }
194             }
195
196             // Ok, no setXXX found, try a setProperty("name", "value")
197             if (setPropertyMethodBool != null || setPropertyMethodVoid != null) {
198                 Object params[] = new Object[2];
199                 params[0] = name;
200                 params[1] = value;
201                 if (setPropertyMethodBool != null) {
202                     try {
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);
209                             return true;
210                         }else {
211                             throw biae;
212                         }
213                     }
214                 } else {
215                     setPropertyMethodVoid.invoke(o, params);
216                     return true;
217                 }
218             }
219
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;
234             }
235             if (cause instanceof VirtualMachineError) {
236                 throw (VirtualMachineError) cause;
237             }
238             if (log.isDebugEnabled())
239                 log.debug("IntrospectionUtils: InvocationTargetException for " +
240                         o.getClass() + " " + name + "=" + value + ")", ie);
241         }
242         return false;
243     }
244
245     public static String capitalize(String name) {
246         if (name == null || name.length() == 0) {
247             return name;
248         }
249         char chars[] = name.toCharArray();
250         chars[0] = Character.toUpperCase(chars[0]);
251         return new String(chars);
252     }
253
254 }