Coverage report

  %line %branch
org.apache.torque.dsfactory.JndiDataSourceFactory
0% 
0% 

 1  
 package org.apache.torque.dsfactory;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2005 The Apache Software Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License")
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 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  
  * This factory tries to avoid excessive context lookups to improve speed.
 43  
  * The time between two lookups can be configured. The default is 0 (no cache).
 44  
  *
 45  
  * @author <a href="mailto:jmcnally@apache.org">John McNally</a>
 46  
  * @author <a href="mailto:thomas@vandahl.org">Thomas Vandahl</a>
 47  
  * @version $Id: JndiDataSourceFactory.java 239636 2005-08-24 12:38:09Z henning $
 48  
  */
 49  0
 public class JndiDataSourceFactory
 50  
     extends AbstractDataSourceFactory
 51  
     implements DataSourceFactory
 52  
 {
 53  
 
 54  
     /** The log. */
 55  0
     private static Log log = LogFactory.getLog(JndiDataSourceFactory.class);
 56  
 
 57  
     /** The path to get the resource from. */
 58  
     private String path;
 59  
     /** The context to get the resource from. */
 60  
     private Context ctx;
 61  
 
 62  
     /** A locally cached copy of the DataSource */
 63  0
     private DataSource ds = null;
 64  
 
 65  
     /** Time of last actual lookup action */
 66  0
     private long lastLookup = 0;
 67  
 
 68  
     /** Time between two lookups */
 69  0
     private long ttl = 0; // ms
 70  
 
 71  
     /**
 72  
      * @see org.apache.torque.dsfactory.DataSourceFactory#getDataSource
 73  
      */
 74  
     public DataSource getDataSource() throws TorqueException
 75  
     {
 76  0
         long time = System.currentTimeMillis();
 77  
 
 78  0
         if (ds == null || time - lastLookup > ttl)
 79  
         {
 80  
             try
 81  
             {
 82  0
                 ds = ((DataSource) ctx.lookup(path));
 83  0
                 lastLookup = time;
 84  
             }
 85  0
             catch (Exception e)
 86  
             {
 87  0
                 throw new TorqueException(e);
 88  0
             }
 89  
         }
 90  
 
 91  0
         return ds;
 92  
     }
 93  
 
 94  
     /**
 95  
      * @see org.apache.torque.dsfactory.DataSourceFactory#initialize
 96  
      */
 97  
     public void initialize(Configuration configuration) throws TorqueException
 98  
     {
 99  0
         super.initialize(configuration);
 100  
 
 101  0
         initJNDI(configuration);
 102  0
         initDataSource(configuration);
 103  0
     }
 104  
 
 105  
     /**
 106  
      * Initializes JNDI.
 107  
      *
 108  
      * @param configuration where to read the settings from
 109  
      * @throws TorqueException if a property set fails
 110  
      */
 111  
     private void initJNDI(Configuration configuration) throws TorqueException
 112  
     {
 113  0
         log.debug("Starting initJNDI");
 114  
 
 115  0
         Configuration c = configuration.subset("jndi");
 116  0
         if (c == null || c.isEmpty())
 117  
         {
 118  0
             throw new TorqueException(
 119  
                 "JndiDataSourceFactory requires a jndi "
 120  
                     + "path property to lookup the DataSource in JNDI.");
 121  
         }
 122  
 
 123  
         try
 124  
         {
 125  0
             Hashtable env = new Hashtable();
 126  0
             for (Iterator i = c.getKeys(); i.hasNext(); )
 127  
             {
 128  0
                 String key = (String) i.next();
 129  0
                 if (key.equals("path"))
 130  
                 {
 131  0
                     path = c.getString(key);
 132  0
                     if (log.isDebugEnabled())
 133  
                     {
 134  0
                         log.debug("JNDI path: " + path);
 135  
                     }
 136  
                 }
 137  0
                 else if (key.equals("ttl"))
 138  
                 {
 139  0
                     ttl = c.getLong(key, ttl);
 140  0
                     if (log.isDebugEnabled())
 141  
                     {
 142  0
                         log.debug("Time between context lookups: " + ttl);
 143  
                     }
 144  
                 }
 145  
                 else
 146  
                 {
 147  0
                     String value = c.getString(key);
 148  0
                     env.put(key, value);
 149  0
                     if (log.isDebugEnabled())
 150  
                     {
 151  0
                         log.debug("Set jndi property: " + key + "=" + value);
 152  
                     }
 153  
                 }
 154  
             }
 155  
 
 156  0
             ctx = new InitialContext(env);
 157  0
             log.debug("Created new InitialContext");
 158  0
             debugCtx(ctx);
 159  
         }
 160  0
         catch (Exception e)
 161  
         {
 162  0
             log.error("", e);
 163  0
             throw new TorqueException(e);
 164  0
         }
 165  0
     }
 166  
 
 167  
     /**
 168  
      * Initializes the DataSource.
 169  
      *
 170  
      * @param configuration where to read the settings from
 171  
      * @throws TorqueException if a property set fails
 172  
      */
 173  
     private void initDataSource(Configuration configuration)
 174  
         throws TorqueException
 175  
     {
 176  0
         log.debug("Starting initDataSource");
 177  
         try
 178  
         {
 179  0
             Object ds = null;
 180  
 
 181  0
             Configuration c = configuration.subset("datasource");
 182  0
             if (c != null)
 183  
             {
 184  0
                 for (Iterator i = c.getKeys(); i.hasNext(); )
 185  
                 {
 186  0
                     String key = (String) i.next();
 187  0
                     if (key.equals("classname"))
 188  
                     {
 189  0
                         String classname = c.getString(key);
 190  0
                         if (log.isDebugEnabled())
 191  
                         {
 192  0
                             log.debug("Datasource class: " + classname);
 193  
                         }
 194  
 
 195  0
                         Class dsClass = Class.forName(classname);
 196  0
                         ds = dsClass.newInstance();
 197  
                     }
 198  
                     else
 199  
                     {
 200  0
                         if (ds != null)
 201  
                         {
 202  0
                             if (log.isDebugEnabled())
 203  
                             {
 204  0
                                 log.debug("Setting datasource property: " + key);
 205  
                             }
 206  0
                             setProperty(key, c, ds);
 207  
                         }
 208  
                         else
 209  
                         {
 210  0
                             log.error("Tried to set property " + key + " without Datasource definition!");
 211  
                         }
 212  
                     }
 213  
                 }
 214  
             }
 215  
 
 216  0
             if (ds != null)
 217  
             {
 218  0
                 bindDStoJndi(ctx, path, ds);
 219  
             }
 220  
         }
 221  0
         catch (Exception e)
 222  
         {
 223  0
             log.error("", e);
 224  0
             throw new TorqueException(e);
 225  0
         }
 226  0
     }
 227  
 
 228  
     /**
 229  
      * Does nothing. We do not want to close a dataSource retrieved from Jndi,
 230  
      * because other applications might use it as well.
 231  
      */
 232  
     public void close()
 233  
     {
 234  
         // do nothing
 235  0
     }
 236  
 
 237  
     /**
 238  
      *
 239  
      * @param ctx the context
 240  
      * @throws NamingException
 241  
      */
 242  
     private void debugCtx(Context ctx) throws NamingException
 243  
     {
 244  0
         log.debug("InitialContext -------------------------------");
 245  0
         Map env = ctx.getEnvironment();
 246  0
         Iterator qw = env.keySet().iterator();
 247  0
         log.debug("Environment properties:" + env.size());
 248  0
         while (qw.hasNext())
 249  
         {
 250  0
             Object prop = qw.next();
 251  0
             log.debug("    " + prop + ": " + env.get(prop));
 252  
         }
 253  0
         log.debug("----------------------------------------------");
 254  0
     }
 255  
 
 256  
     /**
 257  
      *
 258  
      * @param ctx
 259  
      * @param path
 260  
      * @param ds
 261  
      * @throws Exception
 262  
      */
 263  
     private void bindDStoJndi(Context ctx, String path, Object ds)
 264  
         throws Exception
 265  
     {
 266  0
         debugCtx(ctx);
 267  
 
 268  
         // add subcontexts, if not added already
 269  0
         int start = path.indexOf(':') + 1;
 270  0
         if (start > 0)
 271  
         {
 272  0
             path = path.substring(start);
 273  
         }
 274  0
         StringTokenizer st = new StringTokenizer(path, "/");
 275  0
         while (st.hasMoreTokens())
 276  
         {
 277  0
             String subctx = st.nextToken();
 278  0
             if (st.hasMoreTokens())
 279  
             {
 280  
                 try
 281  
                 {
 282  0
                     ctx.createSubcontext(subctx);
 283  0
                     log.debug("Added sub context: " + subctx);
 284  
                 }
 285  0
                 catch (NameAlreadyBoundException nabe)
 286  
                 {
 287  
                     // ignore
 288  
                 }
 289  0
                 catch (NamingException ne)
 290  
                 {
 291  
                     // even though there is a specific exception
 292  
                     // for this condition, some implementations
 293  
                     // throw the more general one.
 294  
                     /*
 295  
                      *                      if (ne.getMessage().indexOf("already bound") == -1 )
 296  
                      *                      {
 297  
                      *                      throw ne;
 298  
                      *                      }
 299  
                      */
 300  
                     // ignore
 301  0
                 }
 302  0
                 ctx = (Context) ctx.lookup(subctx);
 303  
             }
 304  
             else
 305  
             {
 306  
                 // not really a subctx, it is the ds name
 307  0
                 ctx.bind(subctx, ds);
 308  
             }
 309  
         }
 310  0
     }
 311  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.