Index: topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationService.java diff -u topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationService.java:1.1 topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationService.java:1.2 --- topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationService.java:1.1 Mon Apr 2 14:24:37 2007 +++ topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationService.java Wed Nov 14 17:36:11 2007 @@ -19,6 +19,7 @@ package org.codelutin.topia.migration; import org.codelutin.topia.framework.TopiaService; +import org.codelutin.topia.migration.callback.MigrationCallbackHandler; import org.hibernate.cfg.Configuration; /** @@ -28,62 +29,71 @@ * @author Chevallereau Benjamin * @author Eon Sébastien * @author Trève Vincent - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ * - * Last update : $Date: 2007-04-02 14:24:37 $ + * Last update : $Date: 2007-11-14 17:36:11 $ */ public interface TopiaMigrationService extends TopiaService { + /** + * Nom du service + */ 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(); + public String getConfigurationFile(); /** * Modifie le fichier de configuration * @param configurationFile Chemin du fichier de configuration d'hibernate */ - public abstract void setConfigurationFile(String configurationFile); + public void setConfigurationFile(String configurationFile); /** * Retourne la configuration * @return la configuration * @see org.hibernate.cfg.Configuration */ - public abstract Configuration getConfiguration(); + public Configuration getConfiguration(); /** * Renseigne la configuration * @param configuration la configuration * @see org.hibernate.cfg.Configuration */ - public abstract void setConfiguration(Configuration configuration); + public void setConfiguration(Configuration configuration); /** * Retourne le repertoire des anciens schemas * @return Le repertoire des anciens schemas */ - public abstract String getMappingsDirectory(); + public 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); + public void setMappingsDirectory(String mappingsDirectory); /** * Change la version courante * @param version la version */ - public abstract void setApplicationVersion(String version); + public void setApplicationVersion(String version); /** + * Ajoute un callbackhandler pour la migration + */ + public void addMigrationCallbackHandler(MigrationCallbackHandler callbackHandler); + + /** * Migrate the schema * + * @return true si la migration a ete effectuee et s'est bien passee, false sinon * @throws TopiaMigrationServiceException dans le cas ou le schema ne peut pas etre mis a jour */ - public abstract void migrateSchema() throws TopiaMigrationServiceException; + public boolean migrateSchema() throws TopiaMigrationServiceException; } \ No newline at end of file Index: topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationServiceImpl.java diff -u topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationServiceImpl.java:1.7 topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationServiceImpl.java:1.8 --- topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationServiceImpl.java:1.7 Fri Nov 9 16:35:45 2007 +++ topia-service/src/java/org/codelutin/topia/migration/TopiaMigrationServiceImpl.java Wed Nov 14 17:36:11 2007 @@ -21,6 +21,7 @@ import java.io.File; import java.net.URL; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; @@ -33,6 +34,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codelutin.topia.framework.TopiaContextImplementor; +import org.codelutin.topia.migration.callback.MigrationCallbackHandler; import org.codelutin.topia.migration.common.Version; import org.codelutin.topia.migration.kernel.ConfigurationAdapter; import org.codelutin.topia.migration.kernel.ConfigurationHelper; @@ -47,46 +49,52 @@ * * @author Chatellier Eric * @author Chevallereau Benjamin - * @author Eon Sébastien - * @author Trève Vincent - * @version $Revision: 1.7 $ + * @author Eon S�bastien + * @author Tr�ve Vincent + * @version $Revision: 1.8 $ * - * Last update : $Date: 2007-11-09 16:35:45 $ + * Last update : $Date: 2007-11-14 17:36:11 $ */ 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_PREVIOUS_MODEL_NAME = "topia.service.migration.modelnames"; + static public final String MIGRATION_APPLICATION_VERSION = "topia.service.migration.version"; + static public final String MIGRATION_PREVIOUS_MAPPING_DIRECTORY = "topia.service.migration.mappingsdir"; + static public final String MIGRATION_MODEL_NAMES = "topia.service.migration.modelnames"; + static public final String MIGRATION_CALLBACKHANDLERS = "topia.service.migration.callbackhandlers"; /** * C'est la meme, mais ca vire des dependances */ - static final private String TOPIA_PERSISTENCE_DIRECTORIES = "topia.persistence.directories"; - static final private String TOPIA_PERSISTENCE_CLASSES = "topia.persistence.classes"; + static final protected String TOPIA_PERSISTENCE_DIRECTORIES = "topia.persistence.directories"; + static final protected String TOPIA_PERSISTENCE_CLASSES = "topia.persistence.classes"; /** * Nom courant du fichier de configuration. */ - private String currentHibernateConfigurationFile; + protected String currentHibernateConfigurationFile; /** * Configuration hibernate courante utilisee par l'application */ - private Configuration currentApplicationConfiguration; + protected Configuration currentApplicationConfiguration; /** * Chemin du dossier contenant les schema de touts les versions */ - private String mappingsDirectory; + protected String mappingsDirectory; /** * Version courante de l'application */ - private Version currentApplicationVersion; + protected Version currentApplicationVersion; + + /** + * CallbackHandler list + */ + protected List migrationCallBackHandlers; /** * Logger (common-logging) @@ -106,16 +114,28 @@ currentHibernateConfigurationFile = null; // init configuration currentApplicationConfiguration = null; + + // init callbask list + migrationCallBackHandlers = new LinkedList(); } + /* (non-Javadoc) + * @see org.codelutin.topia.framework.TopiaService#getPersistenceClasses() + */ public Class [] getPersistenceClasses() { return null; } + /* (non-Javadoc) + * @see org.codelutin.topia.framework.TopiaService#getServiceName() + */ public String getServiceName() { return TopiaMigrationService.SERVICE_NAME; } + /* (non-Javadoc) + * @see org.codelutin.topia.framework.TopiaService#preInit(org.codelutin.topia.framework.TopiaContextImplementor) + */ public void preInit(TopiaContextImplementor context) { Properties config = context.getConfig(); @@ -182,6 +202,33 @@ } + // ajout des callbackhandlers + String callbackHandlers = config.getProperty(MIGRATION_CALLBACKHANDLERS,""); + + String[] tabCallbackHandlers = callbackHandlers.split(","); + for(String callbackHandler : tabCallbackHandlers) { + callbackHandler = callbackHandler.trim(); + if (!"".equals(callbackHandler)) { + Class clazz; + try { + clazz = (Class)Class.forName(callbackHandler); + MigrationCallbackHandler instance = clazz.newInstance(); + addMigrationCallbackHandler(instance); + } catch (ClassNotFoundException e) { + logger.error( + "CallbackHandler Class " + callbackHandler + + " not found",e); + } catch (InstantiationException e) { + logger.error( + "CallbackHandler class " + callbackHandler + + " cannot be instanciated",e); + } catch (IllegalAccessException e) { + logger.error( + "CallbackHandler class " + callbackHandler + + " cannot be accessed",e); + } + } + } // test mappingdir null @@ -194,7 +241,7 @@ if(applicationversion != null) { // effectue la migration de tous les modeles String modelnamesList = config.getProperty( - MIGRATION_PREVIOUS_MODEL_NAME, ""); + MIGRATION_MODEL_NAMES, ""); String[] modelnames = modelnamesList.split(","); for(String modelname : modelnames) { @@ -212,6 +259,9 @@ } } + /* (non-Javadoc) + * @see org.codelutin.topia.framework.TopiaService#postInit(org.codelutin.topia.framework.TopiaContextImplementor) + */ public void postInit(TopiaContextImplementor context) { } @@ -265,10 +315,18 @@ currentApplicationVersion = new Version(version); } + /* (non-Javadoc) + * @see org.codelutin.topia.migration.TopiaMigrationService#addMigrationCallbackHandler(org.codelutin.topia.migration.callback.MigrationCallbackHandler) + */ + public void addMigrationCallbackHandler( + MigrationCallbackHandler callbackHandler) { + migrationCallBackHandlers.add(callbackHandler); + } + /** * Charge la configuration locale si elle n'est pas deja ete fournit */ - private void loadApplicationConfiguration() { + protected void loadApplicationConfiguration() { // configuration pas deja fournit if(this.currentApplicationConfiguration == null) { @@ -297,8 +355,13 @@ /* (non-Javadoc) * @see org.codelutin.topia.migration.TopiaMigrationService#migrateSchema() */ - public void migrateSchema() throws TopiaMigrationServiceException { + public boolean migrateSchema() throws TopiaMigrationServiceException { + /*temp*/long timeBegin = System.currentTimeMillis(); + + // return flag + boolean schemaMigrated = false; + // log logger.info("Starting Topia Migration Service"); @@ -338,11 +401,33 @@ } logger.info("Application version : " + currentApplicationVersion.getVersion() + ", database version : " + vdbVersion.getVersion()); - + + /*temp*/long timeEnd = System.currentTimeMillis(); + + /*temp*/logger.error("[Time] get db version took : " + (timeEnd - timeBegin) + " ms"); + + // ask handler for migration + boolean doMigration; // vdbVersion < currentApplicationVersion if(vdbVersion.compareTo(currentApplicationVersion) < 0) { + logger.info("Database need update"); + + doMigration = askHandlerForMigration(vdbVersion.getVersion(),currentApplicationVersion.getVersion()); + + schemaMigrated = doMigration; + } + else { + doMigration = false; + schemaMigrated = true; // normal behaviour + logger.info("Database is up to date, no migration needed."); + } + + // si la migration doit etre faite + if(doMigration) { - logger.info("Database need update"); + /*temp*/timeBegin = System.currentTimeMillis(); + + logger.info("Database need update"); // ici, on charge toutes les configuration, entre >= vdbVersion et < currentApplicationVersion Map mVersionAndConfigurationMap = loadOldConfigurations(vdbVersion); @@ -432,21 +517,42 @@ // all done logger.info("All done, migration complete"); - } - else { - logger.info("Database is up to date, exiting."); + /*temp*/timeEnd = System.currentTimeMillis(); + /*temp*/logger.error("[Time] migration took : " + (timeEnd - timeBegin) + " ms"); + } // ferme la connexion a la base dbManager.disconnect(); + + return schemaMigrated; } /** + * Ask handler for migration. + * + * Return true if all handler return true, or if there is no handler + * + * @return true or false + */ + protected boolean askHandlerForMigration(String databaseVersion, String applicationVersion) { + + // true par defaut, s'il n'y a pas de handlers + boolean result = true; + + for(MigrationCallbackHandler callback : migrationCallBackHandlers) { + result &= callback.doMigration(databaseVersion, applicationVersion); + } + + return result; + } + + /** * 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) { + protected Map loadOldConfigurations(Version vdbVersion) { // schema des noms de dossier de version final Pattern pattern = Pattern.compile(mappingsDirectory + File.separator + "([0-9]+(\\.[0-9]+)*)");