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