1 package org.apache.torque.dsfactory;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.util.Hashtable;
20 import java.util.Iterator;
21 import java.util.Map;
22 import java.util.StringTokenizer;
23
24 import javax.naming.Context;
25 import javax.naming.InitialContext;
26 import javax.naming.NameAlreadyBoundException;
27 import javax.naming.NamingException;
28 import javax.sql.DataSource;
29
30 import org.apache.commons.configuration.Configuration;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 import org.apache.torque.TorqueException;
36
37 /***
38 * A factory that looks up the DataSource from JNDI. It is also able
39 * to deploy the DataSource based on properties found in the
40 * configuration.
41 *
42 * @author <a href="mailto:jmcnally@apache.org">John McNally</a>
43 * @version $Id: JndiDataSourceFactory.java,v 1.7 2004/02/22 06:18:52 jmcnally Exp $
44 */
45 public class JndiDataSourceFactory
46 extends AbstractDataSourceFactory
47 implements DataSourceFactory
48 {
49
50 /*** The log. */
51 private static Log log = LogFactory.getLog(JndiDataSourceFactory.class);
52
53 /*** The path to get the resource from. */
54 private String path;
55 /*** The context to get the resource from. */
56 private Context ctx;
57
58 /***
59 * @see org.apache.torque.dsfactory.DataSourceFactory#getDataSource
60 */
61 public DataSource getDataSource() throws TorqueException
62 {
63 DataSource ds = null;
64 try
65 {
66 ds = ((DataSource) ctx.lookup(path));
67 }
68 catch (Exception e)
69 {
70 throw new TorqueException(e);
71 }
72 return ds;
73 }
74
75 /***
76 * @see org.apache.torque.dsfactory.DataSourceFactory#initialize
77 */
78 public void initialize(Configuration configuration) throws TorqueException
79 {
80 if (configuration == null)
81 {
82 throw new TorqueException(
83 "Torque cannot be initialized without "
84 + "a valid configuration. Please check the log files "
85 + "for further details.");
86 }
87 initJNDI(configuration);
88 initDataSource(configuration);
89 }
90
91 /***
92 * Initializes JNDI.
93 *
94 * @param configuration where to read the settings from
95 * @throws TorqueException if a property set fails
96 */
97 private void initJNDI(Configuration configuration) throws TorqueException
98 {
99 log.debug("Starting initJNDI");
100 Hashtable env = null;
101 Configuration c = configuration.subset("jndi");
102 if (c == null)
103 {
104 throw new TorqueException(
105 "JndiDataSourceFactory requires a jndi "
106 + "path property to lookup the DataSource in JNDI.");
107 }
108 try
109 {
110 Iterator i = c.getKeys();
111 while (i.hasNext())
112 {
113 String key = (String) i.next();
114 if (key.equals("path"))
115 {
116 path = c.getString(key);
117 log.debug("JNDI path: " + path);
118 }
119 else
120 {
121 if (env == null)
122 {
123 env = new Hashtable();
124 }
125 String value = c.getString(key);
126 env.put(key, value);
127 log.debug("Set jndi property: " + key + "=" + value);
128 }
129 }
130 if (env == null)
131 {
132 ctx = new InitialContext();
133 }
134 else
135 {
136 ctx = new InitialContext(env);
137 }
138 log.debug("Created new InitialContext");
139 debugCtx(ctx);
140 }
141 catch (Exception e)
142 {
143 log.error("", e);
144 throw new TorqueException(e);
145 }
146 }
147
148 /***
149 * Initializes the DataSource.
150 *
151 * @param configuration where to read the settings from
152 * @throws TorqueException if a property set fails
153 */
154 private void initDataSource(Configuration configuration)
155 throws TorqueException
156 {
157 log.debug("Starting initDataSources");
158 Configuration c = configuration.subset("datasource");
159 try
160 {
161 if (c != null)
162 {
163 Object ds = null;
164 Iterator i = c.getKeys();
165 while (i.hasNext())
166 {
167 String key = (String) i.next();
168 if (key.equals("classname"))
169 {
170 String classname = c.getString(key);
171 log.debug("Datasource class: " + classname);
172
173 Class dsClass = Class.forName(classname);
174 ds = dsClass.newInstance();
175 }
176 else
177 {
178 log.debug("Setting datasource property: " + key);
179 setProperty(key, c, ds);
180 }
181 }
182
183 bindDStoJndi(ctx, path, ds);
184 }
185 }
186 catch (Exception e)
187 {
188 log.error("", e);
189 throw new TorqueException(e);
190 }
191 }
192
193 /***
194 *
195 * @param ctx the context
196 * @throws NamingException
197 */
198 private void debugCtx(Context ctx) throws NamingException
199 {
200 log.debug("InitialContext -------------------------------");
201 Map env = ctx.getEnvironment();
202 Iterator qw = env.keySet().iterator();
203 log.debug("Environment properties:" + env.size());
204 while (qw.hasNext())
205 {
206 Object prop = qw.next();
207 log.debug(" " + prop + ": " + env.get(prop));
208 }
209 log.debug("----------------------------------------------");
210 }
211
212 /***
213 *
214 * @param ctx
215 * @param path
216 * @param ds
217 * @throws Exception
218 */
219 private void bindDStoJndi(Context ctx, String path, Object ds)
220 throws Exception
221 {
222 debugCtx(ctx);
223
224
225 int start = path.indexOf(':') + 1;
226 if (start > 0)
227 {
228 path = path.substring(start);
229 }
230 StringTokenizer st = new StringTokenizer(path, "/");
231 while (st.hasMoreTokens())
232 {
233 String subctx = st.nextToken();
234 if (st.hasMoreTokens())
235 {
236 try
237 {
238 ctx.createSubcontext(subctx);
239 log.debug("Added sub context: " + subctx);
240 }
241 catch (NameAlreadyBoundException nabe)
242 {
243
244 }
245 catch (NamingException ne)
246 {
247
248
249
250
251
252
253
254
255
256
257 }
258 ctx = (Context) ctx.lookup(subctx);
259 }
260 else
261 {
262
263 ctx.bind(subctx, ds);
264 }
265 }
266 }
267 }