Index: topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationServiceException.java diff -u /dev/null topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationServiceException.java:1.1 --- /dev/null Mon Apr 2 14:24:42 2007 +++ topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationServiceException.java Mon Apr 2 14:24:37 2007 @@ -0,0 +1,70 @@ +/* *##% + * Copyright (C) 2007 Code Lutin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.codelutin.topia.migration; + +/** + * TopiaMigrationServiceException.java + * + * @author Chatellier Eric + * @author Chevallereau Benjamin + * @author Eon Sébastien + * @author Trève Vincent + * @version $Revision: 1.1 $ + * + * Last update : $Date: 2007/04/02 14:24:37 $ + */ +public class TopiaMigrationServiceException extends Exception { + + /** + * Version + */ + private static final long serialVersionUID = -8900901171551405745L; + + /** + * Constructeur par defaut + */ + public TopiaMigrationServiceException() { + super(); + } + + /** + * Constructeur avec message + * @param message Le message d'erreur + */ + public TopiaMigrationServiceException(String message) { + super(message); + } + + /** + * Constructeur avec message et exception + * @param message Le message d'erreur + * @param exception l'exception + */ + public TopiaMigrationServiceException(String message, Throwable exception) { + super(message, exception); + } + + /** + * Constructeur avec exception + * @param exception l'exception + */ + public TopiaMigrationServiceException(Throwable exception) { + super(exception); + } +} Index: topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationService.java diff -u /dev/null topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationService.java:1.1 --- /dev/null Mon Apr 2 14:24:42 2007 +++ topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationService.java Mon Apr 2 14:24:37 2007 @@ -0,0 +1,89 @@ +/* *##% + * Copyright (C) 2007 Code Lutin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.codelutin.topia.migration; + +import org.codelutin.topia.framework.TopiaService; +import org.hibernate.cfg.Configuration; + +/** + * TopiaMigrationService.java + * + * @author Chatellier Eric + * @author Chevallereau Benjamin + * @author Eon Sébastien + * @author Trève Vincent + * @version $Revision: 1.1 $ + * + * Last update : $Date: 2007/04/02 14:24:37 $ + */ +public interface TopiaMigrationService extends TopiaService { + + public static final String SERVICE_NAME = "migration"; + + /** + * Renvoie le chemin du ficier de configuration utilise + * @return Chemin du fichier de configuration + */ + public abstract String getConfigurationFile(); + + /** + * Modifie le fichier de configuration + * @param configurationFile Chemin du fichier de configuration d'hibernate + */ + public abstract void setConfigurationFile(String configurationFile); + + /** + * Retourne la configuration + * @return la configuration + * @see org.hibernate.cfg.Configuration + */ + public abstract Configuration getConfiguration(); + + /** + * Renseigne la configuration + * @param configuration la configuration + * @see org.hibernate.cfg.Configuration + */ + public abstract void setConfiguration(Configuration configuration); + + /** + * Retourne le repertoire des anciens schemas + * @return Le repertoire des anciens schemas + */ + public abstract String getMappingsDirectory(); + + /** + * Modifie le chemin du dossier des anciens schemas + * @param mappingsDirectory Le chemin du dossier des anciens schemas + */ + public abstract void setMappingsDirectory(String mappingsDirectory); + + /** + * Change la version courante + * @param version la version + */ + public abstract void setApplicationVersion(String version); + + /** + * Migrate the schema + * + * @throws TopiaMigrationServiceException dans le cas ou le schema ne peut pas etre mis a jour + */ + public abstract void migrateSchema() throws TopiaMigrationServiceException; +} \ No newline at end of file Index: topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationServiceImpl.java diff -u /dev/null topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationServiceImpl.java:1.1 --- /dev/null Mon Apr 2 14:24:43 2007 +++ topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationServiceImpl.java Mon Apr 2 14:24:37 2007 @@ -0,0 +1,437 @@ +/* *##% + * Copyright (C) 2007 Code Lutin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.codelutin.topia.migration; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.topia.framework.TopiaContextImplementor; +import org.codelutin.topia.migration.common.Version; +import org.codelutin.topia.migration.kernel.ConfigurationAdapter; +import org.codelutin.topia.migration.kernel.ConfigurationHelper; +import org.codelutin.topia.migration.kernel.Transformer; +import org.hibernate.cfg.Configuration; + +/** + * TopiaMigrationServiceImpl.java + * + * Classe principale du projet. + * + * @author Chatellier Eric + * @author Chevallereau Benjamin + * @author Eon Sébastien + * @author Trève Vincent + * @version $Revision: 1.1 $ + * + * Last update : $Date: 2007/04/02 14:24:37 $ + */ +public class TopiaMigrationServiceImpl implements TopiaMigrationService { + + /** + * Nom des proprietes + */ + static private final String MIGRATION_APPLICATION_VERSION = "topia.service.migration.version"; + static private final String MIGRATION_PREVIOUS_MAPPING_DIRECTORY = "topia.service.migration.mappingsdir"; + static private final String MIGRATION_HIBERNATE_CONFIGURATION_FILE = "topia.service.migration.hibernateconfigfile"; + + /** + * Nom courant du fichier de configuration. + */ + private String currentHibernateConfigurationFile; + + /** + * Configuration hibernate courante utilisee par l'application + */ + private Configuration currentApplicationConfiguration; + + /** + * Chemin du dossier contenant les schema de touts les versions + */ + private String mappingsDirectory; + + /** + * Version courante de l'application + */ + private Version currentApplicationVersion; + + /** + * Logger (common-logging) + */ + private static Log logger = LogFactory.getLog(TopiaMigrationServiceImpl.class); + + /** + * Constructeur vide. + * + * Visibilite package (contruite par la factory). + * + */ + public TopiaMigrationServiceImpl() { + super(); + + // init the configuration file + currentHibernateConfigurationFile = null; + // init configuration + currentApplicationConfiguration = null; + } + + public Class [] getPersistenceClasses() { + return null; + } + + public String getServiceName() { + return TopiaMigrationService.SERVICE_NAME; + } + + public void preInit(TopiaContextImplementor context) { + // FIXME verifier la version et migrer si necessaire + Properties config = context.getConfig(); + + String hibernateconfigfile = config.getProperty(MIGRATION_HIBERNATE_CONFIGURATION_FILE, null); + String mappingdir = config.getProperty(MIGRATION_PREVIOUS_MAPPING_DIRECTORY, null); + String applicationversion = config.getProperty(MIGRATION_APPLICATION_VERSION, null); + + // MIGRATION_HIBERNATE_CONFIGURATION_FILE est facultatif + // version et mapping non + + if(hibernateconfigfile!=null) { + this.setConfigurationFile(hibernateconfigfile); + } + + // test version null + if(applicationversion == null) { + logger.error("'" + MIGRATION_APPLICATION_VERSION +"' not set."); + } + else { + this.setApplicationVersion(applicationversion); + } + + // test mappingdir null + if(mappingdir == null) { + logger.error("'" + MIGRATION_PREVIOUS_MAPPING_DIRECTORY +"' not set."); + } + else { + this.setMappingsDirectory(mappingdir); + } + + if(applicationversion != null && mappingdir != null) { + try { + // migration + migrateSchema(); + } + catch(TopiaMigrationServiceException e) { + logger.error("Can't migrate schema", e); + } + } + } + + public void postInit(TopiaContextImplementor context) { + + } + + /* (non-Javadoc) + * @see org.codelutin.topia.migration.TopiaMigrationService#getConfigurationFile() + */ + public String getConfigurationFile() { + return currentHibernateConfigurationFile; + } + + /* (non-Javadoc) + * @see org.codelutin.topia.migration.TopiaMigrationService#setConfigurationFile(java.lang.String) + */ + public void setConfigurationFile(String hibernateConfigurationFile) { + this.currentHibernateConfigurationFile = hibernateConfigurationFile; + } + + /* (non-Javadoc) + * @see org.codelutin.topia.migration.TopiaMigrationService#getConfiguration() + */ + public Configuration getConfiguration() { + return currentApplicationConfiguration; + } + + /* (non-Javadoc) + * @see org.codelutin.topia.migration.TopiaMigrationService#setConfiguration(org.hibernate.cfg.Configuration) + */ + public void setConfiguration(Configuration configuration) { + this.currentApplicationConfiguration = configuration; + } + + /* (non-Javadoc) + * @see org.codelutin.topia.migration.TopiaMigrationService#getMappingsDirectory() + */ + public String getMappingsDirectory() { + return mappingsDirectory; + } + + /* (non-Javadoc) + * @see org.codelutin.topia.migration.TopiaMigrationService#setMappingsDirectory(java.lang.String) + */ + public void setMappingsDirectory(String mappingsDirectory) { + this.mappingsDirectory = mappingsDirectory; + } + + /* (non-Javadoc) + * @see org.codelutin.topia.migration.TopiaMigrationService#setApplicationVersion(java.lang.String) + */ + public void setApplicationVersion(String version) { + currentApplicationVersion = new Version(version); + } + + /** + * Charge la configuration locale si elle n'est pas deja ete fournit + */ + private void loadApplicationConfiguration() { + + // configuration pas deja fournit + if(this.currentApplicationConfiguration == null) { + // creation + this.currentApplicationConfiguration = new Configuration(); + + if ( this.currentHibernateConfigurationFile != null ) { + logger.debug("Loading configuration file : " + this.currentHibernateConfigurationFile); + + // chargement via l'objet configuration dhibernate + currentApplicationConfiguration.configure(this.currentHibernateConfigurationFile); + } + else { + logger.debug("Loading configuration file : default hibernate configuration file"); + + // chargement via l'objet configuration dhibernate + currentApplicationConfiguration.configure(); + } + } + else { + // log + logger.debug("Configuration given, nothing to load"); + } + } + + /* (non-Javadoc) + * @see org.codelutin.topia.migration.TopiaMigrationService#migrateSchema() + */ + public void migrateSchema() throws TopiaMigrationServiceException { + + // log + logger.info("Starting Topia Migration Service"); + + // check that version is set + if(this.currentApplicationVersion == null) { + throw new TopiaMigrationServiceException("No version set"); + } + + // check that shema location is set + if(this.mappingsDirectory == null) { + throw new TopiaMigrationServiceException("No old mapping directory set"); + } + + // chargement de la configuration de l'application + loadApplicationConfiguration(); + + // initie un DatabaseManager + // fournit les propietes de connection a la base (properties) + DatabaseManager dbManager = new DatabaseManager(this.currentApplicationConfiguration.getProperties()); + + // recupere la version de la base + Version vdbVersion = dbManager.getDataBaseVersion(); + + // si la version n'a pas ete trouvee + if(vdbVersion == null) { + // la base dans ce cas n'est pas versionee. + // On dit que la version de la base est 0 + // et les schema de cette version 0 doivent + // etre detenu en local + vdbVersion = Version.VZERO; + + logger.info("Database version not found, so database schema is considered as V0"); + + // si la base n'etait pas versionnee, la table version n'existe pas + // creation + dbManager.createVersionTable(); + } + + logger.info("Application version : " + currentApplicationVersion.getVersion() + ", database version : " + vdbVersion.getVersion()); + + // vdbVersion < currentApplicationVersion + if(vdbVersion.compareTo(currentApplicationVersion) < 0) { + + logger.info("Database need update"); + + // ici, on charge toutes les configuration, entre >= vdbVersion et < currentApplicationVersion + Map mVersionAndConfigurationMap = loadOldConfigurations(vdbVersion); + + // Les configurationAdpater pour le kernel + SortedMap smVersionAndConfigurationAdapterMap = new TreeMap(); + + // les configurations sont chargees + // on doit : + // - pour la version vdbVersion, renommer les tables deja en base + // - pour les autres, creer les tables (suffixees avec la version) + + logger.debug("Set old database from old mappings"); + + // en meme temps, on construit les ConfigurationAdapter pour le noyau + for(Map.Entry entry : mVersionAndConfigurationMap.entrySet()) { + Version vVersion = entry.getKey(); + Configuration cConfiguration = entry.getValue(); + + //ConfigurationHelper.getConfigurationForVersion(v) + // ne positionne pas les properties parce qu'elle n'en a pas connaissance + // on les met ici + cConfiguration.setProperties(this.currentApplicationConfiguration.getProperties()); + + // renommage + if(vVersion.equals(vdbVersion)) { + // renomme les anciennes tables + dbManager.renameTables(cConfiguration,vVersion); + } + else { + dbManager.setCurrentOldRenamedMappingSchemaInDatabase(cConfiguration,vVersion); + } + + // on construit les ConfigurationAdpater + ConfigurationAdapter cfgAdpater = new ConfigurationAdapter(cConfiguration,vVersion); + smVersionAndConfigurationAdapterMap.put(vVersion, cfgAdpater); + } + + logger.debug("Creating new schema"); + + // enfin, il reste la configuration de l'application + // on va instancier le nouveau schema (le creer) + dbManager.setCurrentApplicationSchemaInDatabase(this.currentApplicationConfiguration); + + ConfigurationAdapter appCfgAdpater = new ConfigurationAdapter(this.currentApplicationConfiguration,this.currentApplicationVersion); + smVersionAndConfigurationAdapterMap.put(this.currentApplicationVersion, appCfgAdpater); + + logger.info("Data migration"); + // Ici, on a l'ancien schema renommé + // les schemas intermediaires creer et vides + // et le nouveau schema cree et vide + // on doit maintenant migrer les donnees + + // execute la transformation + Transformer trans = new Transformer(smVersionAndConfigurationAdapterMap); + + // migrate data + trans.execute(); + + // log + logger.info("Data migrated"); + + // Changement de la version en base + dbManager.putVersionInDatabase(currentApplicationVersion); + + logger.debug("Deleting old database"); + + // suppresion des anciennes tables de toutes les configuration, sauf + // currentApplicationVersion + // (elle n'est pas dans mVersionAndConfigurationMap) + for(Configuration cfg : mVersionAndConfigurationMap.values()) { + dbManager.removeTablesFromOldMapping(cfg); + } + + // il faudrait ici valider les transactions et fermer les sessions + // vmvManager a sa propre gestion des transactions/session + // this.remoteConfiguration doit en avoir ouverte + // this.localConfiguration aussi + + // all done + logger.info("All done, migration complete"); + + } + else { + logger.info("Database is up to date, exiting."); + } + + // ferme la connexion a la base + dbManager.disconnect(); + } + + /** + * Charge les configurations de version a partir de vdbVersion + * jusqu'a currentApplicationVersion "non compris" + * @param vdbVersion la version de depart + */ + private Map loadOldConfigurations(Version vdbVersion) { + // schema des noms de dossier de version + final Pattern pattern = Pattern.compile("V([0-9]+(\\.[0-9]+)*)"); + + // instancie la map ordonée + Map mVersionAndConfigurationMap = null; + + // parcourt du dossier mappingsDirectory + File mappingBaseDir = new File(mappingsDirectory); + + // pour tous les dossiers qui ont un nom genre "Vx" (x est une version) + File[] filesInIt = mappingBaseDir.listFiles(); + + if (filesInIt != null && filesInIt.length > 0) { + + mVersionAndConfigurationMap = new HashMap(); + + // ensemble ordonnée des version a charger apres + TreeSet tsEnsembleVersionACharger = new TreeSet(); + + for(File fileInIt : filesInIt) { + if(fileInIt.isDirectory()) { + Matcher matcher = pattern.matcher(fileInIt.getName()); + + if(matcher.find()) { + // group(1) est ce qui match entre le premeir niveau de parentheses + String sVersion = matcher.group(1); + //logger.debug("Directory " + fileInIt.getName() + " matches, version = " + sVersion); + + tsEnsembleVersionACharger.add(new Version(sVersion)); + } + } + } + + ConfigurationHelper cfgHelper = new ConfigurationHelper(); + + // charge les version qui conviennent + for(Version v : tsEnsembleVersionACharger) { + if(v.compareTo(vdbVersion) < 0) { + logger.debug("No load needed for version " + v.getVersion()); + } + else { + logger.debug("Loading mapping for version " + v.getVersion()); + + String mappingVersionDir = mappingsDirectory + "/V" + v.getVersion(); + + Configuration cfgForVersion = cfgHelper.getConfigurationInDirectory(mappingVersionDir); + mVersionAndConfigurationMap.put(v, cfgForVersion); + } + } + } + else { + logger.error("There is nothing in directory " + mappingBaseDir.getAbsolutePath() + "; can't load old mappings"); + } + + return mVersionAndConfigurationMap; + } + +} Index: topia-service/src/java/org/codelutin/topia/migration/DatabaseManager.java diff -u /dev/null topia-service/src/java/org/codelutin/topia/migration/DatabaseManager.java:1.1 --- /dev/null Mon Apr 2 14:24:43 2007 +++ topia-service/src/java/org/codelutin/topia/migration/DatabaseManager.java Mon Apr 2 14:24:37 2007 @@ -0,0 +1,346 @@ +/* *##% + * Copyright (C) 2007 Code Lutin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.codelutin.topia.migration; + +import java.util.Iterator; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.topia.migration.common.Version; +import org.codelutin.topia.migration.mappings.TMSVersion; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Environment; +import org.hibernate.exception.JDBCConnectionException; +import org.hibernate.exception.SQLGrammarException; +import org.hibernate.mapping.Table; +import org.hibernate.tool.hbm2ddl.SchemaExport; + +/** + * DatabaseManager.java + * + * Cette classe sert à acceder a la base, pour la version notement + * creer les schemas, renommer et supprimer les tables. + * + * @author Chatellier Eric + * @author Chevallereau Benjamin + * @author Eon Sébastien + * @author Trève Vincent + * @version $Revision: 1.1 $ + * + * Last update : $Date: 2007/04/02 14:24:37 $ + */ +public class DatabaseManager { + + /** + * Session factory + */ + private SessionFactory sessionFactory; + + /** + * Configuration pour se connecter a la base + * et manipuler la table version seulement + */ + private Configuration dbConfiguration; + + /** + * Logger (common-logging) + */ + private static Log logger = LogFactory.getLog(DatabaseManager.class); + + /** + * Suffix du nom des tables : _tms_v0 par exemple + */ + private static String VERSIONNED_TABLES_SUFFIX = "_tms_v"; + + /** + * Constructeur + * @param pInfosConnexion Properties hibernate + */ + public DatabaseManager(Properties pInfosConnexion) { + + // initie les proprietes + this.dbConfiguration = new Configuration(); + dbConfiguration.setProperties(pInfosConnexion); + + logger.debug("Configuration url : " + pInfosConnexion.getProperty(Environment.URL)); + logger.debug("Configuration driver : " + pInfosConnexion.getProperty(Environment.DRIVER)); + logger.debug("Configuration dialect : " + pInfosConnexion.getProperty(Environment.DIALECT)); + + // remplit la suite avec la liste de nos mappings... + logger.debug("Adding mappings for " + TMSVersion.class.getSimpleName()); + + // Hibernate will look for mapping files named + // /org/codelutin/migration/mappings/TMSVersion.hbm.xml in the classpath. + // This approach eliminates any hardcoded filenames. + dbConfiguration.addClass(TMSVersion.class); + + // retourne une session factory + sessionFactory = dbConfiguration.buildSessionFactory(); + } + + /** + * Retourne la version de la base + * @return la version present en base, ou null si la version ne peut pas etre determinee + */ + @SuppressWarnings("unchecked") + public Version getDataBaseVersion() throws TopiaMigrationServiceException { + Version version = null; + + logger.debug("Begin transaction to get version in database"); + + try { + // get session + Session session = sessionFactory.getCurrentSession(); + + // debut d'une transaction + session.beginTransaction(); + + // execute query + List result = (List)session.createCriteria(TMSVersion.class).list(); + if(result.size() == 1) { + version = new Version(result.get(0).getVersion().toString()); + logger.debug("Query executed, version found : " + version.getVersion()); + } + else { + logger.debug("Query executed, no version found"); + } + + // commit + session.getTransaction().commit(); + } + catch(JDBCConnectionException e) { + throw new TopiaMigrationServiceException("Connection to database refused, check your configuration !"); + } + catch(SQLGrammarException e) { + // si la table n'existe pas, on obtient une exception : base non versionnee + logger.debug("Exception on request : table not found"); + + // on retourn null + version = null; + } + + return version; + } + + /** + * Renomme les tables + * @param vdbVersion Version a ajouter + * @param oldConfiguration Configuration contenant le schema + */ + public void renameTables(Configuration oldConfiguration, Version vdbVersion) { + + logger.debug("Renaming tables in configuration and database for version " + vdbVersion.getVersion()); + + // get session + Session session = sessionFactory.getCurrentSession(); + + // debut d'une transaction + session.beginTransaction(); + + // DONE : voir si les relation *<->* sont listees par l'iterateur + // -> ok, normalement c bon, c gere + Iterator i = oldConfiguration.getTableMappings(); + while(i.hasNext()) { + Table table = (Table)i.next(); + + String tableName = table.getName(); + String newTableName = tableName + VERSIONNED_TABLES_SUFFIX + vdbVersion.getValidName(); + + // ALTER TABLE name RENAME TO newName + // marche normalement pour mysql, h2, postgres + + // TODO table existe pas + // TODO autre table existe deja + + logger.debug("Renaming table " + tableName + " to " + newTableName); + String sQuery = "ALTER TABLE " + tableName + " RENAME TO " + newTableName; + //logger.debug("Query : " + sQuery); + + SQLQuery sqlq = session.createSQLQuery(sQuery); + sqlq.executeUpdate(); + + // rennomage dans la config + table.setName(newTableName); + } + + // commit + session.getTransaction().commit(); + } + + /** + * + * @param oldConfiguration + * @param vdbVersion + */ + public void setCurrentOldRenamedMappingSchemaInDatabase(Configuration oldConfiguration, Version vdbVersion) { + + logger.debug("Renaming tables in configuration for version " + vdbVersion.getVersion()); + + // voir si les relation *<->* sont listees par l'iterateur + // -> ok, normalement c bon, c gere + Iterator i = oldConfiguration.getTableMappings(); + while(i.hasNext()) { + Table table = (Table)i.next(); + + String tableName = table.getName(); + String newTableName = tableName + VERSIONNED_TABLES_SUFFIX + vdbVersion.getValidName(); + + // rennomage dans la config + logger.debug("Renaming table " + tableName + " to " + newTableName); + table.setName(newTableName); + } + + // log + logger.debug("Creating schema for version " + vdbVersion.getVersion()); + createSchema(oldConfiguration); + // log + logger.debug("Schema created"); + } + + /** + * Creer le nouveau schema pour l'application + * @param newConfiguration la configuration contenant le nouveau schema + */ + public void setCurrentApplicationSchemaInDatabase(Configuration newConfiguration) { + + // log + logger.debug("Creating new schema"); + + createSchema(newConfiguration); + + // log + logger.debug("Schema created"); + } + + /** + * Creer un schema + * @param configuration la configuration contenant lae schema + */ + private void createSchema(Configuration configuration) { + // creer le schema en base + SchemaExport schemaExport = new SchemaExport(configuration); + schemaExport.create(false, true); + } + + /** + * Creer le schema pour la table "tms_version" + */ + public void createVersionTable() { + + logger.debug("Adding table to put version"); + + // creer le schema en base + // dans la configuration dbConfiguration, il n'y a que la table version + SchemaExport schemaExport = new SchemaExport(dbConfiguration); + schemaExport.create(false, true); + + logger.debug("Table for " + TMSVersion.class.getSimpleName() + " created"); + } + + /** + * Introduit la version du nouveau schema dans la base + * @throws TopiaMigrationServiceException + */ + @SuppressWarnings("unchecked") + public void putVersionInDatabase(Version nouvelleVersion) { + + // get session + Session session = sessionFactory.getCurrentSession(); + + // debut d'une transaction + session.beginTransaction(); + + logger.debug("Deleting existing versions"); + // supprime les versions existants + // au pire, on pourrait remplacer la premiere + // execute query + List lVersion = (List)session.createCriteria(TMSVersion.class).list(); + for(TMSVersion v : lVersion) { + logger.debug("Deleting version " + v.getVersion()); + + session.delete(v); + } + + // positionne la version + logger.debug("Setting database version to " + nouvelleVersion.getVersion()); + TMSVersion version = new TMSVersion(nouvelleVersion.getVersion()); + session.save(version); + + // commit + session.getTransaction().commit(); + } + + + /** + * Supprime les tables des l'ancien mapping + * + * ATTENTION : pour H2 apparement, les version anterieures à 'Version 1.0 / 2007-03-04' + * bug pour la suppression des tables (erreur de lock) + * + * Postgres gere les dépendances entres les tables + * il faut les supprimer dans l'ordre... + * + * @param oldConfiguration configuration contenant le schema + */ + public void removeTablesFromOldMapping(Configuration oldConfiguration) { + + logger.debug("Removing tables from old mapping"); + // get session + Session session = sessionFactory.getCurrentSession(); + + // debut d'une transaction + session.beginTransaction(); + + // les relations *<->* sont listees par l'iterateur + Iterator i = oldConfiguration.getTableMappings(); + while(i.hasNext()) { + Table table = (Table)i.next(); + + String tableName = table.getName(); + // en fait, le nom de la table dans la configuration est deja versionne + + // TODO table existe pas + logger.debug("Deleting table " + tableName); + String sQuery = "DROP TABLE " + tableName + " cascade"; + //logger.debug("Query : " + sQuery); + + // TODO utilsation des dialect pour etre sur d'avoir des requete correctes ? + + SQLQuery sqlq = session.createSQLQuery(sQuery); + sqlq.executeUpdate(); + } + + // commit + session.getTransaction().commit(); + } + + /** + * Se deconnecte + */ + public void disconnect() { + //nettoye + sessionFactory.getCurrentSession().close(); + sessionFactory.close(); + } +}