File Source: DatabaseProvider.java

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   *  contributor license agreements.  The ASF licenses this file to You
     4   * under the Apache License, Version 2.0 (the "License"); you may not
     5   * use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.  For additional information regarding
    15   * copyright in this work, please see the NOTICE file in the top level
    16   * directory of this distribution.
    17   */
    18  
    19  package org.apache.roller.weblogger.business;
    20  
    21  import java.sql.Connection;
    22  import java.sql.DriverManager;
    23  import java.sql.SQLException;
    24  import java.util.ArrayList;
    25  import java.util.List;
    26  import java.util.Properties;
    27  import javax.naming.InitialContext;
    28  import javax.naming.NamingException;
    29  import javax.sql.DataSource;
    30  import org.apache.commons.logging.Log;
    31  import org.apache.commons.logging.LogFactory;
    32  import org.apache.roller.weblogger.WebloggerException;
    33  import org.apache.roller.weblogger.business.startup.StartupException;
    34  import org.apache.roller.weblogger.config.WebloggerConfig;
    35  
    36  
    37  /**
    38   * Encapsulates Roller database configuration via JDBC properties or JNDI.
    39   * 
    40   * <p>To keep the logs from filling up with DB connection errors, will only 
    41   * attempt to connect once.</p>
    42   * 
    43   * <p>Keeps startup exception and log so we can present useful debugging
    44   * information to whoever is installing Roller.</p>
    45   * 
    46   * 
    47   * <p>Reads configuration properties from WebloggerConfig:</p>
    48   * <pre>
    49   * # Specify database configuration type of 'jndi' or 'jdbc'
    50   * database.configurationType=jndi
    51   * 
    52   * # For database configuration type 'jndi',this will be used
    53   * database.jndi.name=jdbc/rollerdb
    54   * 
    55   * # For database configuration type of 'jdbc', you MUST override these
    56   * database.jdbc.driverClass=
    57   * database.jdbc.connectionURL=
    58   * database.jdbc.username=
    59   * database.jdbc.password=
    60   * </pre>
    61   */
    62  public class DatabaseProvider  {
    63      
             /* 
    P/P       *  Method: org.apache.roller.weblogger.business.DatabaseProvider__static_init
              * 
              *  Postconditions:
              *    init'ed(log)
              */
    64      private static Log log = LogFactory.getLog(DatabaseProvider.class);
    65  
             /* 
    P/P       *  Method: org.apache.roller.weblogger.business.DatabaseProvider$ConfigurationType__static_init
              * 
              *  Postconditions:
              *    $VALUES == &new DatabaseProvider$ConfigurationType[](DatabaseProvider$ConfigurationType__static_init#3)
              *    JDBC_PROPERTIES == &new DatabaseProvider$ConfigurationType(DatabaseProvider$ConfigurationType__static_init#2)
              *    $VALUES[1] == &new DatabaseProvider$ConfigurationType(DatabaseProvider$ConfigurationType__static_init#2)
              *    JNDI_NAME == &new DatabaseProvider$ConfigurationType(DatabaseProvider$ConfigurationType__static_init#1)
              *    $VALUES[0] == &new DatabaseProvider$ConfigurationType(DatabaseProvider$ConfigurationType__static_init#1)
              *    new DatabaseProvider$ConfigurationType(DatabaseProvider$ConfigurationType__static_init#1) num objects == 1
              *    new DatabaseProvider$ConfigurationType(DatabaseProvider$ConfigurationType__static_init#2) num objects == 1
              *    new DatabaseProvider$ConfigurationType[](DatabaseProvider$ConfigurationType__static_init#3) num objects == 1
              *    $VALUES.length == 2
              */
    66      public enum ConfigurationType {JNDI_NAME, JDBC_PROPERTIES;}
    67      private ConfigurationType type = ConfigurationType.JNDI_NAME;
    68      private List<String> startupLog = new ArrayList<String>();
    69      
    70      private DataSource dataSource = null;    
    71      private String jndiName = null; 
    72      
    73      private String jdbcDriverClass = null;
    74      private String jdbcConnectionURL = null;
    75      private String jdbcPassword = null;
    76      private String jdbcUsername = null;
    77      private Properties props = null;
    78      
    79      
    80      /**
    81       * Reads configuraiton, loads driver or locates data-source and attempts
    82       * to get test connecton so that we can fail early.
    83       */ 
             /* 
    P/P       *  Method: void org.apache.roller.weblogger.business.DatabaseProvider()
              * 
              *  Preconditions:
              *    log != null
              *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
              *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
              * 
              *  Presumptions:
              *    javax.naming.InitialContext:lookup(...)@128 != null
              *    this.dataSource != null
              *    this.props != null
              * 
              *  Postconditions:
              *    (soft) this.dataSource != null
              *    init'ed(this.jdbcConnectionURL)
              *    init'ed(this.jdbcDriverClass)
              *    init'ed(this.jdbcPassword)
              *    init'ed(this.jdbcUsername)
              *    init'ed(this.jndiName)
              *    (soft) this.props != null
              *    this.startupLog == &new ArrayList(DatabaseProvider#1)
              *    this.type in Addr_Set{&org.apache.roller.weblogger.business.DatabaseProvider$ConfigurationType__static_init.new DatabaseProvider$ConfigurationType(DatabaseProvider$ConfigurationType__static_init#1),&org.apache.roller.weblogger.business.DatabaseProvider$ConfigurationType__static_init.new DatabaseProvider$ConfigurationType(DatabaseProvider$ConfigurationType__static_init#2)}
              *    new ArrayList(DatabaseProvider#1) num objects == 1
              *    ...
              * 
              *  Test Vectors:
              *    java.lang.String:equals(...)@88: {0}, {1}
              */
    84      public DatabaseProvider() throws StartupException {
    85          
    86          String connectionTypeString = 
    87                  WebloggerConfig.getProperty("database.configurationType"); 
    88          if ("jdbc".equals(connectionTypeString)) {
    89              type = ConfigurationType.JDBC_PROPERTIES;
    90          }
    91          jndiName =          WebloggerConfig.getProperty("database.jndi.name");
    92          jdbcDriverClass =   WebloggerConfig.getProperty("database.jdbc.driverClass");
    93          jdbcConnectionURL = WebloggerConfig.getProperty("database.jdbc.connectionURL");
    94          jdbcUsername =      WebloggerConfig.getProperty("database.jdbc.username");
    95          jdbcPassword =      WebloggerConfig.getProperty("database.jdbc.password");
    96          
    97          successMessage("SUCCESS: Got parameters. Using configuration type " + type);
    98  
    99          // If we're doing JDBC then attempt to load JDBC driver class
   100          if (getType() == ConfigurationType.JDBC_PROPERTIES) {
   101              successMessage("-- Using JDBC driver class: "   + jdbcDriverClass);
   102              successMessage("-- Using JDBC connection URL: " + jdbcConnectionURL);
   103              successMessage("-- Using JDBC username: "       + jdbcUsername);
   104              successMessage("-- Using JDBC password: [hidden]");
   105              try {
   106                  Class.forName(getJdbcDriverClass());
   107              } catch (ClassNotFoundException ex) {
   108                  String errorMsg = 
   109                       "ERROR: cannot load JDBC driver class [" + getJdbcDriverClass()+ "]. "
   110                      +"Likely problem: JDBC driver jar missing from server classpath.";
   111                  errorMessage(errorMsg);
   112                  throw new StartupException(errorMsg, ex, startupLog);
   113              }
   114              successMessage("SUCCESS: loaded JDBC driver class [" +getJdbcDriverClass()+ "]");
   115              
   116              if (getJdbcUsername() != null || getJdbcPassword() != null) {
   117                  props = new Properties();
   118                  if (getJdbcUsername() != null) props.put("user", getJdbcUsername());
   119                  if (getJdbcPassword() != null) props.put("password", getJdbcPassword());
   120              }
   121              
   122          // Else attempt to locate JNDI datasource
   123          } else { 
   124              String name = "java:comp/env/" + getJndiName();
   125              successMessage("-- Using JNDI datasource name: " + name);
   126              try {
   127                  InitialContext ic = new InitialContext();
   128                  dataSource = (DataSource)ic.lookup(name);
   129              } catch (NamingException ex) {
   130                  String errorMsg = 
   131                      "ERROR: cannot locate JNDI DataSource [" +name+ "]. "
   132                     +"Likely problem: no DataSource or datasource is misconfigured.";
   133                  errorMessage(errorMsg);
   134                  throw new StartupException(errorMsg, ex, startupLog);
   135              }            
   136              successMessage("SUCCESS: located JNDI DataSource [" +name+ "]");
   137          }
   138          
   139          // So far so good. Now, can we get a connection?
   140          try { 
   141              Connection testcon = getConnection();
+  142              testcon.close();
   143          } catch (Throwable t) {
   144              String errorMsg = 
   145                  "ERROR: unable to obtain database connection. "
   146                 +"Likely problem: bad connection parameters or database unavailable.";
   147              errorMessage(errorMsg);
   148              throw new StartupException(errorMsg, t, startupLog);
   149          }
   150      }
   151      
   152      
   153      private void successMessage(String msg) {
                 /* 
    P/P           *  Method: void successMessage(String)
                  * 
                  *  Preconditions:
                  *    log != null
                  *    this.startupLog != null
                  */
   154          startupLog.add(msg);
   155          log.info(msg);
   156      }
   157      
   158      private void errorMessage(String msg) {
                 /* 
    P/P           *  Method: void errorMessage(String)
                  * 
                  *  Preconditions:
                  *    log != null
                  *    this.startupLog != null
                  */
   159          startupLog.add(msg);
   160          log.error(msg);
   161      }
   162      
   163  
   164      /** 
   165       * List of success and error messages when class was first instantiated.
   166       **/
   167      public List<String> getStartupLog() {
                 /* 
    P/P           *  Method: List getStartupLog()
                  * 
                  *  Preconditions:
                  *    init'ed(this.startupLog)
                  * 
                  *  Postconditions:
                  *    return_value == this.startupLog
                  *    init'ed(return_value)
                  */
   168          return startupLog;
   169      }
   170  
   171      /**
   172       * Get database connection from data-source or driver manager, depending 
   173       * on which is configured.
   174       */
   175      public Connection getConnection() throws SQLException {
                 /* 
    P/P           *  Method: Connection getConnection()
                  * 
                  *  Preconditions:
                  *    init'ed(this.type)
                  *    (soft) this.dataSource != null
                  *    (soft) init'ed(this.jdbcConnectionURL)
                  *    (soft) this.props != null
                  *    (soft) this.props._tainted == 0
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   176          if (getType() == ConfigurationType.JDBC_PROPERTIES) {
   177              return DriverManager.getConnection(getJdbcConnectionURL(), props);
   178          } else {
   179              return dataSource.getConnection();
   180          }
   181      } 
   182  
   183      public ConfigurationType getType() {
                 /* 
    P/P           *  Method: DatabaseProvider$ConfigurationType getType()
                  * 
                  *  Preconditions:
                  *    init'ed(this.type)
                  * 
                  *  Postconditions:
                  *    return_value == this.type
                  *    init'ed(return_value)
                  */
   184          return type;
   185      }
   186  
   187      public String getJndiName() {
                 /* 
    P/P           *  Method: String getJndiName()
                  * 
                  *  Preconditions:
                  *    init'ed(this.jndiName)
                  * 
                  *  Postconditions:
                  *    return_value == this.jndiName
                  *    init'ed(return_value)
                  */
   188          return jndiName;
   189      }
   190  
   191      public String getJdbcDriverClass() {
                 /* 
    P/P           *  Method: String getJdbcDriverClass()
                  * 
                  *  Preconditions:
                  *    init'ed(this.jdbcDriverClass)
                  * 
                  *  Postconditions:
                  *    return_value == this.jdbcDriverClass
                  *    init'ed(return_value)
                  */
   192          return jdbcDriverClass;
   193      }
   194  
   195      public String getJdbcConnectionURL() {
                 /* 
    P/P           *  Method: String getJdbcConnectionURL()
                  * 
                  *  Preconditions:
                  *    init'ed(this.jdbcConnectionURL)
                  * 
                  *  Postconditions:
                  *    return_value == this.jdbcConnectionURL
                  *    init'ed(return_value)
                  */
   196          return jdbcConnectionURL;
   197      }
   198  
   199      public String getJdbcPassword() {
                 /* 
    P/P           *  Method: String getJdbcPassword()
                  * 
                  *  Preconditions:
                  *    init'ed(this.jdbcPassword)
                  * 
                  *  Postconditions:
                  *    return_value == this.jdbcPassword
                  *    init'ed(return_value)
                  */
   200          return jdbcPassword;
   201      }
   202  
   203      public String getJdbcUsername() {
                 /* 
    P/P           *  Method: String getJdbcUsername()
                  * 
                  *  Preconditions:
                  *    init'ed(this.jdbcUsername)
                  * 
                  *  Postconditions:
                  *    return_value == this.jdbcUsername
                  *    init'ed(return_value)
                  */
   204          return jdbcUsername;
   205      }
   206  
   207  }








SofCheck Inspector Build Version : 2.18479
DatabaseProvider.java 2009-Jan-02 14:24:54
DatabaseProvider.class 2009-Sep-04 03:12:30
DatabaseProvider$ConfigurationType.class 2009-Sep-04 03:12:30