From 35c35b9d1cd90baf692779bf3bd3a4d738481f89 Mon Sep 17 00:00:00 2001 From: Robert von Burg Date: Sun, 8 Feb 2015 12:59:21 +0100 Subject: [PATCH] [New] Added new MigrationsHandler to migrate the model - Add the new MigrationsHandler as a StrolchComponent - add migrations/data//n.n.n.xml files - and your migration will run --- ch.eitchnet.utils | 2 +- .../li/strolch/migrations/DataMigration.java | 20 ----- .../java/li/strolch/migrations/Migration.java | 40 --------- .../persistence/api/AbstractTransaction.java | 7 +- .../li/strolch/migrations/MigrationsTest.java | 47 ---------- .../li/strolch/migrations/CodeMigration.java | 0 .../CurrentMigrationVersionQuery.java | 10 +-- .../li/strolch/migrations/DataMigration.java | 48 ++++++++++ .../java/li/strolch/migrations/Migration.java | 81 +++++++++++++++++ .../li/strolch/migrations/Migrations.java | 29 ++++-- .../strolch/migrations/MigrationsHandler.java | 89 +++++++++++++++++-- .../QueryCurrentVersionsAction.java | 0 .../migrations/RunMigrationsAction.java | 0 .../li/strolch/migrations/MigrationsTest.java | 67 ++++++++++++++ .../test/AbstractRealmServiceTest.java | 4 + .../migrationstest/config/PrivilegeConfig.xml | 0 .../migrationstest/config/PrivilegeModel.xml | 0 .../config/StrolchConfiguration.xml | 17 ++-- .../migrationstest/data/StrolchModel.xml | 0 .../migrations/data/defaultRealm/0.1.0.xml | 0 .../migrations/data/defaultRealm/0.1.1.xml | 0 .../migrations/data/defaultRealm/0.5.2.xml | 0 .../migrations/data/defaultRealm/1.0.0.xml | 0 .../migrations/data/defaultRealm/1.0.5.xml | 0 .../migrations/data/defaultRealm/1.1.1.xml | 0 25 files changed, 319 insertions(+), 142 deletions(-) delete mode 100644 li.strolch.agent/src/main/java/li/strolch/migrations/DataMigration.java delete mode 100644 li.strolch.agent/src/main/java/li/strolch/migrations/Migration.java delete mode 100644 li.strolch.agent/src/test/java/li/strolch/migrations/MigrationsTest.java rename {li.strolch.agent => li.strolch.service}/src/main/java/li/strolch/migrations/CodeMigration.java (100%) rename {li.strolch.agent => li.strolch.service}/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java (87%) create mode 100644 li.strolch.service/src/main/java/li/strolch/migrations/DataMigration.java create mode 100644 li.strolch.service/src/main/java/li/strolch/migrations/Migration.java rename {li.strolch.agent => li.strolch.service}/src/main/java/li/strolch/migrations/Migrations.java (90%) rename {li.strolch.agent => li.strolch.service}/src/main/java/li/strolch/migrations/MigrationsHandler.java (51%) rename {li.strolch.agent => li.strolch.service}/src/main/java/li/strolch/migrations/QueryCurrentVersionsAction.java (100%) rename {li.strolch.agent => li.strolch.service}/src/main/java/li/strolch/migrations/RunMigrationsAction.java (100%) create mode 100644 li.strolch.service/src/test/java/li/strolch/migrations/MigrationsTest.java rename {li.strolch.agent => li.strolch.service}/src/test/resources/migrationstest/config/PrivilegeConfig.xml (100%) rename {li.strolch.agent => li.strolch.service}/src/test/resources/migrationstest/config/PrivilegeModel.xml (100%) rename {li.strolch.agent => li.strolch.service}/src/test/resources/migrationstest/config/StrolchConfiguration.xml (69%) rename li.strolch.agent/src/test/resources/migrationstest/data/Model.xml => li.strolch.service/src/test/resources/migrationstest/data/StrolchModel.xml (100%) rename {li.strolch.agent => li.strolch.service}/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.1.0.xml (100%) rename {li.strolch.agent => li.strolch.service}/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.1.1.xml (100%) rename {li.strolch.agent => li.strolch.service}/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.5.2.xml (100%) rename {li.strolch.agent => li.strolch.service}/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.0.0.xml (100%) rename {li.strolch.agent => li.strolch.service}/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.0.5.xml (100%) rename {li.strolch.agent => li.strolch.service}/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.1.1.xml (100%) diff --git a/ch.eitchnet.utils b/ch.eitchnet.utils index d87517e4c..8861db850 160000 --- a/ch.eitchnet.utils +++ b/ch.eitchnet.utils @@ -1 +1 @@ -Subproject commit d87517e4c2a3e9507b2661cc1737031761d99b61 +Subproject commit 8861db85091eea43f06ed2a480360ba670d3c30e diff --git a/li.strolch.agent/src/main/java/li/strolch/migrations/DataMigration.java b/li.strolch.agent/src/main/java/li/strolch/migrations/DataMigration.java deleted file mode 100644 index 1e12a7e9b..000000000 --- a/li.strolch.agent/src/main/java/li/strolch/migrations/DataMigration.java +++ /dev/null @@ -1,20 +0,0 @@ -package li.strolch.migrations; - -import java.io.File; - -import li.strolch.agent.api.ComponentContainer; -import ch.eitchnet.privilege.model.Certificate; -import ch.eitchnet.utils.Version; - -public class DataMigration extends Migration { - - public DataMigration(String realm, Version version, File dataFile) { - super(realm, version, dataFile); - } - - @Override - public void migrate(ComponentContainer container, Certificate certificate) { - - logger.info("[" + this.realm + "] Running migration " + this.version); - } -} diff --git a/li.strolch.agent/src/main/java/li/strolch/migrations/Migration.java b/li.strolch.agent/src/main/java/li/strolch/migrations/Migration.java deleted file mode 100644 index 28feeab49..000000000 --- a/li.strolch.agent/src/main/java/li/strolch/migrations/Migration.java +++ /dev/null @@ -1,40 +0,0 @@ -package li.strolch.migrations; - -import java.io.File; - -import li.strolch.agent.api.ComponentContainer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.eitchnet.privilege.model.Certificate; -import ch.eitchnet.utils.Version; - -public abstract class Migration { - - protected static final Logger logger = LoggerFactory.getLogger(CodeMigration.class); - - protected final String realm; - protected final Version version; - protected final File dataFile; - - public Migration(String realm, Version version, File dataFile) { - this.realm = realm; - this.version = version; - this.dataFile = dataFile; - } - - public String getRealm() { - return realm; - } - - public Version getVersion() { - return version; - } - - public File getDataFile() { - return dataFile; - } - - public abstract void migrate(ComponentContainer container, Certificate certificate); -} diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java index 5e844e893..6fb2fd340 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java @@ -559,10 +559,11 @@ public abstract class AbstractTransaction implements StrolchTransaction { try { this.txResult.setState(TransactionState.CLOSING); + // TODO re-think this. if (!this.commands.isEmpty()) { - String msg = "Current close strategy {0} is readonly and thus does not support doing commands!"; - msg = MessageFormat.format(msg, this.closeStrategy); - throw fail(msg); + logger.error("There are commands registered on a read-only transaction. Changing to rollback! Probably due to an exception!"); + autoCloseableRollback(); + return; } long auditTrailDuration = writeAuditTrail(); diff --git a/li.strolch.agent/src/test/java/li/strolch/migrations/MigrationsTest.java b/li.strolch.agent/src/test/java/li/strolch/migrations/MigrationsTest.java deleted file mode 100644 index dee004885..000000000 --- a/li.strolch.agent/src/test/java/li/strolch/migrations/MigrationsTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package li.strolch.migrations; - -import static li.strolch.agent.ComponentContainerTest.destroyContainer; -import static li.strolch.agent.ComponentContainerTest.logger; -import static li.strolch.agent.ComponentContainerTest.startContainer; - -import java.util.Map; -import java.util.Map.Entry; - -import li.strolch.agent.api.StrolchAgent; -import li.strolch.runtime.privilege.PrivilegeHandler; - -import org.junit.Test; - -import ch.eitchnet.privilege.model.Certificate; -import ch.eitchnet.utils.Version; -import ch.eitchnet.utils.collections.MapOfLists; - -public class MigrationsTest { - - @Test - public void shouldRunMigrations() { - - try { - StrolchAgent agent = startContainer("target/MigrationsTest/", "src/test/resources/migrationstest"); - - PrivilegeHandler privilegeHandler = agent.getContainer().getPrivilegeHandler(); - Certificate cert = privilegeHandler.authenticate("test", "test".getBytes()); - - MigrationsHandler migrationsHandler = agent.getContainer().getComponent(MigrationsHandler.class); - Map currentVersions = migrationsHandler.getCurrentVersions(cert); - for (Entry entry : currentVersions.entrySet()) { - logger.info("[" + entry.getKey() + "] Current version: " + entry.getValue()); - } - - MapOfLists migrationsToRun = migrationsHandler.queryMigrationsToRun(cert); - for (String realm : migrationsToRun.keySet()) { - logger.info("[" + realm + "] Migrations to run: " + migrationsToRun.getList(realm)); - } - - destroyContainer(agent); - } catch (Exception e) { - logger.error(e.getMessage(), e); - throw e; - } - } -} diff --git a/li.strolch.agent/src/main/java/li/strolch/migrations/CodeMigration.java b/li.strolch.service/src/main/java/li/strolch/migrations/CodeMigration.java similarity index 100% rename from li.strolch.agent/src/main/java/li/strolch/migrations/CodeMigration.java rename to li.strolch.service/src/main/java/li/strolch/migrations/CodeMigration.java diff --git a/li.strolch.agent/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java b/li.strolch.service/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java similarity index 87% rename from li.strolch.agent/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java rename to li.strolch.service/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java index d0335d2d7..66c8613c8 100644 --- a/li.strolch.agent/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java @@ -1,5 +1,10 @@ package li.strolch.migrations; +import static li.strolch.migrations.Migration.BAG_PARAMETERS; +import static li.strolch.migrations.Migration.MIGRATIONS_ID; +import static li.strolch.migrations.Migration.MIGRATIONS_TYPE; +import static li.strolch.migrations.Migration.PARAM_CURRENT_VERSION; + import java.util.HashMap; import java.util.Map; @@ -14,11 +19,6 @@ import ch.eitchnet.utils.Version; public class CurrentMigrationVersionQuery { - public static final String MIGRATIONS_TYPE = "Migrations"; - public static final String MIGRATIONS_ID = "migrations"; - public static final String BAG_PARAMETERS = "parameters"; - public static final String PARAM_CURRENT_VERSION = "currentVersion"; - private ComponentContainer container; private Map currentVersions; diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/DataMigration.java b/li.strolch.service/src/main/java/li/strolch/migrations/DataMigration.java new file mode 100644 index 000000000..88049d65d --- /dev/null +++ b/li.strolch.service/src/main/java/li/strolch/migrations/DataMigration.java @@ -0,0 +1,48 @@ +package li.strolch.migrations; + +import java.io.File; +import java.text.MessageFormat; +import java.util.Collections; + +import li.strolch.agent.api.ComponentContainer; +import li.strolch.command.XmlImportModelCommand; +import li.strolch.exception.StrolchException; +import li.strolch.model.ModelStatistics; +import li.strolch.persistence.api.StrolchTransaction; +import ch.eitchnet.privilege.model.Certificate; +import ch.eitchnet.utils.Version; + +public class DataMigration extends Migration { + + public DataMigration(String realm, Version version, File dataFile) { + super(realm, version, dataFile); + } + + @Override + public void migrate(ComponentContainer container, Certificate certificate) { + + XmlImportModelCommand command; + try (StrolchTransaction tx = container.getRealm(getRealm()).openTx(certificate, DataMigration.class)) { + + command = new XmlImportModelCommand(container, tx); + command.setModelFile(getDataFile()); + command.setAddOrders(true); + command.setAddResources(true); + command.setUpdateOrders(true); + command.setUpdateResources(true); + command.setOrderTypes(Collections.emptySet()); + command.setResourceTypes(Collections.emptySet()); + + tx.addCommand(command); + tx.addCommand(buildMigrationVersionChangeCommand(container, tx)); + tx.commitOnClose(); + } catch (Exception e) { + String msg = MessageFormat.format("Migration of {0} failed due to {1}", getVersion(), e.getMessage()); + throw new StrolchException(msg, e); + } + + ModelStatistics statistics = command.getStatistics(); + logger.info(MessageFormat + .format("[{0}] Data migration for {1} loaded {2} Resources and {3} Orders.", getRealm(), getVersion(), statistics.nrOfResources, statistics.nrOfOrders)); //$NON-NLS-1$ + } +} diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/Migration.java b/li.strolch.service/src/main/java/li/strolch/migrations/Migration.java new file mode 100644 index 000000000..0f78aab3c --- /dev/null +++ b/li.strolch.service/src/main/java/li/strolch/migrations/Migration.java @@ -0,0 +1,81 @@ +package li.strolch.migrations; + +import java.io.File; + +import li.strolch.agent.api.ComponentContainer; +import li.strolch.command.AddResourceCommand; +import li.strolch.command.parameter.SetParameterCommand; +import li.strolch.model.ParameterBag; +import li.strolch.model.Resource; +import li.strolch.model.parameter.StringParameter; +import li.strolch.persistence.api.StrolchTransaction; +import li.strolch.service.api.Command; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.eitchnet.privilege.model.Certificate; +import ch.eitchnet.utils.Version; + +public abstract class Migration { + + public static final String MIGRATIONS_TYPE = "Migrations"; + public static final String MIGRATIONS_ID = "migrations"; + public static final String BAG_PARAMETERS = "parameters"; + public static final String PARAM_CURRENT_VERSION = "currentVersion"; + + protected static final Logger logger = LoggerFactory.getLogger(CodeMigration.class); + + protected final String realm; + protected final Version version; + protected final File dataFile; + + public Migration(String realm, Version version, File dataFile) { + this.realm = realm; + this.version = version; + this.dataFile = dataFile; + } + + public String getRealm() { + return realm; + } + + public Version getVersion() { + return version; + } + + public File getDataFile() { + return dataFile; + } + + protected Command buildMigrationVersionChangeCommand(ComponentContainer container, StrolchTransaction tx) { + + Resource migrationsRes = tx.getResourceBy(MIGRATIONS_TYPE, MIGRATIONS_ID); + if (migrationsRes == null) { + migrationsRes = new Resource(MIGRATIONS_ID, MIGRATIONS_TYPE, MIGRATIONS_TYPE); + + ParameterBag bag = new ParameterBag(BAG_PARAMETERS, BAG_PARAMETERS, BAG_PARAMETERS); + migrationsRes.addParameterBag(bag); + + StringParameter currentVersionP = new StringParameter(PARAM_CURRENT_VERSION, PARAM_CURRENT_VERSION, + getVersion().toString()); + bag.addParameter(currentVersionP); + + AddResourceCommand cmd = new AddResourceCommand(container, tx); + cmd.setResource(migrationsRes); + return cmd; + + } else { + + StringParameter currentVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_VERSION); + + SetParameterCommand cmd = new SetParameterCommand(container, tx); + cmd.setParameter(currentVersionP); + cmd.setValueAsString(getVersion().toString()); + + return cmd; + } + } + + public abstract void migrate(ComponentContainer container, Certificate certificate); +} diff --git a/li.strolch.agent/src/main/java/li/strolch/migrations/Migrations.java b/li.strolch.service/src/main/java/li/strolch/migrations/Migrations.java similarity index 90% rename from li.strolch.agent/src/main/java/li/strolch/migrations/Migrations.java rename to li.strolch.service/src/main/java/li/strolch/migrations/Migrations.java index aa752cd1e..942aa408f 100644 --- a/li.strolch.agent/src/main/java/li/strolch/migrations/Migrations.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/Migrations.java @@ -2,7 +2,6 @@ package li.strolch.migrations; import java.io.File; import java.io.FileFilter; -import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.SortedSet; @@ -24,18 +23,27 @@ public class Migrations { private ComponentContainer container; private Map currentVersions; + private boolean verbose; private SortedSet dataMigrations; private SortedSet codeMigrations; - private Map migrationsRan; + private MapOfLists migrationsRan; public Migrations(ComponentContainer container, Map currentVersions) { this.container = container; this.currentVersions = currentVersions; } - public Map getMigrationsRan() { + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + public boolean isVerbose() { + return verbose; + } + + public MapOfLists getMigrationsRan() { return this.migrationsRan; } @@ -49,12 +57,13 @@ public class Migrations { this.codeMigrations = loadCodeMigrations(this.currentVersions, migrationsPath); // log found migrations - logDetectedMigrations(this.currentVersions, this.dataMigrations, this.codeMigrations); + if (this.verbose) + logDetectedMigrations(this.currentVersions, this.dataMigrations, this.codeMigrations); } public void runMigrations(Certificate certificate) { - Map migrationsRan = new HashMap<>(); + MapOfLists migrationsRan = new MapOfLists<>(); for (Entry entry : this.currentVersions.entrySet()) { String realm = entry.getKey(); @@ -69,18 +78,24 @@ public class Migrations { if (!this.codeMigrations.isEmpty()) { for (CodeMigration migration : this.codeMigrations.tailSet(currentCodeMigration)) { migration.migrate(container, certificate); - migrationsRan.put(realm, migration.getVersion()); + migrationsRan.addElement(realm, migration.getVersion()); } } if (!this.dataMigrations.isEmpty()) { for (DataMigration migration : this.dataMigrations.tailSet(currentDataMigration)) { migration.migrate(container, certificate); - migrationsRan.put(realm, migration.getVersion()); + migrationsRan.addElement(realm, migration.getVersion()); } } } + if (migrationsRan.isEmpty()) { + logger.info("There were no migrations required!"); + } else { + logger.info("Migrated " + migrationsRan.size() + " realms!"); + } + this.migrationsRan = migrationsRan; } diff --git a/li.strolch.agent/src/main/java/li/strolch/migrations/MigrationsHandler.java b/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java similarity index 51% rename from li.strolch.agent/src/main/java/li/strolch/migrations/MigrationsHandler.java rename to li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java index c85333bb3..2c33f3312 100644 --- a/li.strolch.agent/src/main/java/li/strolch/migrations/MigrationsHandler.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java @@ -16,8 +16,10 @@ package li.strolch.migrations; import java.io.File; -import java.util.HashMap; import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.RealmHandler; @@ -34,17 +36,30 @@ import ch.eitchnet.utils.collections.MapOfLists; */ public class MigrationsHandler extends StrolchComponent { + private static final String PROP_VERBOSE = "verbose"; + private static final String PROP_POLL_MIGRATIONS = "pollMigrations"; + private static final String PROP_POLL_WAIT = "pollWait"; + private static final String PROP_RUN_MIGRATIONS_ON_START = "runMigrationsOnStart"; private static final String PATH_MIGRATIONS = "migrations"; + private boolean runMigrationsOnStart; + private boolean verbose; + private Migrations migrations; - private Map lastMigrations; + private MapOfLists lastMigrations; private File migrationsPath; + private Timer migrationTimer; + private boolean pollMigrations; + private int pollWait; + public MigrationsHandler(ComponentContainer container, String componentName) { super(container, componentName); } - public Map getLastMigrations() { + public MapOfLists getLastMigrations() { + if (this.lastMigrations == null) + return new MapOfLists<>(); return this.lastMigrations; } @@ -58,25 +73,29 @@ public class MigrationsHandler extends StrolchComponent { Map currentVersions = getCurrentVersions(cert); Migrations migrations = new Migrations(getContainer(), currentVersions); migrations.parseMigrations(this.migrationsPath); + migrations.setVerbose(this.verbose); this.migrations = migrations; return this.migrations.getMigrationsToRun(); } public void runMigrations(Certificate cert) { - this.lastMigrations.clear(); + queryMigrationsToRun(cert); this.migrations.runMigrations(cert); - this.lastMigrations.putAll(this.migrations.getMigrationsRan()); + this.lastMigrations = this.migrations.getMigrationsRan(); } @Override public void initialize(ComponentConfiguration configuration) { - this.lastMigrations = new HashMap<>(); + this.runMigrationsOnStart = configuration.getBoolean(PROP_RUN_MIGRATIONS_ON_START, Boolean.FALSE); + this.verbose = configuration.getBoolean(PROP_VERBOSE, Boolean.FALSE); + this.pollMigrations = configuration.getBoolean(PROP_VERBOSE, Boolean.FALSE); + this.pollWait = configuration.getInt(PROP_VERBOSE, 5); RuntimeConfiguration runtimeConf = configuration.getRuntimeConfiguration(); this.migrationsPath = runtimeConf.getDataDir(MigrationsHandler.class.getName(), PATH_MIGRATIONS, false); - if (this.migrationsPath.exists()) { + if (this.runMigrationsOnStart && this.migrationsPath.exists()) { CurrentMigrationVersionQuery query = new CurrentMigrationVersionQuery(getContainer()); PrivilegeHandler privilegeHandler = getContainer().getComponent(PrivilegeHandler.class); @@ -86,25 +105,77 @@ public class MigrationsHandler extends StrolchComponent { Migrations migrations = new Migrations(getContainer(), currentVersions); migrations.parseMigrations(this.migrationsPath); + migrations.setVerbose(this.verbose); this.migrations = migrations; } + if (this.pollMigrations) { + this.migrationTimer = new Timer("MigrationTimer", true); //$NON-NLS-1$ + long checkInterval = TimeUnit.MINUTES.toMillis(pollWait); + this.migrationTimer.schedule(new MigrationPollTask(), checkInterval, checkInterval); + } + super.initialize(configuration); } @Override public void start() { - if (this.migrations != null) { + if (this.runMigrationsOnStart && this.migrations != null) { PrivilegeHandler privilegeHandler = getContainer().getComponent(PrivilegeHandler.class); RunMigrationsAction action = new RunMigrationsAction(this.migrations); privilegeHandler.runAsSystem(RealmHandler.SYSTEM_USER_AGENT, action); - this.lastMigrations.putAll(this.migrations.getMigrationsRan()); + this.lastMigrations = this.migrations.getMigrationsRan(); } super.start(); } + + @Override + public void stop() { + + if (this.migrationTimer != null) { + this.migrationTimer.cancel(); + } + + this.migrationTimer = null; + + super.stop(); + } + + /** + * Simpler {@link TimerTask} to check for sessions which haven't been active for + * {@link DefaultStrolchSessionHandler#PARAM_SESSION_TTL_MINUTES} minutes. + * + * @author Robert von Burg + */ + private class MigrationPollTask extends TimerTask { + + @Override + public void run() { + + CurrentMigrationVersionQuery query = new CurrentMigrationVersionQuery(getContainer()); + PrivilegeHandler privilegeHandler = getContainer().getComponent(PrivilegeHandler.class); + QueryCurrentVersionsAction queryAction = new QueryCurrentVersionsAction(query); + privilegeHandler.runAsSystem(RealmHandler.SYSTEM_USER_AGENT, queryAction); + Map currentVersions = query.getCurrentVersions(); + + Migrations migrations = new Migrations(getContainer(), currentVersions); + migrations.parseMigrations(MigrationsHandler.this.migrationsPath); + migrations.setVerbose(MigrationsHandler.this.verbose); + + MigrationsHandler.this.migrations = migrations; + + if (migrations.getMigrationsToRun().isEmpty()) { + logger.info("There are no migrations required at the moment!"); + } else { + RunMigrationsAction runMigrationsAction = new RunMigrationsAction(MigrationsHandler.this.migrations); + privilegeHandler.runAsSystem(RealmHandler.SYSTEM_USER_AGENT, runMigrationsAction); + MigrationsHandler.this.lastMigrations = MigrationsHandler.this.migrations.getMigrationsRan(); + } + } + } } diff --git a/li.strolch.agent/src/main/java/li/strolch/migrations/QueryCurrentVersionsAction.java b/li.strolch.service/src/main/java/li/strolch/migrations/QueryCurrentVersionsAction.java similarity index 100% rename from li.strolch.agent/src/main/java/li/strolch/migrations/QueryCurrentVersionsAction.java rename to li.strolch.service/src/main/java/li/strolch/migrations/QueryCurrentVersionsAction.java diff --git a/li.strolch.agent/src/main/java/li/strolch/migrations/RunMigrationsAction.java b/li.strolch.service/src/main/java/li/strolch/migrations/RunMigrationsAction.java similarity index 100% rename from li.strolch.agent/src/main/java/li/strolch/migrations/RunMigrationsAction.java rename to li.strolch.service/src/main/java/li/strolch/migrations/RunMigrationsAction.java diff --git a/li.strolch.service/src/test/java/li/strolch/migrations/MigrationsTest.java b/li.strolch.service/src/test/java/li/strolch/migrations/MigrationsTest.java new file mode 100644 index 000000000..094e141f9 --- /dev/null +++ b/li.strolch.service/src/test/java/li/strolch/migrations/MigrationsTest.java @@ -0,0 +1,67 @@ +package li.strolch.migrations; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import li.strolch.runtime.StrolchConstants; +import li.strolch.runtime.privilege.PrivilegeHandler; +import li.strolch.testbase.runtime.RuntimeMock; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import ch.eitchnet.privilege.model.Certificate; +import ch.eitchnet.utils.Version; +import ch.eitchnet.utils.collections.MapOfLists; + +public class MigrationsTest { + + public static final String RUNTIME_PATH = "target/migrationstest/"; //$NON-NLS-1$ + public static final String CONFIG_SRC = "src/test/resources/migrationstest"; //$NON-NLS-1$ + + protected static RuntimeMock runtimeMock; + protected static Certificate certificate; + + @BeforeClass + public static void beforeClass() throws Exception { + + File rootPath = new File(RUNTIME_PATH); + File configSrc = new File(CONFIG_SRC); + runtimeMock = new RuntimeMock(); + runtimeMock.mockRuntime(rootPath, configSrc); + runtimeMock.startContainer(); + + certificate = runtimeMock.getPrivilegeHandler().authenticate("test", "test".getBytes()); + } + + @AfterClass + public static void afterClass() { + if (runtimeMock != null) + runtimeMock.destroyRuntime(); + } + + @Test + public void shouldRunMigrations() { + + PrivilegeHandler privilegeHandler = runtimeMock.getPrivilegeHandler(); + Certificate cert = privilegeHandler.authenticate("test", "test".getBytes()); + + MigrationsHandler migrationsHandler = runtimeMock.getContainer().getComponent(MigrationsHandler.class); + Map currentVersions = migrationsHandler.getCurrentVersions(cert); + assertEquals("1.1.1", currentVersions.get(StrolchConstants.DEFAULT_REALM).toString()); + + MapOfLists lastMigrations = migrationsHandler.getLastMigrations(); + List expectedMigrations = Arrays.asList(Version.valueOf("0.1.0"), Version.valueOf("0.1.1"), + Version.valueOf("0.5.2"), Version.valueOf("1.0.0"), Version.valueOf("1.0.5"), Version.valueOf("1.1.1")); + assertEquals(expectedMigrations, lastMigrations.getList(StrolchConstants.DEFAULT_REALM)); + + MapOfLists migrationsToRun = migrationsHandler.queryMigrationsToRun(cert); + assertTrue("Expected to have all migrations run", migrationsToRun.isEmpty()); + } +} diff --git a/li.strolch.service/src/test/java/li/strolch/service/test/AbstractRealmServiceTest.java b/li.strolch.service/src/test/java/li/strolch/service/test/AbstractRealmServiceTest.java index 5a574206c..5920530dd 100644 --- a/li.strolch.service/src/test/java/li/strolch/service/test/AbstractRealmServiceTest.java +++ b/li.strolch.service/src/test/java/li/strolch/service/test/AbstractRealmServiceTest.java @@ -35,6 +35,8 @@ import li.strolch.testbase.runtime.RuntimeMock; import org.junit.After; import org.junit.Before; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import ch.eitchnet.db.DbSchemaVersionCheck; import ch.eitchnet.privilege.model.Certificate; @@ -51,6 +53,8 @@ public abstract class AbstractRealmServiceTest { public static final String RUNTIME_PATH = "target/svcTestRuntime/"; //$NON-NLS-1$ public static final String CONFIG_SRC = "src/test/resources/svctest"; //$NON-NLS-1$ + protected static final Logger logger = LoggerFactory.getLogger(AbstractRealmServiceTest.class); + protected static RuntimeMock runtimeMock; protected Certificate certificate; diff --git a/li.strolch.agent/src/test/resources/migrationstest/config/PrivilegeConfig.xml b/li.strolch.service/src/test/resources/migrationstest/config/PrivilegeConfig.xml similarity index 100% rename from li.strolch.agent/src/test/resources/migrationstest/config/PrivilegeConfig.xml rename to li.strolch.service/src/test/resources/migrationstest/config/PrivilegeConfig.xml diff --git a/li.strolch.agent/src/test/resources/migrationstest/config/PrivilegeModel.xml b/li.strolch.service/src/test/resources/migrationstest/config/PrivilegeModel.xml similarity index 100% rename from li.strolch.agent/src/test/resources/migrationstest/config/PrivilegeModel.xml rename to li.strolch.service/src/test/resources/migrationstest/config/PrivilegeModel.xml diff --git a/li.strolch.agent/src/test/resources/migrationstest/config/StrolchConfiguration.xml b/li.strolch.service/src/test/resources/migrationstest/config/StrolchConfiguration.xml similarity index 69% rename from li.strolch.agent/src/test/resources/migrationstest/config/StrolchConfiguration.xml rename to li.strolch.service/src/test/resources/migrationstest/config/StrolchConfiguration.xml index 4ed2e74c8..3e1edf6db 100644 --- a/li.strolch.agent/src/test/resources/migrationstest/config/StrolchConfiguration.xml +++ b/li.strolch.service/src/test/resources/migrationstest/config/StrolchConfiguration.xml @@ -24,26 +24,23 @@ defaultRealm TRANSIENT - Model.xml + StrolchModel.xml ServiceHandler - li.strolch.runtime.configuration.model.ServiceHandlerTest - li.strolch.runtime.configuration.model.ServiceHandlerTestImpl - RealmHandler + li.strolch.service.api.ServiceHandler + li.strolch.service.api.DefaultServiceHandler MigrationsHandler li.strolch.migrations.MigrationsHandler li.strolch.migrations.MigrationsHandler ServiceHandler - - - PostInitializer - li.strolch.runtime.configuration.model.PostInitializerTest - li.strolch.runtime.configuration.model.PostInitializerTestImpl - MigrationsHandler + + true + true + \ No newline at end of file diff --git a/li.strolch.agent/src/test/resources/migrationstest/data/Model.xml b/li.strolch.service/src/test/resources/migrationstest/data/StrolchModel.xml similarity index 100% rename from li.strolch.agent/src/test/resources/migrationstest/data/Model.xml rename to li.strolch.service/src/test/resources/migrationstest/data/StrolchModel.xml diff --git a/li.strolch.agent/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.1.0.xml b/li.strolch.service/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.1.0.xml similarity index 100% rename from li.strolch.agent/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.1.0.xml rename to li.strolch.service/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.1.0.xml diff --git a/li.strolch.agent/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.1.1.xml b/li.strolch.service/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.1.1.xml similarity index 100% rename from li.strolch.agent/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.1.1.xml rename to li.strolch.service/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.1.1.xml diff --git a/li.strolch.agent/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.5.2.xml b/li.strolch.service/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.5.2.xml similarity index 100% rename from li.strolch.agent/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.5.2.xml rename to li.strolch.service/src/test/resources/migrationstest/data/migrations/data/defaultRealm/0.5.2.xml diff --git a/li.strolch.agent/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.0.0.xml b/li.strolch.service/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.0.0.xml similarity index 100% rename from li.strolch.agent/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.0.0.xml rename to li.strolch.service/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.0.0.xml diff --git a/li.strolch.agent/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.0.5.xml b/li.strolch.service/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.0.5.xml similarity index 100% rename from li.strolch.agent/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.0.5.xml rename to li.strolch.service/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.0.5.xml diff --git a/li.strolch.agent/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.1.1.xml b/li.strolch.service/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.1.1.xml similarity index 100% rename from li.strolch.agent/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.1.1.xml rename to li.strolch.service/src/test/resources/migrationstest/data/migrations/data/defaultRealm/1.1.1.xml