/* * Hibernate, Relational Persistence for Idiomatic Java * * Copyright (c) 2010, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package org.hibernate.connection; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.hibernate.HibernateException; import org.hibernate.cfg.Environment; import org.hibernate.util.ReflectHelper; /** * Instantiates a connection provider given either <tt>System</tt> properties or * a <tt>java.util.Properties</tt> instance. The <tt>ConnectionProviderFactory</tt> * first attempts to find a name of a <tt>ConnectionProvider</tt> subclass in the * property <tt>hibernate.connection.provider_class</tt>. If missing, heuristics are used * to choose either <tt>DriverManagerConnectionProvider</tt>, * <tt>DatasourceConnectionProvider</tt>, <tt>C3P0ConnectionProvider</tt> or * <tt>DBCPConnectionProvider</tt>. * * @author Gavin King * @see ConnectionProvider */ public final class ConnectionProviderFactory { private static final Logger log = LoggerFactory.getLogger( ConnectionProviderFactory.class ); /** * Instantiate a <tt>ConnectionProvider</tt> using <tt>System</tt> properties. * * @return The created connection provider. * * @throws HibernateException */ public static ConnectionProvider newConnectionProvider() throws HibernateException { return newConnectionProvider( Environment.getProperties() ); } /** * Instantiate a <tt>ConnectionProvider</tt> using given properties. * Method newConnectionProvider. * * @param properties hibernate <tt>SessionFactory</tt> properties * * @return ConnectionProvider * * @throws HibernateException */ public static ConnectionProvider newConnectionProvider(Properties properties) throws HibernateException { return newConnectionProvider( properties, null ); } /** * Create a connection provider based on the given information. * * @param properties Properties being used to build the {@link org.hibernate.SessionFactory}. * @param connectionProviderInjectionData Something to be injected in the connection provided * * @return The created connection provider * * @throws HibernateException */ public static ConnectionProvider newConnectionProvider(Properties properties, Map connectionProviderInjectionData) throws HibernateException { ConnectionProvider connections; String providerClass = properties.getProperty( Environment.CONNECTION_PROVIDER ); if ( providerClass != null ) { connections = initializeConnectionProviderFromConfig( providerClass ); } else if ( c3p0ConfigDefined( properties ) && c3p0ProviderPresent() ) { connections = initializeConnectionProviderFromConfig("org.hibernate.connection.C3P0ConnectionProvider"); } else if ( properties.getProperty( Environment.DATASOURCE ) != null ) { connections = new DatasourceConnectionProvider(); } else if ( properties.getProperty( Environment.URL ) != null ) { connections = new DriverManagerConnectionProvider(); } else { connections = new UserSuppliedConnectionProvider(); } if ( connectionProviderInjectionData != null && connectionProviderInjectionData.size() != 0 ) { //inject the data try { BeanInfo info = Introspector.getBeanInfo( connections.getClass() ); PropertyDescriptor[] descritors = info.getPropertyDescriptors(); int size = descritors.length; for ( int index = 0; index < size; index++ ) { String propertyName = descritors[index].getName(); if ( connectionProviderInjectionData.containsKey( propertyName ) ) { Method method = descritors[index].getWriteMethod(); method.invoke( connections, new Object[] { connectionProviderInjectionData.get( propertyName ) } ); } } } catch ( IntrospectionException e ) { throw new HibernateException( "Unable to inject objects into the connection provider", e ); } catch ( IllegalAccessException e ) { throw new HibernateException( "Unable to inject objects into the connection provider", e ); } catch ( InvocationTargetException e ) { throw new HibernateException( "Unable to inject objects into the connection provider", e ); } } connections.configure( properties ); return connections; } private static boolean c3p0ProviderPresent() { try { ReflectHelper.classForName( "org.hibernate.connection.C3P0ConnectionProvider" ); } catch ( ClassNotFoundException e ) { log.warn( "c3p0 properties is specificed, but could not find org.hibernate.connection.C3P0ConnectionProvider from the classpath, " + "these properties are going to be ignored." ); return false; } return true; } private static boolean c3p0ConfigDefined(Properties properties) { Iterator iter = properties.keySet().iterator(); while ( iter.hasNext() ) { String property = (String) iter.next(); if ( property.startsWith( "hibernate.c3p0" ) ) { return true; } } return false; } private static ConnectionProvider initializeConnectionProviderFromConfig(String providerClass) { ConnectionProvider connections; try { log.info( "Initializing connection provider: " + providerClass ); connections = (ConnectionProvider) ReflectHelper.classForName( providerClass ).newInstance(); } catch ( Exception e ) { log.error( "Could not instantiate connection provider", e ); throw new HibernateException( "Could not instantiate connection provider: " + providerClass ); } return connections; } // cannot be instantiated private ConnectionProviderFactory() { throw new UnsupportedOperationException(); } /** * Transform JDBC connection properties. * * Passed in the form <tt>hibernate.connection.*</tt> to the * format accepted by <tt>DriverManager</tt> by trimming the leading "<tt>hibernate.connection</tt>". */ public static Properties getConnectionProperties(Properties properties) { Iterator iter = properties.keySet().iterator(); Properties result = new Properties(); while ( iter.hasNext() ) { String prop = (String) iter.next(); if ( prop.startsWith( Environment.CONNECTION_PREFIX ) && !SPECIAL_PROPERTIES.contains( prop ) ) { result.setProperty( prop.substring( Environment.CONNECTION_PREFIX.length() + 1 ), properties.getProperty( prop ) ); } } String userName = properties.getProperty( Environment.USER ); if ( userName != null ) { result.setProperty( "user", userName ); } return result; } private static final Set SPECIAL_PROPERTIES; static { SPECIAL_PROPERTIES = new HashSet(); SPECIAL_PROPERTIES.add( Environment.DATASOURCE ); SPECIAL_PROPERTIES.add( Environment.URL ); SPECIAL_PROPERTIES.add( Environment.CONNECTION_PROVIDER ); SPECIAL_PROPERTIES.add( Environment.POOL_SIZE ); SPECIAL_PROPERTIES.add( Environment.ISOLATION ); SPECIAL_PROPERTIES.add( Environment.DRIVER ); SPECIAL_PROPERTIES.add( Environment.USER ); } }