diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/api/ComponentState.java b/li.strolch.agent/src/main/java/li/strolch/agent/api/ComponentState.java index 118896587..b38c8736d 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/api/ComponentState.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/api/ComponentState.java @@ -32,11 +32,11 @@ public enum ComponentState { throw getIllegalStateEx(newState); break; case SETUP: - if (newState != ComponentState.INITIALIZED && newState != STOPPED) + if (newState != ComponentState.INITIALIZED && newState != STOPPED && newState != DESTROYED) throw getIllegalStateEx(newState); break; case INITIALIZED: - if (newState != ComponentState.STARTED && newState != STOPPED) + if (newState != ComponentState.STARTED && newState != STOPPED && newState != DESTROYED) throw getIllegalStateEx(newState); break; case STARTED: diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/api/RealmHandler.java b/li.strolch.agent/src/main/java/li/strolch/agent/api/RealmHandler.java index a4ebd0b48..10d940eb5 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/api/RealmHandler.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/api/RealmHandler.java @@ -25,6 +25,21 @@ import li.strolch.runtime.StrolchConstants; */ public interface RealmHandler { + /** + * Name of the transaction which boots the agent + */ + public static final String SYSTEM_USER_AGENT = "agent"; //$NON-NLS-1$ + + /** + * Name of the system user which boots the agent + */ + public static final String AGENT_BOOT = "agent_boot"; //$NON-NLS-1$ + + /** + * Name of the system user which performs DB Initialization + */ + public static final String SYSTEM_USER_DB_INITIALIZER = "db_initializer"; + /** * Returns the names of the configured {@link StrolchRealm StrolchRealms} * diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/DefaultRealmHandler.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/DefaultRealmHandler.java index bcc986e8a..5951fac10 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/DefaultRealmHandler.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/DefaultRealmHandler.java @@ -15,8 +15,6 @@ */ package li.strolch.agent.impl; -import static ch.eitchnet.utils.helper.StringHelper.DOT; - import java.text.MessageFormat; import java.util.HashMap; import java.util.HashSet; @@ -38,13 +36,11 @@ import ch.eitchnet.utils.dbc.DBC; */ public class DefaultRealmHandler extends StrolchComponent implements RealmHandler { - private static final String SYSTEM_USER_AGENT = "agent"; //$NON-NLS-1$ - public static final String AGENT_BOOT = "agent_boot"; //$NON-NLS-1$ - public static final String PROP_ENABLE_AUDIT_TRAIL = "enableAuditTrail"; //$NON-NLS-1$ public static final String PROP_ENABLE_AUDIT_TRAIL_FOR_READ = "enableAuditTrailForRead"; //$NON-NLS-1$ public static final String PROP_ENABLE_OBSERVER_UPDATES = "enableObserverUpdates"; //$NON-NLS-1$ public static final String PREFIX_DATA_STORE_MODE = "dataStoreMode"; //$NON-NLS-1$ + public static final String PREFIX_DATA_STORE_FILE = "dataStoreFile"; //$NON-NLS-1$ public static final String PROP_REALMS = "realms"; //$NON-NLS-1$ protected Map realms; @@ -80,7 +76,7 @@ public class DefaultRealmHandler extends StrolchComponent implements RealmHandle this.realms = new HashMap<>(); String[] realms = configuration.getStringArray(PROP_REALMS, StrolchConstants.DEFAULT_REALM); for (String realmName : realms) { - String dataStoreModeKey = makeRealmKey(realmName, PREFIX_DATA_STORE_MODE); + String dataStoreModeKey = StrolchConstants.makeRealmKey(realmName, PREFIX_DATA_STORE_MODE); String realmMode = configuration.getString(dataStoreModeKey, null); DataStoreMode dataStoreMode = DataStoreMode.parseDataStoreMode(realmMode); InternalStrolchRealm realm = dataStoreMode.createRealm(realmName); @@ -89,13 +85,6 @@ public class DefaultRealmHandler extends StrolchComponent implements RealmHandle super.setup(configuration); } - public static String makeRealmKey(String realmName, String key) { - String realmKey = key; - if (!realmName.equals(StrolchConstants.DEFAULT_REALM)) - realmKey += DOT + realmName; - return realmKey; - } - @Override public void initialize(ComponentConfiguration configuration) { diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/EmptyRealm.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/EmptyRealm.java index 184eb5862..4b1d2e1d3 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/EmptyRealm.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/EmptyRealm.java @@ -24,6 +24,7 @@ import li.strolch.agent.api.ResourceMap; import li.strolch.persistence.api.PersistenceHandler; import li.strolch.persistence.api.StrolchTransaction; import li.strolch.persistence.inmemory.InMemoryPersistence; +import li.strolch.runtime.StrolchConstants; import li.strolch.runtime.configuration.ComponentConfiguration; import ch.eitchnet.privilege.model.Certificate; import ch.eitchnet.privilege.model.PrivilegeContext; @@ -82,7 +83,7 @@ public class EmptyRealm extends InternalStrolchRealm { this.resourceMap = new TransactionalResourceMap(); this.orderMap = new TransactionalOrderMap(); - String enableAuditKey = DefaultRealmHandler.makeRealmKey(getRealm(), + String enableAuditKey = StrolchConstants.makeRealmKey(getRealm(), DefaultRealmHandler.PROP_ENABLE_AUDIT_TRAIL); if (configuration.getBoolean(enableAuditKey, Boolean.FALSE)) { this.auditTrail = new TransactionalAuditTrail(); diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/InternalStrolchRealm.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/InternalStrolchRealm.java index 014bbb739..c5d975ddb 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/InternalStrolchRealm.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/InternalStrolchRealm.java @@ -32,6 +32,7 @@ import li.strolch.agent.api.OrderMap; import li.strolch.agent.api.ResourceMap; import li.strolch.agent.api.StrolchRealm; import li.strolch.model.StrolchRootElement; +import li.strolch.runtime.StrolchConstants; import li.strolch.runtime.configuration.ComponentConfiguration; import org.slf4j.Logger; @@ -78,18 +79,18 @@ public abstract class InternalStrolchRealm implements StrolchRealm { public void initialize(ComponentContainer container, ComponentConfiguration configuration) { - String propTryLockTimeUnit = DefaultRealmHandler.makeRealmKey(this.realm, PROP_TRY_LOCK_TIME_UNIT); - String propTryLockTime = DefaultRealmHandler.makeRealmKey(this.realm, PROP_TRY_LOCK_TIME); + String propTryLockTimeUnit = StrolchConstants.makeRealmKey(this.realm, PROP_TRY_LOCK_TIME_UNIT); + String propTryLockTime = StrolchConstants.makeRealmKey(this.realm, PROP_TRY_LOCK_TIME); - String enableAuditKey = DefaultRealmHandler.makeRealmKey(getRealm(), + String enableAuditKey = StrolchConstants.makeRealmKey(getRealm(), DefaultRealmHandler.PROP_ENABLE_AUDIT_TRAIL); this.auditTrailEnabled = configuration.getBoolean(enableAuditKey, Boolean.FALSE); - String enableAuditForReadKey = DefaultRealmHandler.makeRealmKey(getRealm(), + String enableAuditForReadKey = StrolchConstants.makeRealmKey(getRealm(), DefaultRealmHandler.PROP_ENABLE_AUDIT_TRAIL_FOR_READ); this.auditTrailEnabledForRead = configuration.getBoolean(enableAuditForReadKey, Boolean.FALSE); - String updateObserversKey = DefaultRealmHandler.makeRealmKey(getRealm(), + String updateObserversKey = StrolchConstants.makeRealmKey(getRealm(), DefaultRealmHandler.PROP_ENABLE_OBSERVER_UPDATES); this.updateObservers = configuration.getBoolean(updateObserversKey, Boolean.FALSE); if (this.updateObservers) diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/StoreToDaoElementListener.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/StoreToDaoElementListener.java new file mode 100644 index 000000000..14d170383 --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/StoreToDaoElementListener.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013 Robert von Burg + */ +package li.strolch.agent.impl; + +import li.strolch.model.Order; +import li.strolch.model.Resource; +import li.strolch.model.xml.StrolchElementListener; +import li.strolch.persistence.api.OrderDao; +import li.strolch.persistence.api.ResourceDao; +import li.strolch.persistence.api.StrolchTransaction; + +public class StoreToDaoElementListener implements StrolchElementListener { + + private StrolchTransaction tx; + private ResourceDao resourceDao; + private OrderDao orderDao; + + public StoreToDaoElementListener(StrolchTransaction tx) { + this.tx = tx; + this.resourceDao = tx.getPersistenceHandler().getResourceDao(this.tx); + this.orderDao = tx.getPersistenceHandler().getOrderDao(this.tx); + } + + @Override + public void notifyResource(Resource resource) { + this.resourceDao.save(resource); + } + + @Override + public void notifyOrder(Order order) { + this.orderDao.save(order); + } +} \ No newline at end of file diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransientRealm.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransientRealm.java index 7b20a89bf..ed8ad0159 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransientRealm.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransientRealm.java @@ -27,6 +27,7 @@ import li.strolch.model.xml.XmlModelSaxFileReader; import li.strolch.persistence.api.PersistenceHandler; import li.strolch.persistence.api.StrolchTransaction; import li.strolch.persistence.inmemory.InMemoryPersistence; +import li.strolch.runtime.StrolchConstants; import li.strolch.runtime.configuration.ComponentConfiguration; import li.strolch.runtime.configuration.StrolchConfigurationException; import ch.eitchnet.privilege.model.Certificate; @@ -39,8 +40,6 @@ import ch.eitchnet.utils.helper.StringHelper; */ public class TransientRealm extends InternalStrolchRealm { - public static final String PREFIX_DATA_STORE_FILE = "dataStoreFile"; //$NON-NLS-1$ - private ResourceMap resourceMap; private OrderMap orderMap; private AuditTrail auditTrail; @@ -88,7 +87,7 @@ public class TransientRealm extends InternalStrolchRealm { public void initialize(ComponentContainer container, ComponentConfiguration configuration) { super.initialize(container, configuration); - String key = DefaultRealmHandler.makeRealmKey(getRealm(), PREFIX_DATA_STORE_FILE); + String key = StrolchConstants.makeRealmKey(getRealm(), DefaultRealmHandler.PREFIX_DATA_STORE_FILE); if (!configuration.hasProperty(key)) { String msg = "There is no data store file for realm {0}. Set a property with key {1}"; //$NON-NLS-1$ msg = MessageFormat.format(msg, getRealm(), key); diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/PersistenceHandler.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/PersistenceHandler.java index 791671fd8..94d224fd5 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/api/PersistenceHandler.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/PersistenceHandler.java @@ -15,7 +15,13 @@ */ package li.strolch.persistence.api; +import li.strolch.agent.api.AuditTrail; +import li.strolch.agent.api.OrderMap; +import li.strolch.agent.api.ResourceMap; import li.strolch.agent.api.StrolchRealm; +import li.strolch.model.Order; +import li.strolch.model.Resource; +import li.strolch.model.audit.Audit; import ch.eitchnet.privilege.model.Certificate; /** @@ -23,11 +29,59 @@ import ch.eitchnet.privilege.model.Certificate; */ public interface PersistenceHandler { + /** + * Opens a {@link StrolchTransaction} on the given {@link StrolchRealm}. The transaction is the main object to be + * used when accessing and modifying the elements of a realm. + * + * @param realm + * the realm for which the transaction is to be opened + * @param certificate + * the certificate which has access to the realm + * @param action + * the name of the transaction used for auditing + * + * @return the newly created {@link StrolchTransaction} + */ public StrolchTransaction openTx(StrolchRealm realm, Certificate certificate, String action); + /** + * Returns the {@link OrderDao} for the given transaction. Use this only if you want to bypass certain transaction + * features. Accessing {@link Order Orders} should be done through the {@link OrderMap} accessed from the + * transaction + * + * @param tx + * the transaction for which the {@link OrderDao} is to be returned + * + * @return the {@link OrderDao} + */ public OrderDao getOrderDao(StrolchTransaction tx); + /** + * Returns the {@link ResourceDao} for the given transaction. Use this only if you want to bypass certain + * transaction features. Accessing {@link Resource Resources} should be done through the {@link ResourceMap} + * accessed from the transaction + * + * @param tx + * the transaction for which the {@link ResourceDao} is to be returned + * + * @return the {@link ResourceDao} + */ public ResourceDao getResourceDao(StrolchTransaction tx); + /** + * Returns the {@link AuditDao} for the given transaction. Use this only if you want to bypass certain transaction + * features. Accessing {@link Audit Audits} should be done through the {@link AuditTrail} accessed from the + * transaction + * + * @param tx + * the transaction for which the {@link AuditDao} is to be returned + * + * @return the {@link AuditDao} + */ public AuditDao getAuditDao(StrolchTransaction tx); + + /** + * Performs a database specific initialization of the underlying database for each realm. + */ + public void performDbInitialization(); } diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistence.java b/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistence.java index 31ea01515..d6543aee5 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistence.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistence.java @@ -45,6 +45,11 @@ public class InMemoryPersistence implements PersistenceHandler { return daoCache.getAuditDao(); } + @Override + public void performDbInitialization() { + // no-op + } + private synchronized DaoCache getDaoCache(StrolchTransaction tx) { DaoCache daoCache = this.daoCache.get(tx.getRealmName()); if (daoCache == null) { diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistenceHandler.java b/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistenceHandler.java index 192f778a1..5646fbdbc 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistenceHandler.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistenceHandler.java @@ -66,4 +66,9 @@ public class InMemoryPersistenceHandler extends StrolchComponent implements Pers public AuditDao getAuditDao(StrolchTransaction tx) { return this.persistence.getAuditDao(tx); } + + @Override + public void performDbInitialization() { + // no-op + } } diff --git a/li.strolch.agent/src/main/java/li/strolch/runtime/StrolchConstants.java b/li.strolch.agent/src/main/java/li/strolch/runtime/StrolchConstants.java index 63b1817b0..2ed2a0842 100644 --- a/li.strolch.agent/src/main/java/li/strolch/runtime/StrolchConstants.java +++ b/li.strolch.agent/src/main/java/li/strolch/runtime/StrolchConstants.java @@ -15,6 +15,7 @@ */ package li.strolch.runtime; +import static ch.eitchnet.utils.helper.StringHelper.DOT; import li.strolch.agent.api.ObserverHandler; import li.strolch.model.StrolchModelConstants; import li.strolch.persistence.api.PersistenceHandler; @@ -49,4 +50,11 @@ public class StrolchConstants { * @see StrolchModelConstants#INTERPRETATION_ORDER_REF */ public static final String INTERPRETATION_ORDER_REF = StrolchModelConstants.INTERPRETATION_ORDER_REF; + + public static String makeRealmKey(String realmName, String key) { + String realmKey = key; + if (!realmName.equals(DEFAULT_REALM)) + realmKey += DOT + realmName; + return realmKey; + } } diff --git a/li.strolch.agent/src/main/java/li/strolch/runtime/main/MainStarter.java b/li.strolch.agent/src/main/java/li/strolch/runtime/main/MainStarter.java index 789ef6347..9b8a62d46 100644 --- a/li.strolch.agent/src/main/java/li/strolch/runtime/main/MainStarter.java +++ b/li.strolch.agent/src/main/java/li/strolch/runtime/main/MainStarter.java @@ -31,6 +31,8 @@ import org.apache.commons.cli.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import ch.eitchnet.utils.helper.StringHelper; + /** * @author Robert von Burg * @@ -44,9 +46,13 @@ public class MainStarter { private static final String OPT_ENV = "env"; private Options options; + private String env; + private File pathF; + private StrolchAgent agent; public MainStarter() { + Options op = new Options(); Option rootPathOption = new Option("p", OPT_ROOT_PATH, true, "root path to strolch runtime"); rootPathOption.setOptionalArg(false); @@ -61,6 +67,17 @@ public class MainStarter { } public int start(String[] args) { + int ret = parseArgs(args); + if (ret != 0) + return ret; + + setup(); + initialize(); + start(); + return keepAlive(); + } + + public int parseArgs(String[] args) { // create the parser CommandLineParser parser = new GnuParser(); @@ -75,21 +92,46 @@ public class MainStarter { return 1; } - String env = line.getOptionValue(OPT_ENV); - - String pathS = line.getOptionValue(OPT_ROOT_PATH); - File pathF = new File(pathS); - if (!pathF.exists()) { - logger.info(MessageFormat.format("Path parameter does not exist at: {0}", pathS)); + this.env = line.getOptionValue(OPT_ENV); + if (StringHelper.isEmpty(this.env)) { + logger.error("env argument is missing!"); printUsage(); return 1; } - logger.info("Starting Agent..."); - setAgent(new StrolchAgent()); - getAgent().setup(env, pathF); + String pathS = line.getOptionValue(OPT_ROOT_PATH); + this.pathF = new File(pathS); + if (!this.pathF.exists()) { + logger.error(MessageFormat.format("Path parameter does not exist at: {0}", pathS)); + printUsage(); + return 1; + } + + return 0; + } + + public void setup() { + this.agent = new StrolchAgent(); + getAgent().setup(this.env, this.pathF); + } + + public void initialize() { getAgent().initialize(); + } + + public void start() { getAgent().start(); + } + + public void stop() { + getAgent().stop(); + } + + public void destroy() { + getAgent().destroy(); + } + + public int keepAlive() { final AtomicBoolean atomicBoolean = new AtomicBoolean(); @@ -128,23 +170,11 @@ public class MainStarter { } private void printUsage() { - HelpFormatter formatter = new HelpFormatter(); formatter.printHelp("java -classpath lib/ -jar .jar ", this.options); } - /** - * @return the agent - */ public StrolchAgent getAgent() { return this.agent; } - - /** - * @param agent - * the agent to set - */ - public void setAgent(StrolchAgent agent) { - this.agent = agent; - } } diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/DbConnectionCheck.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/DbConnectionCheck.java index 8fa034e5d..eddf8d734 100644 --- a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/DbConnectionCheck.java +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/DbConnectionCheck.java @@ -53,6 +53,8 @@ public class DbConnectionCheck { String username = connectionInfo.getUsername(); String password = connectionInfo.getPassword(); + logger.info("Checking connection " + username + "@" + url); + try (Connection con = DriverManager.getConnection(url, username, password); Statement st = con.createStatement();) { @@ -68,5 +70,7 @@ public class DbConnectionCheck { throw new StrolchConfigurationException(msg, e); } } + + logger.info("All connections OK"); } } diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/DbMigrationState.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/DbMigrationState.java new file mode 100644 index 000000000..3f6b02986 --- /dev/null +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/DbMigrationState.java @@ -0,0 +1,23 @@ +/* + * Copyright 2013 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.persistence.postgresql; + +/** + * @author Robert von Burg + */ +public enum DbMigrationState { + NOTHING, CREATED, MIGRATED, DROPPED_CREATED; +} diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/DbSchemaVersionCheck.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/DbSchemaVersionCheck.java index 7ad6bc8cd..3fae27811 100644 --- a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/DbSchemaVersionCheck.java +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/DbSchemaVersionCheck.java @@ -15,6 +15,9 @@ */ package li.strolch.persistence.postgresql; +import static li.strolch.persistence.postgresql.PostgreSqlPersistenceHandler.PROP_DB_VERSION; +import static li.strolch.persistence.postgresql.PostgreSqlPersistenceHandler.RESOURCE_DB_VERSION; + import java.io.IOException; import java.io.InputStream; import java.sql.Connection; @@ -23,13 +26,12 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.text.MessageFormat; -import java.util.Collection; +import java.util.HashMap; import java.util.Map; import java.util.Properties; import li.strolch.exception.StrolchException; import li.strolch.persistence.api.DbConnectionInfo; -import li.strolch.runtime.configuration.ComponentConfiguration; import li.strolch.runtime.configuration.StrolchConfigurationException; import org.slf4j.Logger; @@ -44,79 +46,95 @@ import ch.eitchnet.utils.helper.FileHelper; @SuppressWarnings(value = "nls") public class DbSchemaVersionCheck { - private static final String RESOURCE_DB_VERSION = "/db_version.properties"; - private static final String PROP_DB_VERSION = "db_version"; - private static final String PROP_ALLOW_SCHEMA_CREATION = "allowSchemaCreation"; - private static final String PROP_ALLOW_SCHEMA_DROP = "allowSchemaDrop"; - private static final Logger logger = LoggerFactory.getLogger(DbSchemaVersionCheck.class); - private Map connetionInfoMap; private boolean allowSchemaCreation; private boolean allowSchemaDrop; + private Map dbMigrationStates; /** - * @param connetionInfoMap - * @param componentConfiguration + * @param allowSchemaCreation + * @param allowSchemaDrop + * @param allowDataInitOnSchemaCreate */ - public DbSchemaVersionCheck(Map connetionInfoMap, - ComponentConfiguration componentConfiguration) { - this.connetionInfoMap = connetionInfoMap; - - this.allowSchemaCreation = componentConfiguration.getBoolean(PROP_ALLOW_SCHEMA_CREATION, Boolean.FALSE); - this.allowSchemaDrop = componentConfiguration.getBoolean(PROP_ALLOW_SCHEMA_DROP, Boolean.FALSE); + public DbSchemaVersionCheck(boolean allowSchemaCreation, boolean allowSchemaDrop) { + this.allowSchemaCreation = allowSchemaCreation; + this.allowSchemaDrop = allowSchemaDrop; + this.dbMigrationStates = new HashMap<>(); } - public void checkSchemaVersion() { + /** + * @return the dbMigrationStates + */ + public Map getDbMigrationStates() { + return this.dbMigrationStates; + } - Collection values = this.connetionInfoMap.values(); - - for (DbConnectionInfo connectionInfo : values) { - String realm = connectionInfo.getRealm(); - String url = connectionInfo.getUrl(); - String username = connectionInfo.getUsername(); - String password = connectionInfo.getPassword(); - - logger.info(MessageFormat.format("[{0}] Checking Schema version for: {1}@{2}", realm, username, url)); - - try (Connection con = DriverManager.getConnection(url, username, password); - Statement st = con.createStatement();) { - - String expectedDbVersion = getExpectedDbVersion(); - - // first see if we have any schema - String msg = "select table_schema, table_name, table_type from information_schema.tables where table_name=''{0}'';"; - String checkSchemaExistsSql = MessageFormat.format(msg, PROP_DB_VERSION); - try (ResultSet rs = st.executeQuery(checkSchemaExistsSql)) { - if (!rs.next()) { - createSchema(realm, expectedDbVersion, st); - } else { - checkCurrentVersion(realm, st, expectedDbVersion); - } - } - - } catch (SQLException e) { - String msg = "Failed to open DB connection to URL {0} due to: {1}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, url, e.getMessage()); - throw new StrolchConfigurationException(msg, e); - } + public void checkSchemaVersion(Map connectionInfoMap) { + for (DbConnectionInfo connectionInfo : connectionInfoMap.values()) { + DbMigrationState dbMigrationState = checkSchemaVersion(connectionInfo); + dbMigrationStates.put(connectionInfo.getRealm(), dbMigrationState); } } - private void checkCurrentVersion(String realm, Statement st, String expectedDbVersion) throws SQLException { + /** + * Returns true if the schema existed or was only migrated, false if the schema was created + * + * @param connectionInfo + * + * @return true if the schema existed or was only migrated, false if the schema was created + */ + public DbMigrationState checkSchemaVersion(DbConnectionInfo connectionInfo) { + String realm = connectionInfo.getRealm(); + String url = connectionInfo.getUrl(); + String username = connectionInfo.getUsername(); + String password = connectionInfo.getPassword(); + + logger.info(MessageFormat.format("[{0}] Checking Schema version for: {1}@{2}", realm, username, url)); + + DbMigrationState migrationType; + + try (Connection con = DriverManager.getConnection(url, username, password); + Statement st = con.createStatement();) { + + String expectedDbVersion = getExpectedDbVersion(); + + // first see if we have any schema + String msg = "select table_schema, table_name, table_type from information_schema.tables where table_name=''{0}'';"; + String checkSchemaExistsSql = MessageFormat.format(msg, PROP_DB_VERSION); + try (ResultSet rs = st.executeQuery(checkSchemaExistsSql)) { + if (!rs.next()) { + migrationType = createSchema(realm, expectedDbVersion, st); + } else { + migrationType = checkCurrentVersion(realm, st, expectedDbVersion); + } + } + + return migrationType; + + } catch (SQLException e) { + String msg = "Failed to open DB connection to URL {0} due to: {1}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, url, e.getMessage()); + throw new StrolchConfigurationException(msg, e); + } + } + + private DbMigrationState checkCurrentVersion(String realm, Statement st, String expectedDbVersion) + throws SQLException { try (ResultSet rs = st.executeQuery("select id, version from db_version order by id desc;")) { if (!rs.next()) { - createSchema(realm, expectedDbVersion, st); + return createSchema(realm, expectedDbVersion, st); } else { String currentVersion = rs.getString(2); if (expectedDbVersion.equals(currentVersion)) { String msg = "[{0}] Schema version {1} is the current version. No changes needed."; msg = MessageFormat.format(msg, realm, currentVersion); logger.info(msg); + return DbMigrationState.NOTHING; } else { String msg = "[{0}] Schema version is not current. Need to upgrade from {1} to {2}"; msg = MessageFormat.format(msg, realm, currentVersion, expectedDbVersion); logger.warn(msg); - upgradeSchema(realm, expectedDbVersion, st); + return upgradeSchema(realm, expectedDbVersion, st); } } } @@ -152,10 +170,17 @@ public class DbSchemaVersionCheck { } /** + * * @param realm + * the realm to create the schema for (a {@link DbConnectionInfo} must exist for it) + * @param dbVersion + * the version to upgrade to * @param st + * the open database {@link Statement} to which the SQL statements will be written + * + * @return true if the schema was created, false if it was not */ - private void createSchema(String realm, String dbVersion, Statement st) { + private DbMigrationState createSchema(String realm, String dbVersion, Statement st) { if (!this.allowSchemaCreation) { String msg = "[{0}] No schema exists, or is not valid. Schema generation is disabled, thus can not continue!"; @@ -174,8 +199,17 @@ public class DbSchemaVersionCheck { } logger.info(MessageFormat.format("[{0}] Successfully created schema for version {1}", realm, dbVersion)); + return DbMigrationState.CREATED; } + /** + * @param realm + * the realm for which the schema must be dropped (a {@link DbConnectionInfo} must exist for it) + * @param dbVersion + * the version with which to to drop the schema + * @param st + * the open database {@link Statement} to which the SQL statements will be written + */ private void dropSchema(String realm, String dbVersion, Statement st) { if (!this.allowSchemaDrop) { @@ -196,10 +230,21 @@ public class DbSchemaVersionCheck { } /** + * Upgrades the schema to the given version. If the current version is below the given version, then currently this + * method drops the schema and recreates it. Real migration must still be implemented + * + * @param realm + * the realm to migrate (a {@link DbConnectionInfo} must exist for it) + * @param dbVersion + * the version to upgrade to * @param st + * the open database {@link Statement} to which the SQL statements will be written + * + * @return true if the schema was recreated, false if it was simply migrated */ - private void upgradeSchema(String realm, String dbVersion, Statement st) { + private DbMigrationState upgradeSchema(String realm, String dbVersion, Statement st) { dropSchema(realm, dbVersion, st); createSchema(realm, dbVersion, st); + return DbMigrationState.DROPPED_CREATED; } } diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlDbInitializer.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlDbInitializer.java new file mode 100644 index 000000000..273f7a326 --- /dev/null +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlDbInitializer.java @@ -0,0 +1,84 @@ +/* + * Copyright 2013 Robert von Burg + */ +package li.strolch.persistence.postgresql; + +import static li.strolch.persistence.postgresql.PostgreSqlPersistenceHandler.PROP_ALLOW_SCHEMA_CREATION; +import static li.strolch.persistence.postgresql.PostgreSqlPersistenceHandler.PROP_ALLOW_SCHEMA_DROP; + +import java.util.Map; +import java.util.Map.Entry; + +import li.strolch.agent.api.StrolchAgent; +import li.strolch.agent.api.StrolchRealm; +import li.strolch.persistence.api.DbConnectionInfo; +import li.strolch.runtime.configuration.ComponentConfiguration; +import li.strolch.runtime.configuration.RuntimeConfiguration; +import li.strolch.runtime.configuration.StrolchConfiguration; +import ch.eitchnet.privilege.model.Certificate; +import ch.eitchnet.privilege.model.PrivilegeContext; + +public class PostgreSqlDbInitializer extends PostgreSqlInitializer { + + private StrolchAgent agent; + private PostgreSqlPersistenceHandler persistenceHandler; + private RuntimeConfiguration runtimeConfig; + private Certificate certificate; + private boolean allowSchemaCreation; + private boolean allowSchemaDrop; + + /** + * @param agent + * @param persistenceHandler + */ + public PostgreSqlDbInitializer(StrolchAgent agent, PostgreSqlPersistenceHandler persistenceHandler, + ComponentConfiguration persistenceConfig) { + super(agent, persistenceHandler); + this.agent = agent; + StrolchConfiguration strolchConfiguration = agent.getStrolchConfiguration(); + this.runtimeConfig = strolchConfiguration.getRuntimeConfiguration(); + this.persistenceHandler = persistenceHandler; + this.allowSchemaCreation = persistenceConfig.getBoolean(PROP_ALLOW_SCHEMA_CREATION, Boolean.FALSE); + this.allowSchemaDrop = persistenceConfig.getBoolean(PROP_ALLOW_SCHEMA_DROP, Boolean.FALSE); + } + + @Override + protected Certificate getCertificate() { + return this.certificate; + } + + @Override + public void execute(PrivilegeContext privilegeContext) { + this.certificate = privilegeContext.getCertificate(); + + // first make sure we can connect to the database + Map connetionInfoMap = this.persistenceHandler.getConnetionInfoMap(); + DbConnectionCheck connectionCheck = new DbConnectionCheck(connetionInfoMap); + connectionCheck.checkConnections(); + + // first make sure that the data store files exist + for (String realmName : this.agent.getContainer().getRealmNames()) { + // throws exception if does not exist + getDataStoreFile(this.runtimeConfig, this.realmConfig, realmName); + } + + // for each connection info: + // - make sure schema exists + // - if it didn't exist, initialize with a set of data defined by the data store file + DbSchemaVersionCheck schemaVersionCheck = new DbSchemaVersionCheck(this.allowSchemaCreation, + this.allowSchemaDrop); + for (Entry entry : connetionInfoMap.entrySet()) { + String realmName = entry.getKey(); + DbConnectionInfo connectionInfo = entry.getValue(); + StrolchRealm realm = this.agent.getContainer().getRealm(realmName); + if (realm.getMode().isTransient()) + continue; + + // check that the schema exists + DbMigrationState migrationType = schemaVersionCheck.checkSchemaVersion(connectionInfo); + + // now init the DB if needed + initSchemaFromDataStore(migrationType, realmName); + } + } +} \ No newline at end of file diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlInitializer.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlInitializer.java new file mode 100644 index 000000000..5683e6271 --- /dev/null +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlInitializer.java @@ -0,0 +1,117 @@ +/* + * Copyright 2013 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.persistence.postgresql; + +import static li.strolch.agent.impl.DefaultRealmHandler.PREFIX_DATA_STORE_FILE; +import static li.strolch.runtime.StrolchConstants.makeRealmKey; + +import java.io.File; +import java.text.MessageFormat; + +import li.strolch.agent.api.RealmHandler; +import li.strolch.agent.api.StrolchAgent; +import li.strolch.agent.impl.StoreToDaoElementListener; +import li.strolch.model.ModelStatistics; +import li.strolch.model.xml.XmlModelSaxFileReader; +import li.strolch.persistence.api.StrolchTransaction; +import li.strolch.runtime.configuration.ComponentConfiguration; +import li.strolch.runtime.configuration.RuntimeConfiguration; +import li.strolch.runtime.configuration.StrolchConfiguration; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.eitchnet.privilege.handler.SystemUserAction; +import ch.eitchnet.privilege.model.Certificate; + +/** + * @author Robert von Burg + */ +public abstract class PostgreSqlInitializer implements SystemUserAction { + + protected static final Logger logger = LoggerFactory.getLogger(PostgreSqlInitializer.class); + protected StrolchAgent agent; + protected PostgreSqlPersistenceHandler persistenceHandler; + protected RuntimeConfiguration runtimeConfig; + protected ComponentConfiguration realmConfig; + + public PostgreSqlInitializer(StrolchAgent agent, PostgreSqlPersistenceHandler persistenceHandler) { + this.agent = agent; + this.persistenceHandler = persistenceHandler; + StrolchConfiguration strolchConfiguration = agent.getStrolchConfiguration(); + this.runtimeConfig = strolchConfiguration.getRuntimeConfiguration(); + this.realmConfig = strolchConfiguration.getComponentConfiguration(RealmHandler.class.getSimpleName()); + } + + protected abstract Certificate getCertificate(); + + /** + * @param migrationType + * @param realmName + */ + protected void initSchemaFromDataStore(DbMigrationState migrationType, String realmName) { + boolean needsDbInit = checkNeedsDbInit(migrationType); + if (!needsDbInit) { + String msg = "Schema for realm {0} had no migration run. No need for data initialization."; + logger.info(MessageFormat.format(msg, realmName)); + return; + } + + String msg = "Migration for schema for realm {0} was {1} so need to initialize the data from the databaseStore..."; + logger.info(MessageFormat.format(msg, realmName, migrationType)); + + ModelStatistics statistics; + try (StrolchTransaction tx = this.persistenceHandler.openTx(this.agent.getContainer().getRealm(realmName), + getCertificate(), RealmHandler.SYSTEM_USER_DB_INITIALIZER)) { + File dataStoreF = getDataStoreFile(this.runtimeConfig, this.realmConfig, realmName); + + StoreToDaoElementListener listener = new StoreToDaoElementListener(tx); + XmlModelSaxFileReader handler = new XmlModelSaxFileReader(listener, dataStoreF); + handler.parseFile(); + statistics = handler.getStatistics(); + } + logger.info(MessageFormat.format("Realm {0} initialization statistics: {1}", realmName, statistics)); + } + + protected boolean checkNeedsDbInit(DbMigrationState migrationType) { + boolean needsDbInit; + switch (migrationType) { + case CREATED: + needsDbInit = true; + break; + case DROPPED_CREATED: + needsDbInit = true; + break; + case MIGRATED: + needsDbInit = false; + break; + case NOTHING: + needsDbInit = false; + break; + default: + needsDbInit = false; + break; + } + return needsDbInit; + } + + protected File getDataStoreFile(RuntimeConfiguration runtimeConfiguration, + ComponentConfiguration realmConfiguration, String realmName) { + String dataStoreKey = makeRealmKey(realmName, PREFIX_DATA_STORE_FILE); + File dataStoreF = realmConfiguration.getDataFile(dataStoreKey, null, runtimeConfiguration, true); + return dataStoreF; + } +} diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlPersistenceHandler.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlPersistenceHandler.java index 3b04443d7..7be1ad973 100644 --- a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlPersistenceHandler.java +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlPersistenceHandler.java @@ -15,7 +15,8 @@ */ package li.strolch.persistence.postgresql; -import static ch.eitchnet.utils.helper.StringHelper.DOT; +import static li.strolch.agent.api.RealmHandler.SYSTEM_USER_DB_INITIALIZER; +import static li.strolch.runtime.StrolchConstants.makeRealmKey; import java.sql.Connection; import java.sql.Driver; @@ -27,6 +28,8 @@ import java.util.Map; import java.util.Set; import li.strolch.agent.api.ComponentContainer; +import li.strolch.agent.api.RealmHandler; +import li.strolch.agent.api.StrolchAgent; import li.strolch.agent.api.StrolchComponent; import li.strolch.agent.api.StrolchRealm; import li.strolch.persistence.api.AuditDao; @@ -36,9 +39,10 @@ import li.strolch.persistence.api.PersistenceHandler; import li.strolch.persistence.api.ResourceDao; import li.strolch.persistence.api.StrolchPersistenceException; import li.strolch.persistence.api.StrolchTransaction; -import li.strolch.runtime.StrolchConstants; import li.strolch.runtime.configuration.ComponentConfiguration; +import li.strolch.runtime.configuration.StrolchConfiguration; import li.strolch.runtime.configuration.StrolchConfigurationException; +import li.strolch.runtime.privilege.PrivilegeHandler; import ch.eitchnet.privilege.model.Certificate; /** @@ -46,9 +50,14 @@ import ch.eitchnet.privilege.model.Certificate; */ public class PostgreSqlPersistenceHandler extends StrolchComponent implements PersistenceHandler { - private static final String PROP_DB_URL = "db.url"; //$NON-NLS-1$ - private static final String PROP_DB_USERNAME = "db.username"; //$NON-NLS-1$ - private static final String PROP_DB_PASSWORD = "db.password"; //$NON-NLS-1$ + public static final String PROP_DB_URL = "db.url"; //$NON-NLS-1$ + public static final String PROP_DB_USERNAME = "db.username"; //$NON-NLS-1$ + public static final String PROP_DB_PASSWORD = "db.password"; //$NON-NLS-1$ + public static final String PROP_ALLOW_SCHEMA_CREATION = "allowSchemaCreation"; + public static final String PROP_ALLOW_SCHEMA_DROP = "allowSchemaDrop"; + public static final String PROP_ALLOW_DATA_INIT_ON_SCHEMA_CREATE = "allowDataInitOnSchemaCreate"; + public static final String PROP_DB_VERSION = "db_version"; + public static final String RESOURCE_DB_VERSION = "/db_version.properties"; private ComponentConfiguration componentConfiguration; private Map connetionInfoMap; @@ -70,14 +79,9 @@ public class PostgreSqlPersistenceHandler extends StrolchComponent implements Pe if (realm.getMode().isTransient()) continue; - String dbUrlKey = PROP_DB_URL; - String dbUsernameKey = PROP_DB_USERNAME; - String dbPasswordKey = PROP_DB_PASSWORD; - if (!realmName.equals(StrolchConstants.DEFAULT_REALM)) { - dbUrlKey += DOT + realmName; - dbUsernameKey += DOT + realmName; - dbPasswordKey += DOT + realmName; - } + String dbUrlKey = makeRealmKey(realmName, PROP_DB_URL); + String dbUsernameKey = makeRealmKey(realmName, PROP_DB_USERNAME); + String dbPasswordKey = makeRealmKey(realmName, PROP_DB_PASSWORD); String dbUrl = componentConfiguration.getString(dbUrlKey, null); String username = componentConfiguration.getString(dbUsernameKey, null); @@ -112,7 +116,15 @@ public class PostgreSqlPersistenceHandler extends StrolchComponent implements Pe msg = MessageFormat.format(msg, connectionInfo.getRealm(), compliant, driver.getMajorVersion(), driver.getMinorVersion()); logger.info(msg); + } + /** + * Returns the map of {@link DbConnectionInfo} which can be used in maintenance mode + * + * @return the connetionInfoMap + */ + public Map getConnetionInfoMap() { + return this.connetionInfoMap; } @Override @@ -122,9 +134,27 @@ public class PostgreSqlPersistenceHandler extends StrolchComponent implements Pe DbConnectionCheck connectionCheck = new DbConnectionCheck(this.connetionInfoMap); connectionCheck.checkConnections(); - DbSchemaVersionCheck schemaVersionCheck = new DbSchemaVersionCheck(this.connetionInfoMap, - this.componentConfiguration); - schemaVersionCheck.checkSchemaVersion(); + boolean allowSchemaCreation = componentConfiguration.getBoolean(PROP_ALLOW_SCHEMA_CREATION, Boolean.FALSE); + boolean allowSchemaDrop = componentConfiguration.getBoolean(PROP_ALLOW_SCHEMA_DROP, Boolean.FALSE); + boolean allowDataInitOnSchemaCreate = componentConfiguration.getBoolean(PROP_ALLOW_DATA_INIT_ON_SCHEMA_CREATE, + Boolean.FALSE); + + DbSchemaVersionCheck schemaVersionCheck = new DbSchemaVersionCheck(allowSchemaCreation, allowSchemaDrop); + schemaVersionCheck.checkSchemaVersion(this.connetionInfoMap); + + // if allowed, perform DB initialization + if (!allowSchemaCreation || !allowSchemaDrop || !allowDataInitOnSchemaCreate) { + logger.info("Data Initialization not enabled, so not checking if needed."); + } else { + Map dbMigrationStates = schemaVersionCheck.getDbMigrationStates(); + String msg = "Data Initialization is enabled, checking for {0} realms if DB initialization is required..."; + logger.info(MessageFormat.format(msg, dbMigrationStates.size())); + PrivilegeHandler privilegeHandler = getContainer().getPrivilegeHandler(); + StrolchAgent agent = getContainer().getAgent(); + PostgreSqlSchemaInitializer schemaInitializer = new PostgreSqlSchemaInitializer(agent, this, + dbMigrationStates); + privilegeHandler.runAsSystem(SYSTEM_USER_DB_INITIALIZER, schemaInitializer); + } super.start(); } @@ -168,4 +198,15 @@ public class PostgreSqlPersistenceHandler extends StrolchComponent implements Pe public AuditDao getAuditDao(StrolchTransaction tx) { return ((PostgreSqlStrolchTransaction) tx).getAuditDao(); } + + @Override + public void performDbInitialization() { + ComponentContainer container = getContainer(); + StrolchAgent agent = container.getAgent(); + PrivilegeHandler privilegeHandler = container.getPrivilegeHandler(); + StrolchConfiguration strolchConfiguration = this.getContainer().getAgent().getStrolchConfiguration(); + PostgreSqlDbInitializer sqlDbInitializer = new PostgreSqlDbInitializer(agent, this, + strolchConfiguration.getComponentConfiguration(getName())); + privilegeHandler.runAsSystem(RealmHandler.SYSTEM_USER_DB_INITIALIZER, sqlDbInitializer); + } } diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlSchemaInitializer.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlSchemaInitializer.java new file mode 100644 index 000000000..d6093be3f --- /dev/null +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlSchemaInitializer.java @@ -0,0 +1,65 @@ +/* + * Copyright 2013 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.persistence.postgresql; + +import java.util.Map; +import java.util.Map.Entry; + +import li.strolch.agent.api.StrolchAgent; +import ch.eitchnet.privilege.model.Certificate; +import ch.eitchnet.privilege.model.PrivilegeContext; + +/** + * @author Robert von Burg + */ +public class PostgreSqlSchemaInitializer extends PostgreSqlInitializer { + + private Map dbMigrationStates; + + /** + * @param agent + * @param persistenceHandler + * @param dbMigrationStates + */ + public PostgreSqlSchemaInitializer(StrolchAgent agent, PostgreSqlPersistenceHandler persistenceHandler, + Map dbMigrationStates) { + super(agent, persistenceHandler); + this.dbMigrationStates = dbMigrationStates; + } + + private Certificate certificate; + + @Override + public void execute(PrivilegeContext privilegeContext) { + this.certificate = privilegeContext.getCertificate(); + + // first make sure the data store exists if needed + for (Entry entry : this.dbMigrationStates.entrySet()) { + if (checkNeedsDbInit(entry.getValue())) + getDataStoreFile(runtimeConfig, realmConfig, entry.getKey()); + } + + // then initialize the schemas + for (Entry entry : this.dbMigrationStates.entrySet()) { + initSchemaFromDataStore(entry.getValue(), entry.getKey()); + } + } + + @Override + protected Certificate getCertificate() { + return this.certificate; + } +} diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlPersistenceHandler.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlPersistenceHandler.java index a281bb768..72e218e83 100644 --- a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlPersistenceHandler.java +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlPersistenceHandler.java @@ -97,4 +97,9 @@ public class XmlPersistenceHandler extends StrolchComponent implements Persisten public AuditDao getAuditDao(StrolchTransaction tx) { return new XmlAuditDao(tx); } + + @Override + public void performDbInitialization() { + throw new UnsupportedOperationException("Not yet implemented!"); + } }