Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ConnectionAdaptor |
|
| 2.625;2.625 |
1 | /* | |
2 | * Copyright 2001,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 | ||
17 | package org.apache.commons.scaffold.sql; | |
18 | ||
19 | ||
20 | import java.sql.Connection; | |
21 | import java.sql.SQLException; | |
22 | ||
23 | import javax.naming.Context; | |
24 | import javax.naming.InitialContext; | |
25 | import javax.naming.NamingException; | |
26 | import javax.sql.DataSource; | |
27 | ||
28 | ||
29 | /** | |
30 | * Base class for SQL connection adaptors. May be used as-is or subclassed. | |
31 | * <p> | |
32 | * This object does not provide any type of connection pooling. | |
33 | * It simply provides a standard means for obtaining a connection | |
34 | * whatever connection pool your application needs. | |
35 | * Scaffold classes in the SQL package call this object internally. | |
36 | * <p> | |
37 | * To use as-is, a DataSource compliant connection pool must be | |
38 | * available as "DATA_SOURCE" via JNDI. A subclass can | |
39 | * locate the pool under any name by any means necessary. | |
40 | *<p> | |
41 | * A <code>ConnectionAdaptor</code> can be instantiated once at | |
42 | * start-up, either from main() or via a servlet, like the | |
43 | * Scaffold ConnectionServlet. | |
44 | * Objects needing a connection can then call the static | |
45 | * method | |
46 | * <code>ConnectionAdaptor.getPool().getConnection()</code>. | |
47 | * <p> | |
48 | * Most implementations will expect callers to use and | |
49 | * close the connections promptly, since they would | |
50 | * usually be part of a pool. | |
51 | * <p> | |
52 | * Subclasses can provide their own resource name or | |
53 | * getConnection() method, and a new constructor to | |
54 | * set the protected pool field to their own | |
55 | * instance. See <code>PoolmanAdaptor</code> for an example. | |
56 | * | |
57 | * @see org.apache.commons.scaffold.http.ConnectionServlet | |
58 | * @see org.apache.commons.scaffold.sql.PoolmanAdaptor | |
59 | * @author Ted Husted | |
60 | * @version $Revision: 155464 $ $Date: 2005-02-26 13:26:54 +0000 (Sat, 26 Feb 2005) $ | |
61 | */ | |
62 | 0 | public class ConnectionAdaptor { |
63 | ||
64 | ||
65 | // ------------------------------------------------------------ message | |
66 | ||
67 | /** | |
68 | * A message for an exception if pool returns null. | |
69 | */ | |
70 | 0 | private String message = "Connection pool " + |
71 | "not available. Check your configuration."; | |
72 | ||
73 | ||
74 | /** | |
75 | * Return a message for an exception if pool returns null. | |
76 | * | |
77 | * @return Message for an exception if pool returns null | |
78 | */ | |
79 | protected String getMessage() { | |
80 | 0 | return this.message; |
81 | } | |
82 | ||
83 | ||
84 | /** | |
85 | * Set a message for an exception if pool returns null. | |
86 | * Adaptor subclasses can call this from their constructor. | |
87 | * | |
88 | * @param Message The message for an exception if pool returns null | |
89 | */ | |
90 | protected void setMessage(String message) { | |
91 | 0 | this.message = message; |
92 | 0 | } |
93 | ||
94 | ||
95 | // ---------------------------------------------------------------- key | |
96 | ||
97 | ||
98 | /** | |
99 | * The default DataSource name. | |
100 | */ | |
101 | public static final String DATA_SOURCE_KEY = "DATA_SOURCE"; | |
102 | ||
103 | ||
104 | /** | |
105 | * The default JNDI context for applications. | |
106 | */ | |
107 | public static final String JNDI_CONTEXT_KEY = "java:comp/env"; | |
108 | ||
109 | ||
110 | /** | |
111 | * The attribute under which our DataSource is stored | |
112 | * [DATA_SOURCE_KEY]. | |
113 | */ | |
114 | 0 | private String key = DATA_SOURCE_KEY; |
115 | ||
116 | ||
117 | /** | |
118 | * Return the attribute under which our datasource is stored. | |
119 | * Subclasses may override this method to provide a different key, | |
120 | * or set a new key at construction. | |
121 | */ | |
122 | public String getKey() { | |
123 | 0 | return this.key; |
124 | } | |
125 | ||
126 | ||
127 | /** | |
128 | * The attribute under which our datasource is stored. | |
129 | * Adaptor subclasses can call this method from a constructor | |
130 | * to change the default resource name. | |
131 | */ | |
132 | public void setKey(String key) { | |
133 | 0 | this.key = key; |
134 | 0 | } |
135 | ||
136 | ||
137 | // --------------------------------------------------------- datasource | |
138 | ||
139 | /** | |
140 | * Field to store singleton reference to default datasource. | |
141 | * | |
142 | * TODO: Add Map to store reference to other datasoruces. | |
143 | */ | |
144 | protected static DataSource datasource; | |
145 | ||
146 | ||
147 | /** | |
148 | * Return datasource using JNDI lookup. Subclasses may | |
149 | * override this method to provide other means of obtaining | |
150 | * a datasource reference. | |
151 | * | |
152 | * @param key The attribute name for the resource. | |
153 | * If null is passed, null is returned. | |
154 | * @return null or the datasource object related to "key" | |
155 | * | |
156 | * TODO: Add cache to store references to the datasources by key. | |
157 | */ | |
158 | protected DataSource getDataSource(String key) | |
159 | throws SQLException { | |
160 | ||
161 | 0 | if (null==key) return null; |
162 | ||
163 | try { | |
164 | ||
165 | 0 | Context env = (Context) new |
166 | InitialContext().lookup(JNDI_CONTEXT_KEY); | |
167 | ||
168 | 0 | return (DataSource) env.lookup(key); |
169 | ||
170 | } | |
171 | ||
172 | 0 | catch (NamingException ne) { |
173 | // Recast naming exception, | |
174 | // since that is what other routines only except | |
175 | // and because another implementation may not generate this. | |
176 | // Should only be an issue during initial setup | |
177 | ||
178 | 0 | throw new SQLException(ne.getMessage()); |
179 | } | |
180 | ||
181 | } // end getDataSource | |
182 | ||
183 | ||
184 | // --------------------------------------------------------- connection | |
185 | ||
186 | /** | |
187 | * Returns a JDBC connection from the default resource. | |
188 | * Calls <code>getDatasource</code> to return the resource | |
189 | * associated with the default attribute name [getKey()]. | |
190 | * <p> | |
191 | * The default datasource object is cached and reused in subsequent | |
192 | * calls. | |
193 | * | |
194 | * @return JDBC connection from resource layer. | |
195 | * @exception SQLException on SQL or other errors. May wrap other | |
196 | * exceptions depending on implementation. Will not return null. | |
197 | */ | |
198 | public Connection getConnection() throws SQLException { | |
199 | ||
200 | 0 | if (null==datasource) { |
201 | ||
202 | 0 | datasource = getDataSource(getKey()); |
203 | ||
204 | 0 | if (null==datasource) |
205 | 0 | throw new SQLException(getMessage()); |
206 | } | |
207 | ||
208 | 0 | return (datasource.getConnection()); |
209 | ||
210 | } // end getConnection | |
211 | ||
212 | ||
213 | /** | |
214 | * Returns a JDBC connection from a connection pool or other | |
215 | * named resource, to be used and closed promptly. | |
216 | * <p> | |
217 | * Default implementation uses JNDI to lookup the resource named by | |
218 | * getResource() ["DATASOURCE"]. | |
219 | * Will not return null. | |
220 | * | |
221 | * @return JDBC connection from resource layer. | |
222 | * @exception SQLException on SQL or other errors. May wrap | |
223 | * other exceptions depending on implementation. | |
224 | * @param resource An attribute name for the resource to use for | |
225 | * this connection or null to call getResource() | |
226 | * @return A working connection; will not return null | |
227 | * @exception SQLException On any SQL error or if pool returns null | |
228 | */ | |
229 | public Connection getConnection(String key) | |
230 | throws SQLException { | |
231 | ||
232 | 0 | if (null==key) return getConnection(); |
233 | ||
234 | 0 | DataSource ds = getDataSource(key); |
235 | ||
236 | 0 | if (null==ds) |
237 | 0 | throw new SQLException(getMessage()); |
238 | ||
239 | 0 | return (ds.getConnection()); |
240 | ||
241 | } // end getConnection | |
242 | ||
243 | ||
244 | // --------------------------------------------------------------- pool | |
245 | ||
246 | ||
247 | /** | |
248 | * Field to store singleton reference to adaptor pool. | |
249 | * This would usually be private for a singleton, | |
250 | * but adaptor subclasses may set the pool upon initialization. | |
251 | * <p> | |
252 | * <code>if (null==pool) set pool = this</code>. | |
253 | */ | |
254 | protected static ConnectionAdaptor pool; | |
255 | ||
256 | ||
257 | /** | |
258 | * Return adaptor instance to use in acquiring connection. | |
259 | * <p> | |
260 | * This is the main entry method to the object. | |
261 | * Client's should call:<br> | |
262 | * <code>Adaptor.getPool().getConnection()</code> | |
263 | * to acquire a connection from the default pool. | |
264 | */ | |
265 | public static ConnectionAdaptor getPool() { | |
266 | ||
267 | 0 | if (null==pool) pool = new ConnectionAdaptor(); |
268 | 0 | return pool; |
269 | ||
270 | } // end getPool | |
271 | ||
272 | ||
273 | } // end ConnectionAdaptor | |
274 |