View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  package org.apache.log4j.db;
    18
    19  import java.sql.Connection;
    20  import java.sql.SQLException;
    21
    22  import javax.naming.Context;
    23  import javax.naming.InitialContext;
    24  import javax.naming.NamingException;
    25
    26  // PortableRemoteObject was introduced in JDK 1.3. We won't use it.
    27  // import javax.rmi.PortableRemoteObject;
    28  import javax.sql.DataSource;
    29
    30
    31  /**
    32   *  The {@code JNDIConnectionSource} is an implementation of
    33   *  {@link ConnectionSource} that obtains a {@link javax.sql.DataSource} from a
    34   *  JNDI provider and uses it to obtain a {@link java.sql.Connection}.  It is
    35   *  primarily designed to be used inside of J2EE application servers or
    36   *  application server clients, assuming the application server supports remote
    37   *  access of {@link javax.sql.DataSource}s.  In this way one can take
    38   *  advantage of  connection pooling and whatever other goodies the application
    39   *  server provides.
    40   *  <p>
    41   *  Sample configuration:<br>
    42   *  <pre>
    43   *    &lt;connectionSource class="org.apache.log4j.jdbc.JNDIConnectionSource"&gt;
    44   *        &lt;param name="jndiLocation" value="jdbc/MySQLDS" /&gt;
    45   *    &lt;/connectionSource&gt;
    46   *  </pre>
    47   *  <p>
    48   *  Sample configuration (with username and password):<br>
    49   *  <pre>
    50   *    &lt;connectionSource class="org.apache.log4j.jdbc.JNDIConnectionSource"&gt;
    51   *        &lt;param name="jndiLocation" value="jdbc/MySQLDS" /&gt;
    52   *        &lt;param name="username" value="myUser" /&gt;
    53   *        &lt;param name="password" value="myPassword" /&gt;
    54   *    &lt;/connectionSource&gt;
    55   *  </pre>
    56   *  <p>
    57   *  Note that this class will obtain an {@link javax.naming.InitialContext}
    58   *  using the no-argument constructor.  This will usually work when executing
    59   *  within a J2EE environment.  When outside the J2EE environment, make sure
    60   *  that you provide a jndi.properties file as described by your JNDI
    61   *  provider's documentation.
    62   *
    63   *  @author <a href="mailto:rdecampo@twcny.rr.com">Ray DeCampo</a>
    64   */
    65  public class JNDIConnectionSource
    66         extends ConnectionSourceSkeleton {
    67    private String jndiLocation = null;
    68    private DataSource dataSource = null;
    69
    70    /**
    71     * @see org.apache.log4j.spi.OptionHandler#activateOptions()
    72     */
    73    public void activateOptions() {
    74      if (jndiLocation == null) {
    75        getLogger().error("No JNDI location specified for JNDIConnectionSource.");
    76      }
    77
    78      discoverConnnectionProperties();
    79
    80    }
    81
    82    /**
    83     * @see org.apache.log4j.db.ConnectionSource#getConnection()
    84     */
    85    public Connection getConnection()
    86           throws SQLException {
    87      Connection conn = null;
    88      try {
    89
    90        if(dataSource == null) {
    91          dataSource = lookupDataSource();
    92        }
    93        if (getUser() == null) {
    94          conn = dataSource.getConnection();
    95        } else {
    96          conn = dataSource.getConnection(getUser(), getPassword());
    97        }
    98      } catch (final NamingException ne) {
    99           getLogger().error("Error while getting data source", ne);
    100       throw new SQLException("NamingException while looking up DataSource: " + ne.getMessage());
    101     } catch (final ClassCastException cce) {
    102       getLogger().error("ClassCastException while looking up DataSource.", cce);
    103       throw new SQLException("ClassCastException while looking up DataSource: " + cce.getMessage());
    104     }
    105
    106     return conn;
    107   }
    108
    109   /**
    110    * Returns the jndiLocation.
    111    * @return String
    112    */
    113   public String getJndiLocation() {
    114     return jndiLocation;
    115   }
    116
    117
    118   /**
    119    * Sets the jndiLocation.
    120    * @param jndiLocation The jndiLocation to set
    121    */
    122   public void setJndiLocation(String jndiLocation) {
    123     this.jndiLocation = jndiLocation;
    124   }
    125
    126
    127   private DataSource lookupDataSource()
    128          throws NamingException, SQLException {
    129     DataSource ds;
    130     Context ctx = new InitialContext();
    131     Object obj = ctx.lookup(jndiLocation);
    132
    133     // PortableRemoteObject was introduced in JDK 1.3. We won't use it.
    134     //ds = (DataSource)PortableRemoteObject.narrow(obj, DataSource.class);
    135     ds = (DataSource) obj;
    136
    137     if (ds == null) {
    138       throw new SQLException("Failed to obtain data source from JNDI location " + jndiLocation);
    139     } else {
    140       return ds;
    141     }
    142   }
    143 }