/* * JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.hibernate.console; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import org.dom4j.DocumentException; import org.dom4j.Node; import org.dom4j.io.DOMWriter; import org.eclipse.datatools.connectivity.IConnectionProfile; import org.eclipse.datatools.connectivity.ProfileManager; import org.eclipse.osgi.util.NLS; import org.hibernate.console.preferences.ConsoleConfigurationPreferences; import org.hibernate.console.preferences.ConsoleConfigurationPreferences.ConfigurationMode; import org.hibernate.util.xpl.DTDEntityResolver; //import org.hibernate.util.ConfigHelper; import org.hibernate.util.xpl.ReflectHelper; import org.hibernate.util.xpl.StringHelper; import org.hibernate.util.xpl.XMLHelper; import org.jboss.tools.hibernate.exception.MappingException; import org.jboss.tools.hibernate.runtime.spi.HibernateException; import org.jboss.tools.hibernate.runtime.spi.IConfiguration; import org.jboss.tools.hibernate.runtime.spi.IEnvironment; import org.jboss.tools.hibernate.runtime.spi.INamingStrategy; import org.jboss.tools.hibernate.runtime.spi.IService; import org.jboss.tools.hibernate.runtime.spi.ServiceLookup; import org.w3c.dom.Document; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXParseException; public class ConfigurationFactory { public static final String FAKE_TM_LOOKUP = "org.hibernate.console.FakeTransactionManagerLookup"; //$NON-NLS-1$ private ConsoleConfigurationPreferences prefs; private Map<String, FakeDelegatingDriver> fakeDrivers; private IService service; private IEnvironment environment; public ConfigurationFactory(ConsoleConfigurationPreferences prefs, Map<String, FakeDelegatingDriver> fakeDrivers) { this.prefs = prefs; this.fakeDrivers = fakeDrivers; service = ServiceLookup.findService(prefs.getHibernateVersion()); environment = service.getEnvironment(); } public ConsoleConfigurationPreferences getPreferences() { return prefs; } public IConfiguration createConfiguration(IConfiguration localCfg, boolean includeMappings) { Properties properties = prefs.getProperties(); if (properties != null) { // in case the transaction manager is empty then we need to inject a faketm since // hibernate will still try and instantiate it. String str = properties.getProperty(environment.getTransactionManagerStrategy()); if (str != null && StringHelper.isEmpty(str)) { properties.setProperty(environment.getTransactionManagerStrategy(), FAKE_TM_LOOKUP); // properties.setProperty( "hibernate.transaction.factory_class", ""); } } if (localCfg == null) { localCfg = buildConfiguration(properties, includeMappings); } else { // Properties origProperties = cfg.getProperties(); // origProperties.putAll(properties); // cfg.setProperties(origProperties); // TODO: this is actually only for jdbc reveng... // localCfg = configureStandardConfiguration( includeMappings, localCfg, properties ); } // here both setProperties and configxml have had their chance to tell which databasedriver // is needed. registerFakeDriver(localCfg.getProperty(environment.getDriver())); // autoConfigureDialect(localCfg); Disabled for now since it causes very looong timeouts for // non-running databases + i havent been needed until now... // TODO: jpa configuration ? if (includeMappings) { File[] mappingFiles = prefs.getMappingFiles(); for (int i = 0; i < mappingFiles.length; i++) { File hbm = mappingFiles[i]; localCfg = localCfg.addFile(hbm); } } // TODO: HBX- localCfg.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false"); //$NON-NLS-1$//$NON-NLS-2$ localCfg.setProperty(environment.getHBM2DDLAuto(), "false"); //$NON-NLS-1$ // to fix: JBIDE-5839 & JBIDE-5997 - setup this property: false is default value // to make hibernate tools diff hibernate versions compatible: // if the property not set get NoSuchMethodError with FullTextIndexEventListener if (localCfg.getProperty("hibernate.search.autoregister_listeners") == null) { //$NON-NLS-1$ localCfg.setProperty("hibernate.search.autoregister_listeners", "true"); //$NON-NLS-1$ //$NON-NLS-2$ } if (localCfg.getProperty("hibernate.validator.apply_to_ddl") == null) { //$NON-NLS-1$ localCfg.setProperty("hibernate.validator.apply_to_ddl", "false"); //$NON-NLS-1$ //$NON-NLS-2$ } return localCfg; } @SuppressWarnings("unused") // autoConfigureDialect(localCfg); Disabled for now since it causes very looong timeouts for // non-running databases + i havent been needed until now... private void autoConfigureDialect(IConfiguration localCfg) { if (localCfg.getProperty(environment.getDialect()) == null) { String dialect = ConnectionProfileUtil.autoDetectDialect(service, localCfg.getProperties()); if (dialect != null){ localCfg.setProperty(environment.getDialect(), dialect); } } } // TODO: delegate to some extension point private IConfiguration buildConfiguration(Properties properties, boolean includeMappings) { IConfiguration localCfg = null; if (prefs.getConfigurationMode().equals(ConfigurationMode.ANNOTATIONS)) { try { localCfg = buildAnnotationConfiguration(); localCfg = configureStandardConfiguration(includeMappings, localCfg, properties); } catch (HibernateConsoleRuntimeException he) { throw he; } catch (Exception e) { throw new HibernateConsoleRuntimeException( ConsoleMessages.ConsoleConfiguration_could_not_load_annotationconfiguration, e); } } else if (prefs.getConfigurationMode().equals(ConfigurationMode.JPA)) { try { localCfg = buildJPAConfiguration(getPreferences().getPersistenceUnitName(), properties, prefs.getEntityResolverName(), includeMappings); } catch (HibernateConsoleRuntimeException he) { throw he; } catch (Exception e) { throw new HibernateConsoleRuntimeException( ConsoleMessages.ConsoleConfiguration_could_not_load_jpa_configuration, e); } } else { localCfg = service.newDefaultConfiguration(); localCfg = configureStandardConfiguration(includeMappings, localCfg, properties); } return localCfg; } private IConfiguration buildAnnotationConfiguration() throws ClassNotFoundException, InstantiationException, IllegalAccessException { return service.newAnnotationConfiguration(); } private IConfiguration buildJPAConfiguration(String persistenceUnit, Properties properties, String entityResolver, boolean includeMappings) { if (StringHelper.isEmpty(persistenceUnit)) { persistenceUnit = null; } try { Map<Object, Object> overrides = new HashMap<Object, Object>(); if (properties != null) { overrides.putAll(properties); } if (StringHelper.isNotEmpty(prefs.getNamingStrategy())) { overrides.put("hibernate.ejb.naming_strategy", prefs.getNamingStrategy()); //$NON-NLS-1$ } if (StringHelper.isNotEmpty(prefs.getDialectName())) { overrides.put(environment.getDialect(), prefs.getDialectName()); } if (!includeMappings) { overrides.put("hibernate.archive.autodetection", "none"); //$NON-NLS-1$//$NON-NLS-2$ } if (StringHelper.isEmpty((String) overrides.get("javax.persistence.validation.mode"))) {//$NON-NLS-1$ overrides.put("javax.persistence.validation.mode", "none"); //$NON-NLS-1$//$NON-NLS-2$ } IConfiguration invoke = service.newJpaConfiguration(entityResolver, persistenceUnit, overrides); changeDatasourceProperties(invoke); invoke = configureConnectionProfile(invoke); return invoke; // Class hibernatePersistanceProviderClass = ReflectHelper.classForName("org.hibernate.jpa.HibernatePersistenceProvider", ConsoleConfiguration.class); // Object hibernatePersistanceProvider = hibernatePersistanceProviderClass.newInstance(); // // Method getEntityManagerFactoryBuilderOrNull = hibernatePersistanceProviderClass.getDeclaredMethod( // "getEntityManagerFactoryBuilderOrNull", // new Class[] { String.class, Map.class }); // getEntityManagerFactoryBuilderOrNull.setAccessible(true); // Object entityManagerFactoryBuilder = // getEntityManagerFactoryBuilderOrNull.invoke( // hibernatePersistanceProvider, // new Object[] { persistenceUnit, overrides}); // // if (entityManagerFactoryBuilder == null) { // throw new HibernateConsoleRuntimeException( // "Persistence unit not found: '" + // persistenceUnit + // "'."); // } // // Method build = // entityManagerFactoryBuilder.getClass().getMethod( // "build", new Class[0]); // build.invoke(entityManagerFactoryBuilder, null); // // Method getHibernateConfiguration = // entityManagerFactoryBuilder.getClass().getMethod( // "getHibernateConfiguration", new Class[0]); // return (Configuration)getHibernateConfiguration.invoke( // entityManagerFactoryBuilder, null); } catch (HibernateConsoleRuntimeException he) { throw he; } catch (Exception e) { throw new HibernateConsoleRuntimeException( ConsoleMessages.ConsoleConfiguration_could_not_create_jpa_based_configuration, e); } } private IConfiguration configureStandardConfiguration(final boolean includeMappings, IConfiguration localCfg, Properties properties) { if (properties != null) { localCfg = localCfg.setProperties(properties); } EntityResolver entityResolver = new DTDEntityResolver(service); if (StringHelper.isNotEmpty(prefs.getEntityResolverName())) { try { entityResolver = (EntityResolver) ReflectHelper.classForName( prefs.getEntityResolverName()).newInstance(); } catch (Exception c) { throw new HibernateConsoleRuntimeException( ConsoleMessages.ConsoleConfiguration_could_not_configure_entity_resolver + prefs.getEntityResolverName(), c); } } localCfg.setEntityResolver(entityResolver); if (StringHelper.isNotEmpty(prefs.getNamingStrategy())) { try { INamingStrategy ns = service.newNamingStrategy( prefs.getNamingStrategy()); localCfg.setNamingStrategy(ns); } catch (Exception c) { throw new HibernateConsoleRuntimeException( ConsoleMessages.ConsoleConfiguration_could_not_configure_naming_strategy + prefs.getNamingStrategy(), c); } } localCfg = loadConfigurationXML(localCfg, includeMappings, entityResolver); changeDatasourceProperties(localCfg); localCfg = configureConnectionProfile(localCfg); // replace dialect if it is set in preferences if (StringHelper.isNotEmpty(prefs.getDialectName())) { localCfg.setProperty(environment.getDialect(), prefs.getDialectName()); } if (StringHelper.isEmpty(localCfg.getProperty("javax.persistence.validation.mode"))) {//$NON-NLS-1$ localCfg.setProperty("javax.persistence.validation.mode", "none"); //$NON-NLS-1$//$NON-NLS-2$ } return localCfg; } @SuppressWarnings("unchecked") private IConfiguration loadConfigurationXML(IConfiguration localCfg, boolean includeMappings, EntityResolver entityResolver) { File configXMLFile = prefs.getConfigXMLFile(); if (!includeMappings) { org.dom4j.Document doc; XMLHelper xmlHelper = new XMLHelper(); InputStream stream = null; String resourceName = "<unknown>"; //$NON-NLS-1$ if (configXMLFile != null) { resourceName = configXMLFile.toString(); try { stream = new FileInputStream(configXMLFile); } catch (FileNotFoundException e1) { throw new HibernateConsoleRuntimeException( ConsoleMessages.ConsoleConfiguration_could_not_access + configXMLFile, e1); } } else { resourceName = "/hibernate.cfg.xml"; //$NON-NLS-1$ if (checkHibernateResoureExistence(resourceName)) { stream = getResourceAsStream(resourceName); // simulate hibernate's // default look up } else { return localCfg; } } try { List<SAXParseException> errors = new ArrayList<SAXParseException>(); doc = xmlHelper.createSAXReader(resourceName, errors, entityResolver).read( new InputSource(stream)); if (errors.size() != 0) { throw new MappingException( ConsoleMessages.ConsoleConfiguration_invalid_configuration, errors .get(0)); } List<Node> list = doc.getRootElement() .element("session-factory").elements("mapping"); //$NON-NLS-1$ //$NON-NLS-2$ for (Node element : list) { element.getParent().remove(element); } DOMWriter dw = new DOMWriter(); Document document = dw.write(doc); return localCfg.configure(document); } catch (DocumentException e) { throw new HibernateException( ConsoleMessages.ConsoleConfiguration_could_not_parse_configuration + resourceName, e); } finally { try { if (stream != null) stream.close(); } catch (IOException ioe) { // log.warn( "could not close input stream for: " + resourceName, ioe ); } } } else { if (configXMLFile != null) { return localCfg.configure(configXMLFile); } else { IConfiguration resultCfg = localCfg; if (checkHibernateResoureExistence("/hibernate.cfg.xml")) { //$NON-NLS-1$ resultCfg = localCfg.configure(); } return resultCfg; } } } private boolean checkHibernateResoureExistence(String resource) { InputStream is = null; try { is = getResourceAsStream(resource); } catch (HibernateException e) { // just ignore } finally { try { if (is != null) is.close(); } catch (IOException e) { // ignore } } return (is != null); } private void changeDatasourceProperties(IConfiguration localCfg){ final Properties invokeProperties = localCfg.getProperties(); // set this property to null! if (invokeProperties.containsKey(environment.getDataSource())){ invokeProperties.setProperty(environment.getTransactionManagerStrategy(), FAKE_TM_LOOKUP); invokeProperties.put(environment.getConnectionProvider(), service.getDriverManagerConnectionProviderClass().getName()); invokeProperties.remove(environment.getDataSource()); localCfg.setProperties(invokeProperties); } } private IConfiguration configureConnectionProfile(IConfiguration localCfg) { String connProfileName = prefs.getConnectionProfileName(); if (connProfileName == null) { return localCfg; } IConnectionProfile profile = ProfileManager.getInstance().getProfileByName( connProfileName); if (profile != null) { localCfg.addProperties(ConnectionProfileUtil.getHibernateConnectionProperties(service, profile)); } else { String out = NLS.bind( ConsoleMessages.ConsoleConfiguration_connection_profile_not_found, connProfileName); throw new HibernateConsoleRuntimeException(out); } return localCfg; } /** * DriverManager checks what classloader a class is loaded from thus we register a FakeDriver * that we know is loaded "properly" which delegates all it class to the real driver. By doing * so we can convince DriverManager that we can use any dynamically loaded driver. * * @param driverClassName */ @SuppressWarnings("unchecked") private void registerFakeDriver(String driverClassName) { if (driverClassName != null) { try { Class<Driver> driverClass = (Class<Driver>)ReflectHelper.classForName(driverClassName); if (!fakeDrivers.containsKey(driverClassName)) { // To avoid "double registration" FakeDelegatingDriver fakeDelegatingDriver = new FakeDelegatingDriver( driverClass.newInstance()); DriverManager.registerDriver(fakeDelegatingDriver); fakeDrivers.put(driverClassName, fakeDelegatingDriver); } } catch (ClassNotFoundException e) { String out = NLS.bind(ConsoleMessages.ConsoleConfiguration_problems_while_loading_database_driverclass, driverClassName); throw new HibernateConsoleRuntimeException(out, e); } catch (InstantiationException e) { String out = NLS.bind(ConsoleMessages.ConsoleConfiguration_problems_while_loading_database_driverclass, driverClassName); throw new HibernateConsoleRuntimeException(out, e); } catch (IllegalAccessException e) { String out = NLS.bind(ConsoleMessages.ConsoleConfiguration_problems_while_loading_database_driverclass, driverClassName); throw new HibernateConsoleRuntimeException(out, e); } catch (SQLException e) { String out = NLS.bind(ConsoleMessages.ConsoleConfiguration_problems_while_loading_database_driverclass, driverClassName); throw new HibernateConsoleRuntimeException(out, e); } } } private InputStream getResourceAsStream(String resource) { String stripped = resource.startsWith("/") ? //$NON-NLS-1$ resource.substring(1) : resource; InputStream stream = null; ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader!=null) { stream = classLoader.getResourceAsStream( stripped ); } if ( stream == null ) { stream = environment.getClass().getResourceAsStream( resource ); } if ( stream == null ) { stream = environment.getClass().getClassLoader().getResourceAsStream( stripped ); } if ( stream == null ) { throw new HibernateException( resource + " not found" ); //$NON-NLS-1$ } return stream; } }