001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.commons.dbcp.datasources;
019:
020: import java.io.ByteArrayInputStream;
021: import java.io.IOException;
022: import java.io.ObjectInputStream;
023:
024: import java.util.Hashtable;
025: import java.util.Map;
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.Properties;
029:
030: import javax.naming.Context;
031: import javax.naming.Name;
032: import javax.naming.RefAddr;
033: import javax.naming.Reference;
034: import javax.naming.spi.ObjectFactory;
035:
036: /**
037: * A JNDI ObjectFactory which creates <code>SharedPoolDataSource</code>s
038: * or <code>PerUserPoolDataSource</code>s
039: *
040: * @version $Revision: 479137 $ $Date: 2006-11-25 08:51:48 -0700 (Sat, 25 Nov 2006) $
041: */
042: abstract class InstanceKeyObjectFactory implements ObjectFactory {
043: private static Map instanceMap = new HashMap();
044:
045: synchronized static String registerNewInstance(
046: InstanceKeyDataSource ds) {
047: int max = 0;
048: Iterator i = instanceMap.keySet().iterator();
049: while (i.hasNext()) {
050: Object obj = i.next();
051: if (obj instanceof String) {
052: try {
053: max = Math.max(max, Integer.valueOf((String) obj)
054: .intValue());
055: } catch (NumberFormatException e) {
056: // no sweat, ignore those keys
057: }
058: }
059: }
060: String instanceKey = String.valueOf(max + 1);
061: // put a placeholder here for now, so other instances will not
062: // take our key. we will replace with a pool when ready.
063: instanceMap.put(instanceKey, ds);
064: return instanceKey;
065: }
066:
067: static void removeInstance(String key) {
068: instanceMap.remove(key);
069: }
070:
071: /**
072: * Close all pools associated with this class.
073: */
074: public static void closeAll() throws Exception {
075: //Get iterator to loop over all instances of this datasource.
076: Iterator instanceIterator = instanceMap.entrySet().iterator();
077: while (instanceIterator.hasNext()) {
078: ((InstanceKeyDataSource) ((Map.Entry) instanceIterator
079: .next()).getValue()).close();
080: }
081: instanceMap.clear();
082: }
083:
084: /**
085: * implements ObjectFactory to create an instance of SharedPoolDataSource
086: * or PerUserPoolDataSource
087: */
088: public Object getObjectInstance(Object refObj, Name name,
089: Context context, Hashtable env) throws IOException,
090: ClassNotFoundException {
091: // The spec says to return null if we can't create an instance
092: // of the reference
093: Object obj = null;
094: if (refObj instanceof Reference) {
095: Reference ref = (Reference) refObj;
096: if (isCorrectClass(ref.getClassName())) {
097: RefAddr ra = ref.get("instanceKey");
098: if (ra != null && ra.getContent() != null) {
099: // object was bound to jndi via Referenceable api.
100: obj = instanceMap.get(ra.getContent());
101: } else {
102: // tomcat jndi creates a Reference out of server.xml
103: // <ResourceParam> configuration and passes it to an
104: // instance of the factory given in server.xml.
105: String key = null;
106: if (name != null) {
107: key = name.toString();
108: obj = instanceMap.get(key);
109: }
110: if (obj == null) {
111: InstanceKeyDataSource ds = getNewInstance(ref);
112: setCommonProperties(ref, ds);
113: obj = ds;
114: if (key != null) {
115: instanceMap.put(key, ds);
116: }
117: }
118: }
119: }
120: }
121: return obj;
122: }
123:
124: private void setCommonProperties(Reference ref,
125: InstanceKeyDataSource ikds) throws IOException,
126: ClassNotFoundException {
127:
128: RefAddr ra = ref.get("dataSourceName");
129: if (ra != null && ra.getContent() != null) {
130: ikds.setDataSourceName(ra.getContent().toString());
131: }
132:
133: ra = ref.get("defaultAutoCommit");
134: if (ra != null && ra.getContent() != null) {
135: ikds.setDefaultAutoCommit(Boolean.valueOf(
136: ra.getContent().toString()).booleanValue());
137: }
138:
139: ra = ref.get("defaultReadOnly");
140: if (ra != null && ra.getContent() != null) {
141: ikds.setDefaultReadOnly(Boolean.valueOf(
142: ra.getContent().toString()).booleanValue());
143: }
144:
145: ra = ref.get("description");
146: if (ra != null && ra.getContent() != null) {
147: ikds.setDescription(ra.getContent().toString());
148: }
149:
150: ra = ref.get("jndiEnvironment");
151: if (ra != null && ra.getContent() != null) {
152: byte[] serialized = (byte[]) ra.getContent();
153: ikds.jndiEnvironment = (Properties) deserialize(serialized);
154: }
155:
156: ra = ref.get("loginTimeout");
157: if (ra != null && ra.getContent() != null) {
158: ikds.setLoginTimeout(Integer.parseInt(ra.getContent()
159: .toString()));
160: }
161:
162: ra = ref.get("testOnBorrow");
163: if (ra != null && ra.getContent() != null) {
164: ikds.setTestOnBorrow(Boolean.getBoolean(ra.getContent()
165: .toString()));
166: }
167:
168: ra = ref.get("testOnReturn");
169: if (ra != null && ra.getContent() != null) {
170: ikds.setTestOnReturn(Boolean.valueOf(
171: ra.getContent().toString()).booleanValue());
172: }
173:
174: ra = ref.get("timeBetweenEvictionRunsMillis");
175: if (ra != null && ra.getContent() != null) {
176: ikds.setTimeBetweenEvictionRunsMillis(Integer.parseInt(ra
177: .getContent().toString()));
178: }
179:
180: ra = ref.get("numTestsPerEvictionRun");
181: if (ra != null && ra.getContent() != null) {
182: ikds.setNumTestsPerEvictionRun(Integer.parseInt(ra
183: .getContent().toString()));
184: }
185:
186: ra = ref.get("minEvictableIdleTimeMillis");
187: if (ra != null && ra.getContent() != null) {
188: ikds.setMinEvictableIdleTimeMillis(Integer.parseInt(ra
189: .getContent().toString()));
190: }
191:
192: ra = ref.get("testWhileIdle");
193: if (ra != null && ra.getContent() != null) {
194: ikds.setTestWhileIdle(Boolean.valueOf(
195: ra.getContent().toString()).booleanValue());
196: }
197:
198: ra = ref.get("validationQuery");
199: if (ra != null && ra.getContent() != null) {
200: ikds.setValidationQuery(ra.getContent().toString());
201: }
202: }
203:
204: /**
205: * @return true if and only if className is the value returned
206: * from getClass().getName().toString()
207: */
208: protected abstract boolean isCorrectClass(String className);
209:
210: /**
211: * Creates an instance of the subclass and sets any properties
212: * contained in the Reference.
213: */
214: protected abstract InstanceKeyDataSource getNewInstance(
215: Reference ref) throws IOException, ClassNotFoundException;
216:
217: /**
218: * used to set some properties saved within a Reference
219: */
220: protected static final Object deserialize(byte[] data)
221: throws IOException, ClassNotFoundException {
222: ObjectInputStream in = null;
223: try {
224: in = new ObjectInputStream(new ByteArrayInputStream(data));
225: return in.readObject();
226: } finally {
227: if (in != null) {
228: try {
229: in.close();
230: } catch (IOException ex) {
231: }
232: }
233: }
234: }
235: }
|