1. /*
  2. * Copyright 1999-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.apache.commons.dbcp.datasources;
  17. import java.io.ByteArrayInputStream;
  18. import java.io.IOException;
  19. import java.io.ObjectInputStream;
  20. import java.util.Hashtable;
  21. import java.util.Map;
  22. import java.util.HashMap;
  23. import java.util.Iterator;
  24. import java.util.Properties;
  25. import javax.naming.Context;
  26. import javax.naming.Name;
  27. import javax.naming.RefAddr;
  28. import javax.naming.Reference;
  29. import javax.naming.spi.ObjectFactory;
  30. /**
  31. * A JNDI ObjectFactory which creates <code>SharedPoolDataSource</code>s
  32. * or <code>PerUserPoolDataSource</code>s
  33. *
  34. * @version $Revision: 1.9 $ $Date: 2004/02/28 21:51:59 $
  35. */
  36. abstract class InstanceKeyObjectFactory
  37. implements ObjectFactory
  38. {
  39. private static Map instanceMap = new HashMap();
  40. synchronized static String registerNewInstance(InstanceKeyDataSource ds) {
  41. int max = 0;
  42. Iterator i = instanceMap.keySet().iterator();
  43. while (i.hasNext()) {
  44. Object obj = i.next();
  45. if (obj instanceof String)
  46. {
  47. try {
  48. max = Math.max(max, Integer.valueOf((String)obj).intValue());
  49. }
  50. catch (NumberFormatException e) {
  51. // no sweat, ignore those keys
  52. }
  53. }
  54. }
  55. String instanceKey = String.valueOf(max + 1);
  56. // put a placeholder here for now, so other instances will not
  57. // take our key. we will replace with a pool when ready.
  58. instanceMap.put(instanceKey, ds);
  59. return instanceKey;
  60. }
  61. static void removeInstance(String key)
  62. {
  63. instanceMap.remove(key);
  64. }
  65. /**
  66. * Close all pools associated with this class.
  67. */
  68. public static void closeAll() throws Exception {
  69. //Get iterator to loop over all instances of this datasource.
  70. Iterator instanceIterator = instanceMap.entrySet().iterator();
  71. while (instanceIterator.hasNext()) {
  72. ((InstanceKeyDataSource)
  73. ((Map.Entry) instanceIterator.next()).getValue()).close();
  74. }
  75. instanceMap.clear();
  76. }
  77. /**
  78. * implements ObjectFactory to create an instance of SharedPoolDataSource
  79. * or PerUserPoolDataSource
  80. */
  81. public Object getObjectInstance(Object refObj, Name name,
  82. Context context, Hashtable env)
  83. throws IOException, ClassNotFoundException {
  84. // The spec says to return null if we can't create an instance
  85. // of the reference
  86. Object obj = null;
  87. if (refObj instanceof Reference) {
  88. Reference ref = (Reference) refObj;
  89. if (isCorrectClass(ref.getClassName())) {
  90. RefAddr ra = ref.get("instanceKey");
  91. if (ra != null && ra.getContent() != null) {
  92. // object was bound to jndi via Referenceable api.
  93. obj = instanceMap.get(ra.getContent());
  94. }
  95. else
  96. {
  97. // tomcat jndi creates a Reference out of server.xml
  98. // <ResourceParam> configuration and passes it to an
  99. // instance of the factory given in server.xml.
  100. String key = null;
  101. if (name != null)
  102. {
  103. key = name.toString();
  104. obj = instanceMap.get(key);
  105. }
  106. if (obj == null)
  107. {
  108. InstanceKeyDataSource ds = getNewInstance(ref);
  109. setCommonProperties(ref, ds);
  110. obj = ds;
  111. if (key != null)
  112. {
  113. instanceMap.put(key, ds);
  114. }
  115. }
  116. }
  117. }
  118. }
  119. return obj;
  120. }
  121. private void setCommonProperties(Reference ref,
  122. InstanceKeyDataSource ikds)
  123. throws IOException, ClassNotFoundException {
  124. RefAddr ra = ref.get("dataSourceName");
  125. if (ra != null && ra.getContent() != null) {
  126. ikds.setDataSourceName(ra.getContent().toString());
  127. }
  128. ra = ref.get("defaultAutoCommit");
  129. if (ra != null && ra.getContent() != null) {
  130. ikds.setDefaultAutoCommit(Boolean.valueOf(
  131. ra.getContent().toString()).booleanValue());
  132. }
  133. ra = ref.get("defaultReadOnly");
  134. if (ra != null && ra.getContent() != null) {
  135. ikds.setDefaultReadOnly(Boolean.valueOf(
  136. ra.getContent().toString()).booleanValue());
  137. }
  138. ra = ref.get("description");
  139. if (ra != null && ra.getContent() != null) {
  140. ikds.setDescription(ra.getContent().toString());
  141. }
  142. ra = ref.get("jndiEnvironment");
  143. if (ra != null && ra.getContent() != null) {
  144. byte[] serialized = (byte[]) ra.getContent();
  145. ikds.jndiEnvironment =
  146. (Properties) deserialize(serialized);
  147. }
  148. ra = ref.get("loginTimeout");
  149. if (ra != null && ra.getContent() != null) {
  150. ikds.setLoginTimeout(
  151. Integer.parseInt(ra.getContent().toString()));
  152. }
  153. ra = ref.get("testOnBorrow");
  154. if (ra != null && ra.getContent() != null) {
  155. ikds.setTestOnBorrow(
  156. Boolean.getBoolean(ra.getContent().toString()));
  157. }
  158. ra = ref.get("testOnReturn");
  159. if (ra != null && ra.getContent() != null) {
  160. ikds.setTestOnReturn(Boolean.valueOf(
  161. ra.getContent().toString()).booleanValue());
  162. }
  163. ra = ref.get("timeBetweenEvictionRunsMillis");
  164. if (ra != null && ra.getContent() != null) {
  165. ikds.setTimeBetweenEvictionRunsMillis(
  166. Integer.parseInt(ra.getContent().toString()));
  167. }
  168. ra = ref.get("numTestsPerEvictionRun");
  169. if (ra != null && ra.getContent() != null) {
  170. ikds.setNumTestsPerEvictionRun(
  171. Integer.parseInt(ra.getContent().toString()));
  172. }
  173. ra = ref.get("minEvictableIdleTimeMillis");
  174. if (ra != null && ra.getContent() != null) {
  175. ikds.setMinEvictableIdleTimeMillis(
  176. Integer.parseInt(ra.getContent().toString()));
  177. }
  178. ra = ref.get("testWhileIdle");
  179. if (ra != null && ra.getContent() != null) {
  180. ikds.setTestWhileIdle(Boolean.valueOf(
  181. ra.getContent().toString()).booleanValue());
  182. }
  183. ra = ref.get("validationQuery");
  184. if (ra != null && ra.getContent() != null) {
  185. ikds.setValidationQuery(ra.getContent().toString());
  186. }
  187. }
  188. /**
  189. * @return true if and only if className is the value returned
  190. * from getClass().getName().toString()
  191. */
  192. protected abstract boolean isCorrectClass(String className);
  193. /**
  194. * Creates an instance of the subclass and sets any properties
  195. * contained in the Reference.
  196. */
  197. protected abstract InstanceKeyDataSource getNewInstance(Reference ref)
  198. throws IOException, ClassNotFoundException;
  199. /**
  200. * used to set some properties saved within a Reference
  201. */
  202. protected static final Object deserialize(byte[] data)
  203. throws IOException, ClassNotFoundException {
  204. ObjectInputStream in = null;
  205. try {
  206. in = new ObjectInputStream(new ByteArrayInputStream(data));
  207. return in.readObject();
  208. } finally {
  209. try {
  210. in.close();
  211. } catch (IOException ex) {
  212. }
  213. }
  214. }
  215. }