This is an automated email from the git hooks/post-receive script. New commit to branch feature/2892 in repository topia. See http://git.nuiton.org/topia.git commit c2fa911d1d99a5e4a82ff39476984f2ba8f784ba Author: Brendan Le Ny <bleny@codelutin.com> Date: Fri Nov 28 12:56:34 2014 +0100 Introduce TopiaConfiguration with two implementation (bean and properties backed), introduce HibernateTopiaMigrationService, remove obsolete method on TopiaService, rewrite HibernateProvider#newConfiguration to remove all unused tricks, change some signatures to use Set instead of arrays --- .../HibernateTopiaMigrationService.java | 34 +++ .../persistence/PropertiesTopiaConfiguration.java | 151 +++++++++++ .../topia/persistence/TopiaApplicationContext.java | 5 +- .../topia/persistence/TopiaConfiguration.java | 38 +++ .../persistence/TopiaConfigurationBuilder.java | 294 +++++++++++++++++++++ .../persistence/TopiaConfigurationConstants.java | 16 +- .../TopiaMisconfigurationException.java | 20 ++ .../org/nuiton/topia/persistence/TopiaService.java | 7 - .../internal/AbstractTopiaApplicationContext.java | 126 ++++----- .../persistence/internal/HibernateProvider.java | 192 +++++--------- .../internal/support/TopiaServiceSupportImpl.java | 99 +++---- .../internal/support/MyFirstTopiaServiceImpl.java | 5 - .../internal/support/MySecondTopiaServiceImpl.java | 5 - .../support/TopiaServiceSupportImplTest.java | 91 ------- .../topia/flyway/TopiaFlywayServiceImpl.java | 17 +- .../topia/liquibase/TopiaLiquibaseServiceImpl.java | 15 +- .../topia/migration/TopiaMigrationEngine.java | 27 +- .../replication/TopiaReplicationServiceImpl.java | 6 - .../templates/ApplicationContextTransformer.java | 4 +- .../topia/templates/EntityEnumTransformer.java | 32 +-- 20 files changed, 741 insertions(+), 443 deletions(-) diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/HibernateTopiaMigrationService.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/HibernateTopiaMigrationService.java new file mode 100644 index 0000000..aed8930 --- /dev/null +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/HibernateTopiaMigrationService.java @@ -0,0 +1,34 @@ +package org.nuiton.topia.persistence; + + +import java.util.Map; + +public class HibernateTopiaMigrationService implements TopiaMigrationService { + + protected TopiaApplicationContext topiaApplicationContext; + + @Override + public void initTopiaService(TopiaApplicationContext topiaApplicationContext, Map<String, String> serviceConfiguration) { + this.topiaApplicationContext = topiaApplicationContext; + } + + @Override + public String getSchemaVersion() { + throw new UnsupportedOperationException(); + } + + @Override + public void initOnCreateSchema() { + // do nothing + } + + @Override + public void runSchemaMigration() { + topiaApplicationContext.updateSchema(); + } + + @Override + public void close() { + + } +} diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/PropertiesTopiaConfiguration.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/PropertiesTopiaConfiguration.java new file mode 100644 index 0000000..3e3fb08 --- /dev/null +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/PropertiesTopiaConfiguration.java @@ -0,0 +1,151 @@ +package org.nuiton.topia.persistence; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import org.apache.commons.lang3.StringUtils; +import org.hibernate.cfg.AvailableSettings; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Properties; + +public class PropertiesTopiaConfiguration implements TopiaConfiguration { + + protected static final String TOPIA_SERVICE_CONFIGURATION_PREFIX = "topia.service."; + + protected ImmutableMap<String, String> configuration; + + protected Map<String, Class<? extends TopiaService>> declaredServices; + + protected Map<String, Map<String, String>> declaredServicesConfiguration; + + public PropertiesTopiaConfiguration(Map<String, String> configuration) { + Preconditions.checkNotNull(configuration); + this.configuration = ImmutableMap.copyOf(configuration); + } + + public PropertiesTopiaConfiguration(Properties properties) { + this((Map) ImmutableMap.copyOf(properties)); + } + + @Override + public boolean isInitSchema() { + String initSchemaConfigValue = configuration.get(TopiaConfigurationConstants.CONFIG_PERSISTENCE_INIT_SCHEMA); + boolean initSchema = StringUtils.isBlank(initSchemaConfigValue) || Boolean.parseBoolean(initSchemaConfigValue); + return initSchema; + } + + @Override + public String getTopiaIdFactoryClassName() { + return configuration.get(TopiaConfigurationConstants.CONFIG_PERSISTENCE_TOPIA_ID_FACTORY_CLASS_NAME); + } + + @Override + public String getSchemaName() { + return configuration.get(TopiaConfigurationConstants.CONFIG_DEFAULT_SCHEMA); + } + + @Override + public String getJdbcDriverClassName() { + return configuration.get(TopiaConfigurationConstants.CONFIG_DRIVER); + } + + @Override + public String getJdbcConnectionUrl() { + return configuration.get(TopiaConfigurationConstants.CONFIG_URL); + } + + @Override + public String getJdbcConnectionUser() { + return configuration.get(TopiaConfigurationConstants.CONFIG_USER); + } + + @Override + public String getJdbcConnectionPassword() { + return configuration.get(TopiaConfigurationConstants.CONFIG_PASS); + } + + @Override + public Integer getConnectionPoolMinSize() { + return Integer.valueOf(configuration.get(AvailableSettings.C3P0_MIN_SIZE)); + } + + @Override + public Integer getConnectionPoolMaxSize() { + return Integer.valueOf(configuration.get(AvailableSettings.C3P0_MAX_SIZE)); + } + + @Override + public ImmutableMap<String, String> getHibernateExtraConfiguration() { + Map<String, String> extraHibernateConfiguration = new LinkedHashMap<String, String>(); + for (Map.Entry<String, String> entry : configuration.entrySet()) { + String key = entry.getKey(); + boolean keyMustBeIncludedInHibernateExtraConfiguration = + ! TopiaConfigurationConstants.MAIN_CONFIGURATION.contains(key) + && key.startsWith("hibernate."); + if (keyMustBeIncludedInHibernateExtraConfiguration) { + extraHibernateConfiguration.put(key, entry.getValue()); + } + } + return ImmutableMap.copyOf(extraHibernateConfiguration); + } + + protected void readServices() { + declaredServices = new LinkedHashMap<String, Class<? extends TopiaService>>(); + declaredServicesConfiguration = new LinkedHashMap<String, Map<String, String>>(); + for (Map.Entry<String, String> entry : configuration.entrySet()) { + String prefixedConfigurationKey = entry.getKey(); + String configurationValue = entry.getValue(); + if (prefixedConfigurationKey.startsWith(TOPIA_SERVICE_CONFIGURATION_PREFIX)) { + String configurationKey = StringUtils.removeStart(prefixedConfigurationKey, TOPIA_SERVICE_CONFIGURATION_PREFIX); + String[] split = StringUtils.split(configurationKey, '.'); + Preconditions.checkState(split.length > 0, "'" + prefixedConfigurationKey + "' is not a valid configuration key"); + String serviceName = split[0]; + if (split.length == 1) { + // service declaration instantiate it + try { + Class<?> loadedClass = Class.forName(configurationValue); + // TODO brendan 26/11/14 check cast + Class<? extends TopiaService> serviceClass = (Class<? extends TopiaService>) loadedClass; + declaredServices.put(serviceName, serviceClass); + } catch (ClassNotFoundException e) { + throw new TopiaMisconfigurationException("unable to find class " + configurationValue + " in classpath", this); + } + } else { + // service configuration, save it to push it back later + Map<String, String> serviceConfiguration = declaredServicesConfiguration.get(serviceName); + if (serviceConfiguration == null) { + serviceConfiguration = new LinkedHashMap<String, String>(); + declaredServicesConfiguration.put(serviceName, serviceConfiguration); + } + String serviceConfigurationKey = StringUtils.removeStart(configurationKey, serviceName + "."); + serviceConfiguration.put(serviceConfigurationKey, configurationValue); + } + } + } + declaredServices = ImmutableMap.copyOf(declaredServices); + declaredServicesConfiguration = ImmutableMap.copyOf(declaredServicesConfiguration); + } + + @Override + public Map<String, Class<? extends TopiaService>> getDeclaredServices() { + if (declaredServices == null) { + readServices(); + } + return declaredServices; + } + + @Override + public Map<String, Map<String, String>> getDeclaredServicesConfiguration() { + if (declaredServicesConfiguration == null) { + readServices(); + } + return declaredServicesConfiguration; + } + + @Override + public boolean isConnectionPoolingEnabled() { + return configuration.containsKey(AvailableSettings.C3P0_MIN_SIZE); + } + +} diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaApplicationContext.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaApplicationContext.java index a1e359c..08f8aaa 100644 --- a/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaApplicationContext.java +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaApplicationContext.java @@ -24,7 +24,6 @@ package org.nuiton.topia.persistence; * #L% */ -import com.google.common.collect.ImmutableMap; import org.nuiton.topia.persistence.support.TopiaListenableSupport; import org.nuiton.topia.persistence.support.TopiaServiceSupport; @@ -87,12 +86,10 @@ public interface TopiaApplicationContext<K extends TopiaPersistenceContext> Class<? extends TopiaEntity>[] getContractClasses(); - ImmutableMap<String, String> getConfiguration(); + TopiaConfiguration getConfiguration(); List<Class<?>> getPersistenceClasses(); - boolean isInitSchema(); - void initSchema(); boolean isSchemaEmpty(); diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaConfiguration.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaConfiguration.java new file mode 100644 index 0000000..51c8ca3 --- /dev/null +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaConfiguration.java @@ -0,0 +1,38 @@ +package org.nuiton.topia.persistence; + +import java.util.Map; + +/** + * Configuration needed to instantiate a {@link org.nuiton.topia.persistence.TopiaApplicationContext} + * + * @since 3.0 + */ +public interface TopiaConfiguration { + + boolean isInitSchema(); + + String getTopiaIdFactoryClassName(); + + String getSchemaName(); + + String getJdbcDriverClassName(); + + String getJdbcConnectionUrl(); + + String getJdbcConnectionUser(); + + String getJdbcConnectionPassword(); + + Map<String, String> getHibernateExtraConfiguration(); + + boolean isConnectionPoolingEnabled(); + + Integer getConnectionPoolMinSize(); + + Integer getConnectionPoolMaxSize(); + + Map<String,Class<? extends TopiaService>> getDeclaredServices(); + + Map<String,Map<String,String>> getDeclaredServicesConfiguration(); + +} diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaConfigurationBuilder.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaConfigurationBuilder.java new file mode 100644 index 0000000..9dfd18f --- /dev/null +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaConfigurationBuilder.java @@ -0,0 +1,294 @@ +package org.nuiton.topia.persistence; + +import org.apache.commons.lang3.StringUtils; + +import java.util.Collections; +import java.util.Map; + +public class TopiaConfigurationBuilder { + + /** + * Do nothing but throws {@link TopiaMisconfigurationException} if there is a problem in + * given configuration. + */ + public static void check(TopiaConfiguration topiaConfiguration) throws TopiaMisconfigurationException { + if (StringUtils.isBlank(topiaConfiguration.getJdbcConnectionUrl())) { + throw new TopiaMisconfigurationException("you must provide JDBC connection URL", topiaConfiguration); + } + if (StringUtils.isBlank(topiaConfiguration.getJdbcConnectionUser())) { + throw new TopiaMisconfigurationException("you must provide JDBC connection user", topiaConfiguration); + } + if (topiaConfiguration.getJdbcConnectionPassword() == null) { + throw new TopiaMisconfigurationException("you must provide JDBC connection password", topiaConfiguration); + } + if (topiaConfiguration.isConnectionPoolingEnabled()) { + if (topiaConfiguration.getConnectionPoolMinSize() == null || topiaConfiguration.getConnectionPoolMaxSize() == null) { + throw new TopiaMisconfigurationException("You must configure pool size if you want it to be enabled", topiaConfiguration); + } + } + Map<String, String> hibernateExtraConfiguration = topiaConfiguration.getHibernateExtraConfiguration(); + if (hibernateExtraConfiguration.containsKey(TopiaConfigurationConstants.CONFIG_HBM2DDL_AUTO)) { + throw new TopiaMisconfigurationException("you must not use " + TopiaConfigurationConstants.CONFIG_HBM2DDL_AUTO + + " configuration directive, if you want Hibernate to update the schema, use " + + HibernateTopiaMigrationService.class.getName(), topiaConfiguration); + } + for (Map.Entry<String, String> entry : hibernateExtraConfiguration.entrySet()) { + String key = entry.getKey(); + boolean entryIsOk = key.startsWith("hibernate.") + && ! TopiaConfigurationConstants.MAIN_CONFIGURATION.contains(key); + if ( ! entryIsOk) { + throw new TopiaMisconfigurationException("hibernate extra configuration is " + + hibernateExtraConfiguration + + " but it should not contains a key " + key, topiaConfiguration); + } + } + } + + public static ConfigureConnectionPoolingStep forPostgresqlDatabase(String jdbcConnectionUrl, String jdbcConnectionUser, String jdbcConnectionPassword) { + return forDatabase(jdbcConnectionUrl, jdbcConnectionUser, jdbcConnectionPassword, "org.postgresql.Driver"); + } + + public static ConfigureConnectionPoolingStep forH2Database(String jdbcConnectionUrl, String jdbcConnectionUser, String jdbcConnectionPassword) { + return forDatabase(jdbcConnectionUrl, jdbcConnectionUser, jdbcConnectionPassword, "org.h2.Driver"); + } + + public static ConfigureConnectionPoolingStep forH2Database(String jdbcConnectionUrl) { + return forH2Database(jdbcConnectionUrl, "sa", ""); + } + + public static ConfigureConnectionPoolingStep forDatabase(String jdbcConnectionUrl, String jdbcConnectionUser, String jdbcConnectionPassword, String jdbcDriverClassName) { + TopiaConfigurationBean topiaConfigurationBean = new TopiaConfigurationBean(); + topiaConfigurationBean.setJdbcConnectionUrl(jdbcConnectionUrl); + topiaConfigurationBean.setJdbcConnectionUser(jdbcConnectionUser); + topiaConfigurationBean.setJdbcConnectionPassword(jdbcConnectionPassword); + topiaConfigurationBean.setJdbcDriverClassName(jdbcDriverClassName); + return new ConfigureConnectionPoolingStep(topiaConfigurationBean); + } + + protected static class TopiaConfigurationBean implements TopiaConfiguration { + + private String topiaIdFactoryClassName; + + private String schemaName; + + private String jdbcDriverClassName; + + private String jdbcConnectionUrl; + + private String jdbcConnectionUser; + + private String jdbcConnectionPassword; + + private Map<String, String> hibernateExtraConfiguration; + + private boolean connectionPoolingEnabled; + + private Integer connectionPoolMinSize; + + private boolean initSchema; + + private Map<String, Class<? extends TopiaService>> declaredServices; + + private Map<String, Map<String, String>> declaredServicesConfiguration; + + private Integer connectionPoolMaxSize; + + @Override + public String getTopiaIdFactoryClassName() { + return topiaIdFactoryClassName; + } + + public void setTopiaIdFactoryClassName(String topiaIdFactoryClassName) { + this.topiaIdFactoryClassName = topiaIdFactoryClassName; + } + + @Override + public String getSchemaName() { + return schemaName; + } + + public void setSchemaName(String schemaName) { + this.schemaName = schemaName; + } + + @Override + public String getJdbcDriverClassName() { + return jdbcDriverClassName; + } + + public void setJdbcDriverClassName(String jdbcDriverClassName) { + this.jdbcDriverClassName = jdbcDriverClassName; + } + + @Override + public String getJdbcConnectionUrl() { + return jdbcConnectionUrl; + } + + public void setJdbcConnectionUrl(String jdbcConnectionUrl) { + this.jdbcConnectionUrl = jdbcConnectionUrl; + } + + @Override + public String getJdbcConnectionUser() { + return jdbcConnectionUser; + } + + public void setJdbcConnectionUser(String jdbcConnectionUser) { + this.jdbcConnectionUser = jdbcConnectionUser; + } + + @Override + public String getJdbcConnectionPassword() { + return jdbcConnectionPassword; + } + + public void setJdbcConnectionPassword(String jdbcConnectionPassword) { + this.jdbcConnectionPassword = jdbcConnectionPassword; + } + + @Override + public Map<String, String> getHibernateExtraConfiguration() { + return hibernateExtraConfiguration; + } + + public void setHibernateExtraConfiguration(Map<String, String> hibernateExtraConfiguration) { + this.hibernateExtraConfiguration = hibernateExtraConfiguration; + } + + @Override + public boolean isConnectionPoolingEnabled() { + return connectionPoolingEnabled; + } + + public void setConnectionPoolingEnabled(boolean connectionPoolingEnabled) { + this.connectionPoolingEnabled = connectionPoolingEnabled; + } + + @Override + public Integer getConnectionPoolMinSize() { + return connectionPoolMinSize; + } + + public void setConnectionPoolMinSize(Integer connectionPoolMinSize) { + this.connectionPoolMinSize = connectionPoolMinSize; + } + + @Override + public boolean isInitSchema() { + return initSchema; + } + + public void setInitSchema(boolean initSchema) { + this.initSchema = initSchema; + } + + @Override + public Map<String, Class<? extends TopiaService>> getDeclaredServices() { + return declaredServices; + } + + public void setDeclaredServices(Map<String, Class<? extends TopiaService>> declaredServices) { + this.declaredServices = declaredServices; + } + + @Override + public Map<String, Map<String, String>> getDeclaredServicesConfiguration() { + return declaredServicesConfiguration; + } + + public void setDeclaredServicesConfiguration(Map<String, Map<String, String>> declaredServicesConfiguration) { + this.declaredServicesConfiguration = declaredServicesConfiguration; + } + + @Override + public Integer getConnectionPoolMaxSize() { + return connectionPoolMaxSize; + } + + public void setConnectionPoolMaxSize(Integer connectionPoolMaxSize) { + this.connectionPoolMaxSize = connectionPoolMaxSize; + } + + public void addDeclaredService(String serviceName, String serviceClassName, Map<String, String> serviceConfiguration) { + try { + Class<?> aClass = Class.forName(serviceClassName); + Class<? extends TopiaService> serviceClass = (Class<? extends TopiaService>) aClass; + addDeclaredService(serviceName, serviceClass, serviceConfiguration); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(serviceClassName + " cannot be found in classpath"); + } + } + + public void addDeclaredService(String serviceName, Class<? extends TopiaService> serviceClassName, Map<String, String> serviceConfiguration) { + declaredServices.put(serviceName, serviceClassName); + declaredServicesConfiguration.put(serviceName, serviceConfiguration); + } + + } + + protected static class ConfigureConnectionPoolingStep { + + protected TopiaConfigurationBean topiaConfigurationBean; + + public ConfigureConnectionPoolingStep(TopiaConfigurationBean topiaConfigurationBean) { + this.topiaConfigurationBean = topiaConfigurationBean; + } + + public ConfigureInitSchemaStep doNotUseConnectionPooling() { + topiaConfigurationBean.setConnectionPoolingEnabled(false); + return new ConfigureInitSchemaStep(topiaConfigurationBean); + } + + public ConfigureInitSchemaStep useConnectionPooling(int connectionPoolMinSize, int connectionPoolMaxSize) { + topiaConfigurationBean.setConnectionPoolingEnabled(true); + topiaConfigurationBean.setConnectionPoolMinSize(connectionPoolMinSize); + topiaConfigurationBean.setConnectionPoolMaxSize(connectionPoolMaxSize); + return new ConfigureInitSchemaStep(topiaConfigurationBean); + } + + } + + protected static class ConfigureInitSchemaStep { + + protected TopiaConfigurationBean topiaConfigurationBean; + + public ConfigureInitSchemaStep(TopiaConfigurationBean topiaConfigurationBean) { + this.topiaConfigurationBean = topiaConfigurationBean; + } + + public BuildStep dontTouchTheSchema() { + return new BuildStep(topiaConfigurationBean); + } + + public BuildStep useHiberateUpdate() { + topiaConfigurationBean.addDeclaredService("migration", org.nuiton.topia.persistence.HibernateTopiaMigrationService.class, Collections.<String, String>emptyMap()); + return new BuildStep(topiaConfigurationBean); + } + + public BuildStep useFlyway() { + topiaConfigurationBean.addDeclaredService("migration", "org.nuiton.topia.flyway.TopiaFlywayServiceImpl", Collections.<String, String>emptyMap()); + return new BuildStep(topiaConfigurationBean); + } + + public BuildStep useLiquibase() { + topiaConfigurationBean.addDeclaredService("migration", "org.nuiton.topia.flyway.TopiaLiquibaseServiceImpl", Collections.<String, String>emptyMap()); + return new BuildStep(topiaConfigurationBean); + } + + } + + protected static class BuildStep { + + protected TopiaConfigurationBean topiaConfigurationBean; + + public BuildStep(TopiaConfigurationBean topiaConfigurationBean) { + this.topiaConfigurationBean = topiaConfigurationBean; + } + + public TopiaConfigurationBean build() { + check(topiaConfigurationBean); + return topiaConfigurationBean; + } + } +} diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaConfigurationConstants.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaConfigurationConstants.java index 4652f5b..1f5f5ad 100644 --- a/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaConfigurationConstants.java +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaConfigurationConstants.java @@ -24,6 +24,8 @@ package org.nuiton.topia.persistence; * #L% */ +import com.google.common.collect.ImmutableSet; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; /** @@ -36,6 +38,15 @@ import org.hibernate.cfg.Environment; */ public interface TopiaConfigurationConstants { + ImmutableSet<String> MAIN_CONFIGURATION = ImmutableSet.of( + TopiaConfigurationConstants.CONFIG_DRIVER, + TopiaConfigurationConstants.CONFIG_URL, + TopiaConfigurationConstants.CONFIG_USER, + TopiaConfigurationConstants.CONFIG_PASS, + AvailableSettings.C3P0_MIN_SIZE, + AvailableSettings.C3P0_MAX_SIZE + ); + String CONFIG_DEFAULT_SCHEMA = Environment.DEFAULT_SCHEMA; String CONFIG_USER = Environment.USER; @@ -64,13 +75,8 @@ public interface TopiaConfigurationConstants { String CONFIG_URL = Environment.URL; - @Deprecated - String CONFIG_PERSISTENCE_DIRECTORIES = "topia.persistence.directories"; - String CONFIG_PERSISTENCE_CLASSES = "topia.persistence.classes"; - String CONFIG_PERSISTENCE_PROPERTIES_FILE = "topia.persistence.properties.file"; - /** * Configuration directive to change topia Ids generation strategy. * <p/> diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaMisconfigurationException.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaMisconfigurationException.java new file mode 100644 index 0000000..683b2ff --- /dev/null +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaMisconfigurationException.java @@ -0,0 +1,20 @@ +package org.nuiton.topia.persistence; + +/** + * Exception raised when a user has wrongly configured ToPIA. + * + * @since 3.0 + */ +public class TopiaMisconfigurationException extends TopiaException { + + protected TopiaConfiguration topiaConfiguration; + + public TopiaMisconfigurationException(String message, TopiaConfiguration topiaConfiguration) { + super(message); + this.topiaConfiguration = topiaConfiguration; + } + + public TopiaConfiguration getTopiaConfiguration() { + return topiaConfiguration; + } +} diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaService.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaService.java index 02d758f..e5d6585 100644 --- a/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaService.java +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaService.java @@ -45,13 +45,6 @@ public interface TopiaService { void initTopiaService(TopiaApplicationContext topiaApplicationContext, Map<String, String> serviceConfiguration); /** - * Retrieve entities of this service needed for persistence. - * - * @return List of entities full qualified name separated by a comma - */ - Class<?>[] getPersistenceClasses(); - - /** * Called when service is no longer necessary. This method is called when {@link TopiaApplicationContext#close} * is called. */ diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/AbstractTopiaApplicationContext.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/AbstractTopiaApplicationContext.java index 82591fb..d7be043 100644 --- a/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/AbstractTopiaApplicationContext.java +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/AbstractTopiaApplicationContext.java @@ -25,10 +25,7 @@ package org.nuiton.topia.persistence.internal; */ import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -36,9 +33,10 @@ import org.hibernate.HibernateException; import org.hibernate.cfg.Configuration; import org.hibernate.tool.hbm2ddl.SchemaExport; import org.hibernate.tool.hbm2ddl.SchemaUpdate; +import org.nuiton.topia.persistence.PropertiesTopiaConfiguration; import org.nuiton.topia.persistence.TopiaApplicationContext; import org.nuiton.topia.persistence.TopiaApplicationContextCache; -import org.nuiton.topia.persistence.TopiaConfigurationConstants; +import org.nuiton.topia.persistence.TopiaConfiguration; import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.topia.persistence.TopiaException; import org.nuiton.topia.persistence.TopiaIdFactory; @@ -57,6 +55,7 @@ import org.nuiton.topia.persistence.support.TopiaServiceSupport; import org.nuiton.topia.persistence.util.TopiaUtil; import java.beans.PropertyChangeListener; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -79,7 +78,7 @@ public abstract class AbstractTopiaApplicationContext<K extends TopiaPersistence protected TopiaIdFactory topiaIdFactory; - protected ImmutableMap<String, String> configuration; + protected TopiaConfiguration configuration; protected TopiaFiresSupport topiaFiresSupport; @@ -98,18 +97,24 @@ public abstract class AbstractTopiaApplicationContext<K extends TopiaPersistence protected Set<TopiaPersistenceContext> persistenceContexts = Collections.newSetFromMap( new WeakHashMap<TopiaPersistenceContext, Boolean>()); + /** + * @deprecated use {@link #AbstractTopiaApplicationContext(org.nuiton.topia.persistence.TopiaConfiguration)} + */ + @Deprecated public AbstractTopiaApplicationContext(Properties properties) { - // TODO arnaud 11/10/13 vérifier le comportement - this((Map) ImmutableMap.copyOf(properties)); + this(new PropertiesTopiaConfiguration(properties)); } + /** + * @deprecated use {@link #AbstractTopiaApplicationContext(org.nuiton.topia.persistence.TopiaConfiguration)} + */ + @Deprecated public AbstractTopiaApplicationContext(Map<String, String> configuration) { - Map<String, String> configurationCopy = Maps.newHashMap(); - configurationCopy.putAll(configuration); - if ( ! configuration.containsKey(TopiaConfigurationConstants.CONFIG_PERSISTENCE_CLASSES)) { - configurationCopy.put(TopiaConfigurationConstants.CONFIG_PERSISTENCE_CLASSES, getImplementationClassesAsString()); - } - this.configuration = ImmutableMap.copyOf(configurationCopy); + this(new PropertiesTopiaConfiguration(configuration)); + } + + public AbstractTopiaApplicationContext(TopiaConfiguration configuration) { + this.configuration = configuration; init(); } @@ -148,13 +153,12 @@ public abstract class AbstractTopiaApplicationContext<K extends TopiaPersistence /** * If application context should init schema. * - * This implementation check for {@link TopiaConfigurationConstants#CONFIG_PERSISTENCE_INIT_SCHEMA} - * value and return true by default. + * This simple check is in its own method so it can be overridden. + * + * @see {@link org.nuiton.topia.persistence.TopiaConfiguration#isInitSchema()} */ - @Override - public boolean isInitSchema() { - String initSchemaConfigValue = getConfiguration().get(TopiaConfigurationConstants.CONFIG_PERSISTENCE_INIT_SCHEMA); - boolean initSchema = StringUtils.isBlank(initSchemaConfigValue) || Boolean.parseBoolean(initSchemaConfigValue); + protected boolean isInitSchema() { + boolean initSchema = configuration.isInitSchema(); return initSchema; } @@ -175,67 +179,40 @@ public abstract class AbstractTopiaApplicationContext<K extends TopiaPersistence boolean migrationServiceEnabled = ! migrationServices.isEmpty(); - String hbm2ddlAutoConfigurationValue = - getConfiguration().get( - TopiaConfigurationConstants.CONFIG_HBM2DDL_AUTO); - // see {@link org.hibernate.cfg.SettingsFactory.buildSettings()} - boolean hbm2ddlAutoEnabled = - ImmutableSet.of("update", "create", "create-drop").contains(hbm2ddlAutoConfigurationValue); - - if (hbm2ddlAutoEnabled) { - Preconditions.checkState( - ! migrationServiceEnabled, - String.format("Your configuration includes both a migration service and [%s=%s] configuration " + - "directive. That will lead to an inconsistent state of the schema", - TopiaConfigurationConstants.CONFIG_HBM2DDL_AUTO, hbm2ddlAutoConfigurationValue)); + if (isSchemaEmpty()) { if (log.isInfoEnabled()) { - String format = "%s=%s detected, will let Hibernate deal with schema initialization"; - log.info(String.format(format,TopiaConfigurationConstants.CONFIG_HBM2DDL_AUTO, hbm2ddlAutoConfigurationValue)); + log.info("schema is empty, will create"); } - } else { - if (isSchemaEmpty()) { + createSchema(); + if (migrationServiceEnabled) { if (log.isInfoEnabled()) { - log.info("schema is empty, will create"); + log.info("schema created, will call migration service"); } - createSchema(); - if (migrationServiceEnabled) { - if (log.isInfoEnabled()) { - log.info("schema created, will call migration service"); - } - TopiaMigrationService migrationService = - Iterables.getOnlyElement(migrationServices); - migrationService.initOnCreateSchema(); - } else { - if (log.isInfoEnabled()) { - log.info("schema created, no migration service provided"); - } + TopiaMigrationService migrationService = + Iterables.getOnlyElement(migrationServices); + migrationService.initOnCreateSchema(); + } else { + if (log.isInfoEnabled()) { + log.info("schema created, no migration service provided"); + } + } + } else { + if (migrationServiceEnabled) { + if (log.isInfoEnabled()) { + log.info("schema exists, will try to migrate"); } + TopiaMigrationService migrationService = + Iterables.getOnlyElement(migrationServices); + migrationService.runSchemaMigration(); } else { - if (migrationServiceEnabled) { - if (log.isInfoEnabled()) { - log.info("schema exists, will try to migrate"); - } - TopiaMigrationService migrationService = - Iterables.getOnlyElement(migrationServices); - migrationService.runSchemaMigration(); - } else { - if (log.isInfoEnabled()) { - log.info("schema exists, no migration service provided"); - } + if (log.isInfoEnabled()) { + log.info("schema exists, no migration service provided"); } } } } - protected abstract Class<? extends TopiaEntity>[] getImplementationClasses(); - - protected String getImplementationClassesAsString() { - StringBuilder buffer = new StringBuilder(); - for (Class<? extends TopiaEntity> aClass : getImplementationClasses()) { - buffer.append(',').append(aClass.getName()); - } - return buffer.substring(1); - } + protected abstract Set<Class<? extends TopiaEntity>> getImplementationClasses(); protected void registerPersistenceContext(TopiaPersistenceContext persistenceContext) { persistenceContexts.add(persistenceContext); @@ -244,7 +221,7 @@ public abstract class AbstractTopiaApplicationContext<K extends TopiaPersistence // FIXME AThimel 25/11/13 I don't like it to be public, but necessary for services. Review it public HibernateProvider getHibernateProvider() { if (hibernateProvider == null) { - hibernateProvider = new HibernateProvider(configuration, topiaServiceSupport, sessionRegistry); + hibernateProvider = new HibernateProvider(getConfiguration(), topiaServiceSupport, sessionRegistry, getImplementationClasses()); } return hibernateProvider; } @@ -254,14 +231,13 @@ public abstract class AbstractTopiaApplicationContext<K extends TopiaPersistence } @Override - public ImmutableMap<String, String> getConfiguration() { + public TopiaConfiguration getConfiguration() { return configuration; } protected TopiaIdFactory getTopiaIdFactory() { if (topiaIdFactory == null) { - String topiaIdFactoryClassName = - getConfiguration().get(TopiaConfigurationConstants.CONFIG_PERSISTENCE_TOPIA_ID_FACTORY_CLASS_NAME); + String topiaIdFactoryClassName = getConfiguration().getTopiaIdFactoryClassName(); if (StringUtils.isEmpty(topiaIdFactoryClassName)) { topiaIdFactory = new DefaultTopiaIdFactory(); } else { @@ -391,7 +367,7 @@ public abstract class AbstractTopiaApplicationContext<K extends TopiaPersistence @Override public List<Class<?>> getPersistenceClasses() { - return getHibernateProvider().getPersistentClasses(); + return new ArrayList<Class<?>>(getImplementationClasses()); } @Override @@ -413,7 +389,7 @@ public abstract class AbstractTopiaApplicationContext<K extends TopiaPersistence @Override public String getSchemaName() { // TODO AThimel 02/08/13 I absolutely don't know if it works - return getConfiguration().get(TopiaConfigurationConstants.CONFIG_DEFAULT_SCHEMA); + return getConfiguration().getSchemaName(); } @Override diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/HibernateProvider.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/HibernateProvider.java index a2907b3..5579545 100644 --- a/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/HibernateProvider.java +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/HibernateProvider.java @@ -24,20 +24,18 @@ package org.nuiton.topia.persistence.internal; * #L% */ -import java.io.File; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import org.apache.commons.lang3.StringUtils; +import com.google.common.base.Preconditions; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Environment; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.dialect.Oracle10gDialect; +import org.hibernate.dialect.PostgreSQL9Dialect; +import org.hibernate.dialect.SQLServer2012Dialect; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.event.service.spi.EventListenerRegistry; @@ -46,15 +44,15 @@ import org.hibernate.service.Service; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.service.spi.Stoppable; +import org.nuiton.topia.persistence.TopiaConfiguration; import org.nuiton.topia.persistence.TopiaConfigurationConstants; -import org.nuiton.topia.persistence.TopiaNotFoundException; -import org.nuiton.topia.persistence.TopiaService; +import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.topia.persistence.internal.support.TopiaHibernateEventListener; import org.nuiton.topia.persistence.support.TopiaServiceSupport; import org.nuiton.topia.persistence.util.TopiaUtil; -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; +import java.util.Properties; +import java.util.Set; /** * @author Arnaud Thimel (Code Lutin) @@ -66,42 +64,23 @@ public class HibernateProvider { protected SessionFactory hibernateSessionFactory; protected Configuration hibernateConfiguration; - protected Map<String, String> configuration; + protected TopiaConfiguration topiaConfiguration; protected TopiaServiceSupport topiaServiceSupport; protected TopiaHibernateSessionRegistry sessionRegistry; /** * List of persistent classes */ - protected List<Class<?>> persistentClasses = Lists.newArrayList(); + protected Set<Class<? extends TopiaEntity>> entityClasses; - public HibernateProvider(Map<String, String> configuration, + public HibernateProvider(TopiaConfiguration topiaConfiguration, TopiaServiceSupport topiaServiceSupport, - TopiaHibernateSessionRegistry sessionRegistry) { - this.configuration = configuration; + TopiaHibernateSessionRegistry sessionRegistry, + Set<Class<? extends TopiaEntity>> entityClasses) { + this.topiaConfiguration = topiaConfiguration; this.topiaServiceSupport = topiaServiceSupport; this.sessionRegistry = sessionRegistry; - } - - protected String getProperty(String key) { - return getProperty(key, null); - } - - protected String getProperty(String key, String defaultValue) { - String result = defaultValue; - if (configuration.containsKey(key)) { - result = configuration.get(key); - } - - return result; - } - - public List<Class<?>> getPersistentClasses() { - if (persistentClasses.isEmpty()) { - // Force configuration load - getHibernateConfiguration(); - } - return persistentClasses; + this.entityClasses = entityClasses; } /** @@ -129,100 +108,67 @@ public class HibernateProvider { * @return a new Hibernate Configuration instance without built mappings. */ public Configuration newHibernateConfiguration() { - Configuration result = new Configuration(); - - // ajout des repertoires contenant les mappings hibernate - String[] dirs = getProperty( - TopiaConfigurationConstants.CONFIG_PERSISTENCE_DIRECTORIES, "").split(","); - for (String dir : dirs) { - dir = dir.trim(); - if (StringUtils.isNotEmpty(dir)) { - if (log.isDebugEnabled()) { - log.debug("Load persistence from dir : " + dir); - } - result.addDirectory(new File(dir)); - } - } - // ajout des classes dites persistentes - Set<Class<?>> hibernatePersistanceClasses = new HashSet<Class<?>>(); - for (TopiaService service : topiaServiceSupport.getServices().values()) { - Class<?>[] classes = service.getPersistenceClasses(); - - // certains service n'ont pas de classe persistantes - if (classes != null) { - // sletellier 20110411 : http://www.nuiton.org/issues/show/1454 - hibernatePersistanceClasses.addAll(Arrays.asList(classes)); -// for (Class<?> clazz : classes) { -// hibernateConfiguration.addClass(clazz); -// } - } - } + Configuration newHibernateConfiguration = new Configuration(); - String listPersistenceClasses = getProperty( - TopiaConfigurationConstants.CONFIG_PERSISTENCE_CLASSES, ""); - - String[] classes = listPersistenceClasses.split(","); - for (String classname : classes) { - classname = classname.trim(); - if (StringUtils.isNotEmpty(classname)) { - if (log.isDebugEnabled()) { - log.debug("Load persistent class : " + classname); - } - - // XXX echatellier 20111007 ce qui est dommage ici, c'est - // la definition de cette classe ne sert a rien (apart security) - // car pour hibernate hibernateConfiguration.addClass(persistanceClass) - // il ne se sert pas de la classe en fait et fait seulement - // un classname.replace( '.', '/' ) + ".hbm.xml"; - // pour obtenir le mapping et la reinstancier ensuite - - Class<?> clazz; - try { - clazz = Class.forName(classname); - } catch (ClassNotFoundException eee) { - if (log.isDebugEnabled()) { - log.debug("Class " + classname + " not found"); - } - throw new TopiaNotFoundException( - String.format("Persistence class %1$s not found", - classname)); - } - persistentClasses.add(clazz); - - // sletellier 20110411 : http://www.nuiton.org/issues/show/1454 -// hibernateConfiguration.addClass(clazz); - hibernatePersistanceClasses.add(clazz); - } + for (Class<? extends TopiaEntity> entityClass : entityClasses) { + newHibernateConfiguration.addClass(entityClass); } - // sletellier 20110411 : http://www.nuiton.org/issues/show/1454 - // Add persistence classes in hibernate config - for (Class<?> persistenceClass : hibernatePersistanceClasses) { - result.addClass(persistenceClass); - } + Properties properties = new Properties(); - Properties prop = new Properties(); - prop.putAll(result.getProperties()); - prop.putAll(configuration); + // JDBC + properties.put(Environment.URL, topiaConfiguration.getJdbcConnectionUrl()); + properties.put(Environment.DRIVER, topiaConfiguration.getJdbcDriverClassName()); + properties.put(Environment.USER, topiaConfiguration.getJdbcConnectionUser()); + properties.put(Environment.PASS, topiaConfiguration.getJdbcConnectionPassword()); - // Strange behavior, all properties are already loaded from - // constructor. Difficult to use this behavior, need to have - // TOPIA_PERSISTENCE_PROPERTIES_FILE in config. - Properties propertiesFromClasspath = - TopiaUtil.getProperties(getProperty(TopiaConfigurationConstants.CONFIG_PERSISTENCE_PROPERTIES_FILE)); + // dialect + properties.put(Environment.DIALECT, getHibernateDialect(topiaConfiguration)); - if (!propertiesFromClasspath.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("Load properties from file : " + - propertiesFromClasspath); - } - prop.putAll(propertiesFromClasspath); + // Connection pool + if (topiaConfiguration.isConnectionPoolingEnabled()) { + properties.put(AvailableSettings.C3P0_MIN_SIZE, topiaConfiguration.getConnectionPoolMinSize()); + properties.put(AvailableSettings.C3P0_MAX_SIZE, topiaConfiguration.getConnectionPoolMaxSize()); } - result.setProperties(prop); + properties.put(Environment.HBM2DDL_AUTO, "validate"); - return result; + // TODO brendan 27/11/14 check if C3P0 in classpath ? + + // user specific configuration + properties.putAll(topiaConfiguration.getHibernateExtraConfiguration()); + + newHibernateConfiguration.setProperties(properties); + + return newHibernateConfiguration; + + } + + public static String getHibernateDialect(TopiaConfiguration topiaConfiguration) { + String hibernateDialect = topiaConfiguration.getHibernateExtraConfiguration().get(TopiaConfigurationConstants.CONFIG_DIALECT); + if (hibernateDialect == null) { + hibernateDialect = guessHibernateDialect(topiaConfiguration.getJdbcConnectionUrl(), topiaConfiguration.getJdbcDriverClassName()); + } + return hibernateDialect; + } + + public static String guessHibernateDialect(String jdbcConnectionUrl, String jdbcDriverClassName) { + String guessedHibernateDialect = null; + if (jdbcConnectionUrl.startsWith("jdbc:postgresql:") || jdbcDriverClassName.equals("org.postgresql.Driver")) { + guessedHibernateDialect = PostgreSQL9Dialect.class.getName(); + } else if (jdbcConnectionUrl.startsWith("jdbc:h2:") || jdbcDriverClassName.equals("org.h2.Driver")) { + guessedHibernateDialect = H2Dialect.class.getName(); + } else if (jdbcConnectionUrl.startsWith("jdbc:oracle:") || jdbcDriverClassName.equals("oracle.jdbc.driver.OracleDriver")) { + guessedHibernateDialect = Oracle10gDialect.class.getName(); + } else if (jdbcConnectionUrl.startsWith("jdbc:jtds:sqlserver:") || jdbcDriverClassName.equals("net.sourceforge.jtds.jdbc.Driver")) { + guessedHibernateDialect = SQLServer2012Dialect.class.getName(); + } else { + if (log.isWarnEnabled()) { + log.warn("unable to guess Hibernate dialect for JDBC URL " + jdbcConnectionUrl + " and JDBC driver " + jdbcDriverClassName + ". Please, submit a patch!"); + } + } + return guessedHibernateDialect; } /** diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/support/TopiaServiceSupportImpl.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/support/TopiaServiceSupportImpl.java index 504f809..df187cc 100644 --- a/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/support/TopiaServiceSupportImpl.java +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/support/TopiaServiceSupportImpl.java @@ -24,12 +24,11 @@ package org.nuiton.topia.persistence.internal.support; * #L% */ -import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.topia.persistence.TopiaApplicationContext; +import org.nuiton.topia.persistence.TopiaConfiguration; import org.nuiton.topia.persistence.TopiaException; import org.nuiton.topia.persistence.TopiaService; import org.nuiton.topia.persistence.support.TopiaServiceSupport; @@ -75,81 +74,48 @@ public class TopiaServiceSupportImpl implements TopiaServiceSupport { private static final Log log = LogFactory.getLog(TopiaServiceSupportImpl.class); - protected static final String TOPIA_SERVICE_CONFIGURATION_PREFIX = "topia.service."; - protected ImmutableMap<String, TopiaService> services; public void initServices(TopiaApplicationContext topiaApplicationContext) { - ImmutableMap<String, String> topiaApplicationContextConfiguration = + TopiaConfiguration topiaConfiguration = topiaApplicationContext.getConfiguration(); - // the services: name → instance - Map<String, TopiaService> services = new HashMap<String, TopiaService>(); - - // the services configurations (key is the name of the service) - Map<String, Map<String, String>> servicesConfigurations = new HashMap<String, Map<String, String>>(); - - // read topiaApplicationContextConfiguration and fill both services and servicesConfigurations maps. - loadServices(topiaApplicationContextConfiguration, services, servicesConfigurations); + Map<String, Class<? extends TopiaService>> declaredServices = + topiaConfiguration.getDeclaredServices(); - // now all the services are instantiated and and the configuration are known, call init on all services - callInitOnAllTopiaServices(topiaApplicationContext, services, servicesConfigurations); - - // keep references of all the service created for further use - this.services = ImmutableMap.copyOf(services); - - } + Map<String, Map<String, String>> declaredServicesConfiguration = + topiaConfiguration.getDeclaredServicesConfiguration(); + // the services: name → instance + Map<String, TopiaService> services = new HashMap<String, TopiaService>(); - /** - * Read topiaApplicationContextConfiguration and fill both services and servicesConfigurations maps. - */ - protected void loadServices(ImmutableMap<String, String> topiaApplicationContextConfiguration, Map<String, TopiaService> services, Map<String, Map<String, String>> servicesConfigurations) { - for (Map.Entry<String, String> entry : topiaApplicationContextConfiguration.entrySet()) { - String prefixedConfigurationKey = entry.getKey(); - String configurationValue = entry.getValue(); - if (prefixedConfigurationKey.startsWith(TOPIA_SERVICE_CONFIGURATION_PREFIX)) { - String configurationKey = StringUtils.removeStart(prefixedConfigurationKey, TOPIA_SERVICE_CONFIGURATION_PREFIX); - String[] split = StringUtils.split(configurationKey, '.'); - Preconditions.checkState(split.length > 0, "'" + prefixedConfigurationKey + "' is not a valid configuration key"); - String serviceName = split[0]; - if (split.length == 1) { - // service declaration instantiate it - try { - Class<?> forName = Class.forName(configurationValue); - Object newInstance = forName.getConstructor().newInstance(); - TopiaService service1 = (TopiaService) newInstance; - services.put(serviceName, service1); - if (log.isInfoEnabled()) { - log.info("instantiated service " + serviceName + ": " + service1); - } - } catch (ClassNotFoundException e) { - throw new TopiaException("unable to find topia service class " + configurationValue, e); - } catch (InstantiationException e) { - throw new TopiaException("unable to instantiate class " + configurationValue, e); - } catch (IllegalAccessException e) { - throw new TopiaException("unable to instantiate class " + configurationValue, e); - } catch (InvocationTargetException e) { - throw new TopiaException("unable to instantiate class " + configurationValue, e); - } catch (NoSuchMethodException e) { - throw new TopiaException("unable to instantiate class " + configurationValue, e); - } - } else { - // service configuration, save it to push it back later - Map<String, String> serviceConfiguration = servicesConfigurations.get(serviceName); - if (serviceConfiguration == null) { - serviceConfiguration = new LinkedHashMap<String, String>(); - servicesConfigurations.put(serviceName, serviceConfiguration); - } - String serviceConfigurationKey = StringUtils.removeStart(configurationKey, serviceName + "."); - serviceConfiguration.put(serviceConfigurationKey, configurationValue); + // instantiate all services + for (Map.Entry<String, Class<? extends TopiaService>> entry : declaredServices.entrySet()) { + String serviceName = entry.getKey(); + Class<? extends TopiaService> serviceClass = entry.getValue(); + try { + Object newInstance = serviceClass.getConstructor().newInstance(); + TopiaService service1 = (TopiaService) newInstance; + services.put(serviceName, service1); + if (log.isInfoEnabled()) { + log.info("instantiated service " + serviceName + ": " + service1); } + } catch (InstantiationException e) { + throw new TopiaException("unable to instantiate service class " + serviceClass, e); + } catch (IllegalAccessException e) { + throw new TopiaException("unable to instantiate service class " + serviceClass, e); + } catch (InvocationTargetException e) { + throw new TopiaException("unable to instantiate service class " + serviceClass, e); + } catch (NoSuchMethodException e) { + throw new TopiaException("unable to instantiate service class " + serviceClass, e); } } - } - protected void callInitOnAllTopiaServices(TopiaApplicationContext topiaApplicationContext, Map<String, TopiaService> services, Map<String, Map<String, String>> servicesConfigurations) { + // the services configurations (key is the name of the service) + Map<String, Map<String, String>> servicesConfigurations = new HashMap<String, Map<String, String>>(); + + // now all the services are instantiated and and the configuration are known, call init on all services for (Map.Entry<String, TopiaService> entry : services.entrySet()) { String serviceName = entry.getKey(); TopiaService topiaService = entry.getValue(); @@ -162,8 +128,13 @@ public class TopiaServiceSupportImpl implements TopiaServiceSupport { } topiaService.initTopiaService(topiaApplicationContext, serviceConfiguration); } + + // keep references of all the service created for further use + this.services = ImmutableMap.copyOf(services); + } + @Override public Map<String, TopiaService> getServices() { return services; diff --git a/topia-persistence/src/test/java/org/nuiton/topia/persistence/internal/support/MyFirstTopiaServiceImpl.java b/topia-persistence/src/test/java/org/nuiton/topia/persistence/internal/support/MyFirstTopiaServiceImpl.java index d61f9cb..ddef334 100644 --- a/topia-persistence/src/test/java/org/nuiton/topia/persistence/internal/support/MyFirstTopiaServiceImpl.java +++ b/topia-persistence/src/test/java/org/nuiton/topia/persistence/internal/support/MyFirstTopiaServiceImpl.java @@ -41,11 +41,6 @@ public class MyFirstTopiaServiceImpl implements MyFirstTopiaService { } @Override - public Class<?>[] getPersistenceClasses() { - return new Class<?>[0]; - } - - @Override public void initTopiaService(TopiaApplicationContext topiaApplicationContext, Map<String, String> serviceConfiguration) { this.serviceConfiguration = serviceConfiguration; if (log.isDebugEnabled()) { diff --git a/topia-persistence/src/test/java/org/nuiton/topia/persistence/internal/support/MySecondTopiaServiceImpl.java b/topia-persistence/src/test/java/org/nuiton/topia/persistence/internal/support/MySecondTopiaServiceImpl.java index b037698..1a60d71 100644 --- a/topia-persistence/src/test/java/org/nuiton/topia/persistence/internal/support/MySecondTopiaServiceImpl.java +++ b/topia-persistence/src/test/java/org/nuiton/topia/persistence/internal/support/MySecondTopiaServiceImpl.java @@ -42,11 +42,6 @@ public class MySecondTopiaServiceImpl implements MySecondTopiaService { } @Override - public Class<?>[] getPersistenceClasses() { - return new Class<?>[0]; - } - - @Override public void close() { // nothing to do } diff --git a/topia-persistence/src/test/java/org/nuiton/topia/persistence/internal/support/TopiaServiceSupportImplTest.java b/topia-persistence/src/test/java/org/nuiton/topia/persistence/internal/support/TopiaServiceSupportImplTest.java deleted file mode 100644 index 17d5d49..0000000 --- a/topia-persistence/src/test/java/org/nuiton/topia/persistence/internal/support/TopiaServiceSupportImplTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.nuiton.topia.persistence.internal.support; - -/* - * #%L - * ToPIA :: Persistence - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2004 - 2014 CodeLutin - * %% - * This program 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 3 of the - * License, or (at your option) any later version. - * - * 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.collect.ImmutableMap; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; -import org.nuiton.topia.persistence.TopiaApplicationContext; -import org.nuiton.topia.persistence.TopiaService; - -import java.util.HashMap; -import java.util.Map; - -public class TopiaServiceSupportImplTest { - - protected TopiaServiceSupportImpl topiaServiceSupport; - - protected ImmutableMap<String, String> configuration; - - protected TopiaApplicationContext topiaApplicationContextMock = Mockito.mock(TopiaApplicationContext.class); - - @Before - public void setUp() { - String myFistTopiaServiceImplFqn = MyFirstTopiaServiceImpl.class.getName(); - String mySecondTopiaServiceImplFqn = MySecondTopiaServiceImpl.class.getName(); - configuration = ImmutableMap.<String, String>builder() - .put("topia.service.myService1", myFistTopiaServiceImplFqn) - .put("topia.service.myService1.myConfigurationKey1", "myConfigurationValue1") - .put("topia.service.myService2", mySecondTopiaServiceImplFqn) - .build(); - Mockito.when(topiaApplicationContextMock.getConfiguration()).thenReturn(configuration); - topiaServiceSupport = new TopiaServiceSupportImpl(); - } - - @Test - public void testLoadServices() { - - // the services: name → instance - Map<String, TopiaService> services = new HashMap<String, TopiaService>(); - - // the services configurations (key is the name of the service) - Map<String, Map<String, String>> servicesConfigurations = new HashMap<String, Map<String, String>>(); - - topiaServiceSupport.loadServices(configuration, services, servicesConfigurations); - - Assert.assertEquals(2, services.size()); - - TopiaService myService1 = services.get("myService1"); - - Assert.assertTrue(myService1 instanceof MyFirstTopiaServiceImpl); - - Assert.assertEquals("myConfigurationValue1", servicesConfigurations.get("myService1").get("myConfigurationKey1")); - - } - - @Test - public void testGetServices() { - - topiaServiceSupport.initServices(topiaApplicationContextMock); - - Map<String, MySecondTopiaService> services = topiaServiceSupport.getServices(MySecondTopiaService.class); - - Assert.assertEquals(1, services.size()); - - } - -} diff --git a/topia-service-flyway/src/main/java/org/nuiton/topia/flyway/TopiaFlywayServiceImpl.java b/topia-service-flyway/src/main/java/org/nuiton/topia/flyway/TopiaFlywayServiceImpl.java index dd48540..bab14a1 100644 --- a/topia-service-flyway/src/main/java/org/nuiton/topia/flyway/TopiaFlywayServiceImpl.java +++ b/topia-service-flyway/src/main/java/org/nuiton/topia/flyway/TopiaFlywayServiceImpl.java @@ -29,7 +29,6 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; - import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; @@ -38,7 +37,7 @@ import org.flywaydb.core.Flyway; import org.flywaydb.core.api.MigrationInfo; import org.flywaydb.core.internal.util.Location; import org.nuiton.topia.persistence.TopiaApplicationContext; -import org.nuiton.topia.persistence.TopiaConfigurationConstants; +import org.nuiton.topia.persistence.TopiaConfiguration; import org.nuiton.topia.persistence.TopiaException; import org.nuiton.topia.persistence.TopiaMigrationServiceException; @@ -110,12 +109,6 @@ public class TopiaFlywayServiceImpl implements TopiaFlywayService { } - @Override - public Class<?>[] getPersistenceClasses() { - // No Hibernate persistence classes to create - return null; - } - /** * Define flyway database credentials. * @@ -125,11 +118,11 @@ public class TopiaFlywayServiceImpl implements TopiaFlywayService { */ protected void setDataSource(Flyway flyway, TopiaApplicationContext topiaApplicationContext) { - Map<String, String> configuration = topiaApplicationContext.getConfiguration(); + TopiaConfiguration configuration = topiaApplicationContext.getConfiguration(); - String url = configuration.get(TopiaConfigurationConstants.CONFIG_URL); - String user = configuration.get(TopiaConfigurationConstants.CONFIG_USER); - String password = configuration.get(TopiaConfigurationConstants.CONFIG_PASS); + String url = configuration.getJdbcConnectionUrl(); + String user = configuration.getJdbcConnectionUser(); + String password = configuration.getJdbcConnectionPassword(); flyway.setDataSource(url, user, password); diff --git a/topia-service-liquibase/src/main/java/org/nuiton/topia/liquibase/TopiaLiquibaseServiceImpl.java b/topia-service-liquibase/src/main/java/org/nuiton/topia/liquibase/TopiaLiquibaseServiceImpl.java index 25e161a..116a676 100644 --- a/topia-service-liquibase/src/main/java/org/nuiton/topia/liquibase/TopiaLiquibaseServiceImpl.java +++ b/topia-service-liquibase/src/main/java/org/nuiton/topia/liquibase/TopiaLiquibaseServiceImpl.java @@ -37,7 +37,7 @@ import liquibase.resource.ResourceAccessor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.topia.persistence.TopiaApplicationContext; -import org.nuiton.topia.persistence.TopiaConfigurationConstants; +import org.nuiton.topia.persistence.TopiaConfiguration; import org.nuiton.topia.persistence.TopiaMigrationServiceException; import java.util.Map; @@ -90,11 +90,6 @@ public class TopiaLiquibaseServiceImpl implements TopiaLiquibaseService { } @Override - public Class<?>[] getPersistenceClasses() { - return new Class<?>[0]; - } - - @Override public String getSchemaVersion() { // TODO brendan 18/07/14 use http://www.liquibase.org/documentation/changes/tag_database.html ? @@ -156,10 +151,10 @@ public class TopiaLiquibaseServiceImpl implements TopiaLiquibaseService { } protected Database openDatabase(TopiaApplicationContext topiaApplicationContext, ResourceAccessor resourceAccessor) { - Map<String, String> configuration = topiaApplicationContext.getConfiguration(); - String url = configuration.get(TopiaConfigurationConstants.CONFIG_URL); - String user = configuration.get(TopiaConfigurationConstants.CONFIG_USER); - String password = configuration.get(TopiaConfigurationConstants.CONFIG_PASS); + TopiaConfiguration configuration = topiaApplicationContext.getConfiguration(); + String url = configuration.getJdbcConnectionUrl(); + String user = configuration.getJdbcConnectionUser(); + String password = configuration.getJdbcConnectionPassword(); try { Database database = DatabaseFactory.getInstance().openDatabase(url, user, password, resourceAccessor); return database; diff --git a/topia-service-migration/src/main/java/org/nuiton/topia/migration/TopiaMigrationEngine.java b/topia-service-migration/src/main/java/org/nuiton/topia/migration/TopiaMigrationEngine.java index 5de5206..cbde69f 100644 --- a/topia-service-migration/src/main/java/org/nuiton/topia/migration/TopiaMigrationEngine.java +++ b/topia-service-migration/src/main/java/org/nuiton/topia/migration/TopiaMigrationEngine.java @@ -26,7 +26,6 @@ package org.nuiton.topia.migration; import com.google.common.base.Function; import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -36,6 +35,7 @@ import org.hibernate.cfg.Environment; import org.nuiton.topia.migration.mappings.TMSVersion; import org.nuiton.topia.migration.mappings.TMSVersionHibernateDao; import org.nuiton.topia.persistence.TopiaApplicationContext; +import org.nuiton.topia.persistence.TopiaConfiguration; import org.nuiton.topia.persistence.TopiaConfigurationConstants; import org.nuiton.topia.persistence.TopiaException; import org.nuiton.topia.persistence.TopiaMigrationServiceException; @@ -188,12 +188,6 @@ public class TopiaMigrationEngine implements TopiaMigrationService { //-------------------------------------------------------------------------- @Override - public Class<?>[] getPersistenceClasses() { - // TMSVersion class is not part of the application - return null; - } - - @Override public void initTopiaService(TopiaApplicationContext topiaApplicationContext, Map<String, String> serviceConfiguration) { Properties config = new Properties(); @@ -634,15 +628,16 @@ public class TopiaMigrationEngine implements TopiaMigrationService { * @since 2.5.3 */ protected static Configuration createTMSHibernateConfiguration(TopiaApplicationContext appContext) { - ImmutableMap<String, String> applicationConfig = appContext.getConfiguration(); + + TopiaConfiguration topiaConfiguration = appContext.getConfiguration(); Properties prop = new Properties(); - copyIfExists(applicationConfig, prop, Environment.URL); - copyIfExists(applicationConfig, prop, Environment.USER); - copyIfExists(applicationConfig, prop, Environment.PASS); - copyIfExists(applicationConfig, prop, Environment.DRIVER); - copyIfExists(applicationConfig, prop, Environment.DIALECT); + prop.put(Environment.URL, topiaConfiguration.getJdbcConnectionUrl()); + prop.put(Environment.USER, topiaConfiguration.getJdbcConnectionUser()); + prop.put(Environment.PASS, topiaConfiguration.getJdbcConnectionPassword()); + prop.put(Environment.DRIVER, topiaConfiguration.getJdbcDriverClassName()); + prop.put(Environment.DIALECT, HibernateProvider.getHibernateDialect(topiaConfiguration)); Configuration result = new Configuration(); result.setProperties(prop); @@ -651,12 +646,6 @@ public class TopiaMigrationEngine implements TopiaMigrationService { return result; } - protected static void copyIfExists(Map<String, String> from, Properties to, String propertyName) { - if (from.containsKey(propertyName)) { - to.put(propertyName, from.get(propertyName)); - } - } - @Override public void close() { // nothing to do diff --git a/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationServiceImpl.java b/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationServiceImpl.java index 43b6861..0a6b98a 100644 --- a/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationServiceImpl.java +++ b/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationServiceImpl.java @@ -66,12 +66,6 @@ public class TopiaReplicationServiceImpl implements TopiaReplicationService { //-------------------------------------------------------------------------- @Override - public Class<?>[] getPersistenceClasses() { - // pas de classes persistentes pour ce service - return null; - } - - @Override public void initTopiaService(TopiaApplicationContext topiaApplicationContext, Map<String, String> serviceConfiguration) { if ( ! serviceConfiguration.isEmpty()) { diff --git a/topia-templates/src/main/java/org/nuiton/topia/templates/ApplicationContextTransformer.java b/topia-templates/src/main/java/org/nuiton/topia/templates/ApplicationContextTransformer.java index d561600..a397921 100644 --- a/topia-templates/src/main/java/org/nuiton/topia/templates/ApplicationContextTransformer.java +++ b/topia-templates/src/main/java/org/nuiton/topia/templates/ApplicationContextTransformer.java @@ -40,6 +40,7 @@ import org.nuiton.topia.persistence.internal.AbstractTopiaPersistenceContextCons import org.nuiton.topia.persistence.util.EntityOperator; import java.util.Properties; +import java.util.Set; /** * To generate PersistenceHelper @@ -209,7 +210,8 @@ public class ApplicationContextTransformer extends ObjectModelTransformerToJava ); // getImplementationClasses method - op = addOperation(output, "getImplementationClasses", "Class<? extends TopiaEntity>[]", ObjectModelJavaModifier.PUBLIC); + addImport(output, Set.class); + op = addOperation(output, "getImplementationClasses", "Set<Class<? extends TopiaEntity>>", ObjectModelJavaModifier.PUBLIC); addAnnotation(output, op, Override.class); setOperationBody(op, "" /*{ diff --git a/topia-templates/src/main/java/org/nuiton/topia/templates/EntityEnumTransformer.java b/topia-templates/src/main/java/org/nuiton/topia/templates/EntityEnumTransformer.java index d1e848f..549d415 100644 --- a/topia-templates/src/main/java/org/nuiton/topia/templates/EntityEnumTransformer.java +++ b/topia-templates/src/main/java/org/nuiton/topia/templates/EntityEnumTransformer.java @@ -24,13 +24,9 @@ package org.nuiton.topia.templates; * #L% */ -import java.lang.reflect.Array; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -42,18 +38,21 @@ import org.nuiton.eugene.models.object.ObjectModelEnumeration; import org.nuiton.eugene.models.object.ObjectModelJavaModifier; import org.nuiton.eugene.models.object.ObjectModelOperation; import org.nuiton.eugene.models.object.xml.ObjectModelAttributeImpl; -import org.nuiton.topia.persistence.TopiaEntityEnumProvider; -import org.nuiton.topia.persistence.TopiaException; import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.topia.persistence.TopiaEntityEnum; +import org.nuiton.topia.persistence.TopiaException; import org.nuiton.topia.persistence.util.EntityOperator; import org.nuiton.topia.persistence.util.EntityOperatorStore; - -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; import org.nuiton.topia.persistence.util.TopiaEntityHelper; +import java.lang.reflect.Array; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + /*{generator option: parentheses = false}*/ /*{generator option: writeString = +}*/ @@ -433,15 +432,16 @@ public class EntityEnumTransformer extends ObjectModelTransformerToJava { }*/ ); + addImport(entityEnum, LinkedHashSet.class); // getImplementationClasses method - op = addOperation(entityEnum, "getImplementationClasses", "Class<? extends TopiaEntity>[]", + op = addOperation(entityEnum, "getImplementationClasses", "Set<Class<? extends TopiaEntity>>", ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC); setOperationBody(op, "" /*{ <%=entityEnumName%>[] values = values(); - Class<? extends TopiaEntity>[] result = (Class<? extends TopiaEntity>[]) Array.newInstance(Class.class, values.length); + Set<Class<? extends TopiaEntity>> result = new LinkedHashSet<Class<? extends TopiaEntity>>(); for (int i = 0; i < values.length; i++) { - result[i] = values[i].getImplementation(); + result.add(values[i].getImplementation()); } return result; }*/ -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.