1 package org.apache.torque.dsfactory; 2 3 21 22 import java.util.Hashtable ; 23 import java.util.Iterator ; 24 import java.util.Map ; 25 import java.util.StringTokenizer ; 26 27 import javax.naming.Context ; 28 import javax.naming.InitialContext ; 29 import javax.naming.NameAlreadyBoundException ; 30 import javax.naming.NamingException ; 31 import javax.sql.DataSource ; 32 33 import org.apache.commons.configuration.Configuration; 34 35 import org.apache.commons.logging.Log; 36 import org.apache.commons.logging.LogFactory; 37 38 import org.apache.torque.TorqueException; 39 40 52 public class JndiDataSourceFactory 53 extends AbstractDataSourceFactory 54 { 55 58 public static final String JNDI_KEY = "jndi"; 59 60 63 public static final String PATH_KEY = "path"; 64 65 69 public static final String TIME_BETWEEN_LOOKUPS_KEY = "ttl"; 70 71 75 public static final String DATASOURCE_KEY = "datasource"; 76 77 81 public static final String CLASSNAME_KEY = "classname"; 82 83 84 private static Log log = LogFactory.getLog(JndiDataSourceFactory.class); 85 86 87 private String path; 88 89 private Context ctx; 90 91 92 private DataSource ds = null; 93 94 95 private long lastLookup = 0; 96 97 98 private long ttl = 0; 100 103 public DataSource getDataSource() throws TorqueException 104 { 105 long time = System.currentTimeMillis(); 106 107 if (ds == null || time - lastLookup > ttl) 108 { 109 try 110 { 111 ds = ((DataSource ) ctx.lookup(path)); 112 lastLookup = time; 113 } 114 catch (Exception e) 115 { 116 throw new TorqueException(e); 117 } 118 } 119 120 return ds; 121 } 122 123 126 public void initialize(Configuration configuration) throws TorqueException 127 { 128 super.initialize(configuration); 129 130 initJNDI(configuration); 131 initDataSource(configuration); 132 } 133 134 140 private void initJNDI(Configuration configuration) throws TorqueException 141 { 142 log.debug("Starting initJNDI"); 143 144 Configuration c = configuration.subset(JNDI_KEY); 145 if (c == null || c.isEmpty()) 146 { 147 throw new TorqueException( 148 "JndiDataSourceFactory requires a jndi " 149 + "path property to lookup the DataSource in JNDI."); 150 } 151 152 try 153 { 154 Hashtable env = new Hashtable (); 155 for (Iterator i = c.getKeys(); i.hasNext();) 156 { 157 String key = (String ) i.next(); 158 if (key.equals(PATH_KEY)) 159 { 160 path = c.getString(key); 161 if (log.isDebugEnabled()) 162 { 163 log.debug("JNDI path: " + path); 164 } 165 } 166 else if (key.equals(TIME_BETWEEN_LOOKUPS_KEY)) 167 { 168 ttl = c.getLong(key, ttl); 169 if (log.isDebugEnabled()) 170 { 171 log.debug("Time between context lookups: " + ttl); 172 } 173 } 174 else 175 { 176 String value = c.getString(key); 177 env.put(key, value); 178 if (log.isDebugEnabled()) 179 { 180 log.debug("Set jndi property: " + key + "=" + value); 181 } 182 } 183 } 184 185 ctx = new InitialContext (env); 186 log.debug("Created new InitialContext"); 187 debugCtx(ctx); 188 } 189 catch (Exception e) 190 { 191 log.error("", e); 192 throw new TorqueException(e); 193 } 194 } 195 196 202 private void initDataSource(Configuration configuration) 203 throws TorqueException 204 { 205 log.debug("Starting initDataSource"); 206 try 207 { 208 Object dataSource = null; 209 210 Configuration c = configuration.subset(DATASOURCE_KEY); 211 if (c != null) 212 { 213 for (Iterator i = c.getKeys(); i.hasNext();) 214 { 215 String key = (String ) i.next(); 216 if (key.equals(CLASSNAME_KEY)) 217 { 218 String classname = c.getString(key); 219 if (log.isDebugEnabled()) 220 { 221 log.debug("Datasource class: " + classname); 222 } 223 224 Class dsClass = Class.forName(classname); 225 dataSource = dsClass.newInstance(); 226 } 227 else 228 { 229 if (dataSource != null) 230 { 231 if (log.isDebugEnabled()) 232 { 233 log.debug("Setting datasource property: " + key); 234 } 235 setProperty(key, c, dataSource); 236 } 237 else 238 { 239 log.error("Tried to set property " + key 240 + " without Datasource definition!"); 241 } 242 } 243 } 244 } 245 246 if (dataSource != null) 247 { 248 bindDStoJndi(ctx, path, dataSource); 249 } 250 } 251 catch (Exception e) 252 { 253 log.error("", e); 254 throw new TorqueException(e); 255 } 256 } 257 258 262 public void close() 263 { 264 } 266 267 272 private void debugCtx(Context ctx) throws NamingException 273 { 274 log.debug("InitialContext -------------------------------"); 275 Map env = ctx.getEnvironment(); 276 Iterator qw = env.entrySet().iterator(); 277 log.debug("Environment properties:" + env.size()); 278 while (qw.hasNext()) 279 { 280 Map.Entry entry = (Map.Entry ) qw.next(); 281 log.debug(" " + entry.getKey() + ": " + entry.getValue()); 282 } 283 log.debug("----------------------------------------------"); 284 } 285 286 293 private void bindDStoJndi(Context ctx, String path, Object ds) 294 throws Exception 295 { 296 debugCtx(ctx); 297 298 int start = path.indexOf(':') + 1; 300 if (start > 0) 301 { 302 path = path.substring(start); 303 } 304 StringTokenizer st = new StringTokenizer (path, "/"); 305 while (st.hasMoreTokens()) 306 { 307 String subctx = st.nextToken(); 308 if (st.hasMoreTokens()) 309 { 310 try 311 { 312 ctx.createSubcontext(subctx); 313 log.debug("Added sub context: " + subctx); 314 } 315 catch (NameAlreadyBoundException nabe) 316 { 317 log.debug("Sub context " + subctx + " already exists"); 319 } 320 catch (NamingException ne) 321 { 322 log.debug("Naming exception caught " 323 + "when creating subcontext" 324 + subctx, 325 ne); 326 335 } 337 ctx = (Context ) ctx.lookup(subctx); 338 } 339 else 340 { 341 ctx.bind(subctx, ds); 343 } 344 } 345 } 346 } 347 | Popular Tags |