1 package org.apache.torque.dsfactory;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.util.Hashtable;
58 import java.util.Iterator;
59 import java.util.Map;
60 import java.util.StringTokenizer;
61
62 import javax.naming.Context;
63 import javax.naming.InitialContext;
64 import javax.naming.NameAlreadyBoundException;
65 import javax.naming.NamingException;
66 import javax.sql.DataSource;
67
68 import org.apache.commons.configuration.Configuration;
69
70 import org.apache.commons.logging.Log;
71 import org.apache.commons.logging.LogFactory;
72
73 import org.apache.torque.TorqueException;
74
75 /***
76 * A factory that looks up the DataSource from JNDI. It is also able
77 * to deploy the DataSource based on properties found in the
78 * configuration.
79 *
80 * @author <a href="mailto:jmcnally@apache.org">John McNally</a>
81 * @version $Id: JndiDataSourceFactory.java,v 1.6 2003/05/14 19:38:04 mpoeschl Exp $
82 */
83 public class JndiDataSourceFactory
84 extends AbstractDataSourceFactory
85 implements DataSourceFactory
86 {
87
88 /*** The log. */
89 private static Log log = LogFactory.getLog(JndiDataSourceFactory.class);
90
91 /*** The path to get the resource from. */
92 private String path;
93 /*** The context to get the resource from. */
94 private Context ctx;
95
96 /***
97 * @see org.apache.torque.dsfactory.DataSourceFactory#getDataSource
98 */
99 public DataSource getDataSource() throws TorqueException
100 {
101 DataSource ds = null;
102 try
103 {
104 ds = ((DataSource) ctx.lookup(path));
105 }
106 catch (Exception e)
107 {
108 throw new TorqueException(e);
109 }
110 return ds;
111 }
112
113 /***
114 * @see org.apache.torque.dsfactory.DataSourceFactory#initialize
115 */
116 public void initialize(Configuration configuration) throws TorqueException
117 {
118 if (configuration == null)
119 {
120 throw new TorqueException(
121 "Torque cannot be initialized without "
122 + "a valid configuration. Please check the log files "
123 + "for further details.");
124 }
125 initJNDI(configuration);
126 initDataSource(configuration);
127 }
128
129 /***
130 * Initializes JNDI.
131 *
132 * @param configuration where to read the settings from
133 * @throws TorqueException if a property set fails
134 */
135 private void initJNDI(Configuration configuration) throws TorqueException
136 {
137 log.debug("Starting initJNDI");
138 Hashtable env = null;
139 Configuration c = configuration.subset("jndi");
140 if (c == null)
141 {
142 throw new TorqueException(
143 "JndiDataSourceFactory requires a jndi "
144 + "path property to lookup the DataSource in JNDI.");
145 }
146 try
147 {
148 Iterator i = c.getKeys();
149 while (i.hasNext())
150 {
151 String key = (String) i.next();
152 if (key.equals("path"))
153 {
154 path = c.getString(key);
155 log.debug("JNDI path: " + path);
156 }
157 else
158 {
159 if (env == null)
160 {
161 env = new Hashtable();
162 }
163 String value = c.getString(key);
164 env.put(key, value);
165 log.debug("Set jndi property: " + key + "=" + value);
166 }
167 }
168 if (env == null)
169 {
170 ctx = new InitialContext();
171 }
172 else
173 {
174 ctx = new InitialContext(env);
175 }
176 log.debug("Created new InitialContext");
177 debugCtx(ctx);
178 }
179 catch (Exception e)
180 {
181 log.error("", e);
182 throw new TorqueException(e);
183 }
184 }
185
186 /***
187 * Initializes the DataSource.
188 *
189 * @param configuration where to read the settings from
190 * @throws TorqueException if a property set fails
191 */
192 private void initDataSource(Configuration configuration)
193 throws TorqueException
194 {
195 log.debug("Starting initDataSources");
196 Configuration c = configuration.subset("datasource");
197 try
198 {
199 if (c != null)
200 {
201 Object ds = null;
202 Iterator i = c.getKeys();
203 while (i.hasNext())
204 {
205 String key = (String) i.next();
206 if (key.equals("classname"))
207 {
208 String classname = c.getString(key);
209 log.debug("Datasource class: " + classname);
210
211 Class dsClass = Class.forName(classname);
212 ds = dsClass.newInstance();
213 }
214 else
215 {
216 log.debug("Setting datasource property: " + key);
217 setProperty(key, c, ds);
218 }
219 }
220
221 bindDStoJndi(ctx, path, ds);
222 }
223 }
224 catch (Exception e)
225 {
226 log.error("", e);
227 throw new TorqueException(e);
228 }
229 }
230
231 /***
232 *
233 * @param ctx the context
234 * @throws NamingException
235 */
236 private void debugCtx(Context ctx) throws NamingException
237 {
238 log.debug("InitialContext -------------------------------");
239 Map env = ctx.getEnvironment();
240 Iterator qw = env.keySet().iterator();
241 log.debug("Environment properties:" + env.size());
242 while (qw.hasNext())
243 {
244 Object prop = qw.next();
245 log.debug(" " + prop + ": " + env.get(prop));
246 }
247 log.debug("----------------------------------------------");
248 }
249
250 /***
251 *
252 * @param ctx
253 * @param path
254 * @param ds
255 * @throws Exception
256 */
257 private void bindDStoJndi(Context ctx, String path, Object ds)
258 throws Exception
259 {
260 debugCtx(ctx);
261
262 // add subcontexts, if not added already
263 int start = path.indexOf(':') + 1;
264 if (start > 0)
265 {
266 path = path.substring(start);
267 }
268 StringTokenizer st = new StringTokenizer(path, "/");
269 while (st.hasMoreTokens())
270 {
271 String subctx = st.nextToken();
272 if (st.hasMoreTokens())
273 {
274 try
275 {
276 ctx.createSubcontext(subctx);
277 log.debug("Added sub context: " + subctx);
278 }
279 catch (NameAlreadyBoundException nabe)
280 {
281 // ignore
282 }
283 catch (NamingException ne)
284 {
285 // even though there is a specific exception
286 // for this condition, some implementations
287 // throw the more general one.
288 /*
289 if (ne.getMessage().indexOf("already bound") == -1 )
290 {
291 throw ne;
292 }
293 */
294 // ignore
295 }
296 ctx = (Context) ctx.lookup(subctx);
297 }
298 else
299 {
300 // not really a subctx, it is the ds name
301 ctx.bind(subctx, ds);
302 }
303 }
304 }
305 }
This page was automatically generated by Maven