| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. The ASF licenses this file to You |
| * under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. For additional information regarding |
| * copyright in this work, please see the NOTICE file in the top level |
| * directory of this distribution. |
| */ |
| |
| package org.apache.roller.weblogger.business; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.SQLException; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Properties; |
| import javax.naming.InitialContext; |
| import javax.naming.NamingException; |
| import javax.sql.DataSource; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.roller.weblogger.business.startup.StartupException; |
| import org.apache.roller.weblogger.config.WebloggerConfig; |
| |
| |
| /** |
| * Encapsulates Roller database configuration via JDBC properties or JNDI. |
| * |
| * <p>To keep the logs from filling up with DB connection errors, will only |
| * attempt to connect once.</p> |
| * |
| * <p>Keeps startup exception and log so we can present useful debugging |
| * information to whoever is installing Roller.</p> |
| * |
| * |
| * <p>Reads configuration properties from WebloggerConfig:</p> |
| * <pre> |
| * # Specify database configuration type of 'jndi' or 'jdbc' |
| * database.configurationType=jndi |
| * |
| * # For database configuration type 'jndi',this will be used |
| * database.jndi.name=jdbc/rollerdb |
| * |
| * # For database configuration type of 'jdbc', you MUST override these |
| * database.jdbc.driverClass= |
| * database.jdbc.connectionURL= |
| * database.jdbc.username= |
| * database.jdbc.password= |
| * </pre> |
| */ |
| public class DatabaseProvider { |
| |
| private static Log log = LogFactory.getLog(DatabaseProvider.class); |
| |
| public enum ConfigurationType {JNDI_NAME, JDBC_PROPERTIES} |
| private ConfigurationType type = ConfigurationType.JNDI_NAME; |
| private List<String> startupLog = new ArrayList<String>(); |
| |
| private DataSource dataSource = null; |
| private String jndiName = null; |
| |
| private String jdbcDriverClass = null; |
| private String jdbcConnectionURL = null; |
| private String jdbcPassword = null; |
| private String jdbcUsername = null; |
| private Properties props = null; |
| |
| |
| /** |
| * Reads configuraiton, loads driver or locates data-source and attempts |
| * to get test connecton so that we can fail early. |
| */ |
| public DatabaseProvider() throws StartupException { |
| |
| String connectionTypeString = |
| WebloggerConfig.getProperty("database.configurationType"); |
| if ("jdbc".equals(connectionTypeString)) { |
| type = ConfigurationType.JDBC_PROPERTIES; |
| } |
| jndiName = WebloggerConfig.getProperty("database.jndi.name"); |
| jdbcDriverClass = WebloggerConfig.getProperty("database.jdbc.driverClass"); |
| jdbcConnectionURL = WebloggerConfig.getProperty("database.jdbc.connectionURL"); |
| jdbcUsername = WebloggerConfig.getProperty("database.jdbc.username"); |
| jdbcPassword = WebloggerConfig.getProperty("database.jdbc.password"); |
| |
| successMessage("SUCCESS: Got parameters. Using configuration type " + type); |
| |
| // If we're doing JDBC then attempt to load JDBC driver class |
| if (getType() == ConfigurationType.JDBC_PROPERTIES) { |
| successMessage("-- Using JDBC driver class: " + jdbcDriverClass); |
| successMessage("-- Using JDBC connection URL: " + jdbcConnectionURL); |
| successMessage("-- Using JDBC username: " + jdbcUsername); |
| successMessage("-- Using JDBC password: [hidden]"); |
| try { |
| Class.forName(getJdbcDriverClass()); |
| } catch (ClassNotFoundException ex) { |
| String errorMsg = |
| "ERROR: cannot load JDBC driver class [" + getJdbcDriverClass()+ "]. " |
| +"Likely problem: JDBC driver jar missing from server classpath."; |
| errorMessage(errorMsg); |
| throw new StartupException(errorMsg, ex, startupLog); |
| } |
| successMessage("SUCCESS: loaded JDBC driver class [" +getJdbcDriverClass()+ "]"); |
| |
| if (getJdbcUsername() != null || getJdbcPassword() != null) { |
| props = new Properties(); |
| if (getJdbcUsername() != null) { |
| props.put("user", getJdbcUsername()); |
| } |
| if (getJdbcPassword() != null) { |
| props.put("password", getJdbcPassword()); |
| } |
| } |
| |
| // Else attempt to locate JNDI datasource |
| } else { |
| String name = getFullJndiName(); |
| successMessage("-- Using JNDI datasource name: " + name); |
| try { |
| InitialContext ic = new InitialContext(); |
| dataSource = (DataSource)ic.lookup(name); |
| } catch (NamingException ex) { |
| String errorMsg = |
| "ERROR: cannot locate JNDI DataSource [" +name+ "]. " |
| +"Likely problem: no DataSource or datasource is misconfigured."; |
| errorMessage(errorMsg); |
| throw new StartupException(errorMsg, ex, startupLog); |
| } |
| successMessage("SUCCESS: located JNDI DataSource [" +name+ "]"); |
| } |
| |
| // So far so good. Now, can we get a connection? |
| try { |
| Connection testcon = getConnection(); |
| testcon.close(); |
| } catch (Exception e) { |
| String errorMsg = |
| "ERROR: unable to obtain database connection. " |
| +"Likely problem: bad connection parameters or database unavailable."; |
| errorMessage(errorMsg); |
| throw new StartupException(errorMsg, e, startupLog); |
| } |
| } |
| |
| |
| private void successMessage(String msg) { |
| startupLog.add(msg); |
| log.info(msg); |
| } |
| |
| private void errorMessage(String msg) { |
| startupLog.add(msg); |
| log.error(msg); |
| } |
| |
| |
| /** |
| * List of success and error messages when class was first instantiated. |
| **/ |
| public List<String> getStartupLog() { |
| return startupLog; |
| } |
| |
| /** |
| * Get database connection from data-source or driver manager, depending |
| * on which is configured. |
| */ |
| public Connection getConnection() throws SQLException { |
| if (getType() == ConfigurationType.JDBC_PROPERTIES) { |
| return DriverManager.getConnection(getJdbcConnectionURL(), props); |
| } else { |
| return dataSource.getConnection(); |
| } |
| } |
| |
| public ConfigurationType getType() { |
| return type; |
| } |
| |
| public String getJndiName() { |
| return jndiName; |
| } |
| |
| public String getJdbcDriverClass() { |
| return jdbcDriverClass; |
| } |
| |
| public String getJdbcConnectionURL() { |
| return jdbcConnectionURL; |
| } |
| |
| public String getJdbcPassword() { |
| return jdbcPassword; |
| } |
| |
| public String getJdbcUsername() { |
| return jdbcUsername; |
| } |
| |
| public String getFullJndiName() { |
| if (null != jndiName && jndiName.startsWith("java:")) { |
| return jndiName; |
| } |
| return "java:comp/env/" + jndiName; |
| } |
| |
| } |