package com.cloudhopper.commons.sql; /* * #%L * ch-commons-sql * %% * Copyright (C) 2012 - 2013 Cloudhopper by Twitter * %% * Licensed 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. * #L% */ import com.cloudhopper.commons.sql.adapter.DataSourceAdapter; import java.lang.management.ManagementFactory; import java.sql.Connection; import java.sql.Driver; import java.sql.SQLException; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Class for creating, managing, and monitoring of the life-cycle of DataSources. * * @author joelauer */ public class DataSourceManager { private static final Logger logger = LoggerFactory.getLogger(DataSourceManager.class); private DataSourceManager() { // do nothing } /** * Verifies a DataSource is functional. This method will call getConnection() * on the DataSource and if that fails a SQLException will be thrown. * @param ds The DataSource to verify * @throws java.sql.SQLException Thrown if the call to getConnection() fails * to obtain a SQL connection. */ public static void verify(DataSource ds) throws SQLException { Connection conn = null; try { // get a connection -- this will test the connection works conn = ds.getConnection(); } finally { JdbcUtil.close(conn); } } /** * Creates a new DataSource from the DataSourceConfiguration. * @param configuration The configuration of the DataSource * @return A new DataSource tied to the configuration * @throws SQLMissingDependencyException Thrown if a dependency (external jar) * is missing from the configuration. * @throws SQLConfigurationException Thrown if there was an error while * configuring the DataSource. */ public static DataSource create(DataSourceConfiguration configuration) throws SQLMissingDependencyException, SQLConfigurationException { // verify all required properties are configured and set configuration.validate(); // clone the configuration so we can save the properties used to create the ds DataSourceConfiguration config = (DataSourceConfiguration)configuration.clone(); // verify database driver exists and try to register the database driver try { // create a new instance Driver driver = (Driver)Class.forName(config.getDriver()).newInstance(); // put out some properties to save 'em? } catch (Exception e) { throw new SQLMissingDependencyException("Database driver '" + config.getDriver() + "' failed to load. Perhaps missing jar file?", e); } // get the class responsible for creating the datasource String adapterClass = config.getProvider().getAdapter(); // create a new instance of the adapter DataSourceAdapter adapter = null; try { adapter = (DataSourceAdapter)Class.forName(adapterClass).newInstance(); } catch (Exception e) { //throw new SQLConfigurationException("Invalid DataSourceAdapter class specified. Should be impossible error?"); throw new SQLMissingDependencyException("DataSourceAdapter '" + adapterClass + "' failed to load. Perhaps missing jar file?", e); } // delegate creating the new datasource to the adapter ManagedDataSource mds = adapter.create(config); // if the user requested this datasource to be added to jmx if (config.getJmx()) { // hmm... if jmx is turned on, let's register the MBean MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); try { ObjectName name = new ObjectName(config.getJmxDomain() + ":type=ManagedDataSource,name=" + config.getName()); mbs.registerMBean(mds, name); } catch (Exception e) { // log the error, but don't throw an exception for this datasource logger.error("Error while attempting to register ManagedDataSourceMBean '" + config.getName() + "'", e); } } // return the datasource return mds.getDataSource(); } }