[Major] Added a DB initialization mechanism
Now PostgreSQL implementation can import a configured dataStore if the persistence handler configuration property ‘allowDataInitOnSchemaCreate’. For this to work, the schema must have a migration status of CREATED, or DROPPED_CREATED on startup, or using the new method PersistenceHandler.performDbInitialization()-method. Further the properties ‘allowSchemaDrop’ and ‘allowSchemaCreate’ must be enabled.
This commit is contained in:
parent
461af7b24f
commit
96740a571c
|
@ -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:
|
||||
|
|
|
@ -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}
|
||||
*
|
||||
|
|
|
@ -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<String, InternalStrolchRealm> 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) {
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <eitch@eitchnet.ch>
|
||||
*
|
||||
|
@ -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.containing.main.class>.jar <options>", 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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 <eitch@eitchnet.ch>
|
||||
*/
|
||||
public enum DbMigrationState {
|
||||
NOTHING, CREATED, MIGRATED, DROPPED_CREATED;
|
||||
}
|
|
@ -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<String, DbConnectionInfo> connetionInfoMap;
|
||||
private boolean allowSchemaCreation;
|
||||
private boolean allowSchemaDrop;
|
||||
private Map<String, DbMigrationState> dbMigrationStates;
|
||||
|
||||
/**
|
||||
* @param connetionInfoMap
|
||||
* @param componentConfiguration
|
||||
* @param allowSchemaCreation
|
||||
* @param allowSchemaDrop
|
||||
* @param allowDataInitOnSchemaCreate
|
||||
*/
|
||||
public DbSchemaVersionCheck(Map<String, DbConnectionInfo> 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<String, DbMigrationState> getDbMigrationStates() {
|
||||
return this.dbMigrationStates;
|
||||
}
|
||||
|
||||
Collection<DbConnectionInfo> 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<String, DbConnectionInfo> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
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<String, DbConnectionInfo> 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<String, DbConnectionInfo> 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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 <eitch@eitchnet.ch>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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<String, DbConnectionInfo> 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<String, DbConnectionInfo> 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<String, DbMigrationState> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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 <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PostgreSqlSchemaInitializer extends PostgreSqlInitializer {
|
||||
|
||||
private Map<String, DbMigrationState> dbMigrationStates;
|
||||
|
||||
/**
|
||||
* @param agent
|
||||
* @param persistenceHandler
|
||||
* @param dbMigrationStates
|
||||
*/
|
||||
public PostgreSqlSchemaInitializer(StrolchAgent agent, PostgreSqlPersistenceHandler persistenceHandler,
|
||||
Map<String, DbMigrationState> 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<String, DbMigrationState> entry : this.dbMigrationStates.entrySet()) {
|
||||
if (checkNeedsDbInit(entry.getValue()))
|
||||
getDataStoreFile(runtimeConfig, realmConfig, entry.getKey());
|
||||
}
|
||||
|
||||
// then initialize the schemas
|
||||
for (Entry<String, DbMigrationState> entry : this.dbMigrationStates.entrySet()) {
|
||||
initSchemaFromDataStore(entry.getValue(), entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Certificate getCertificate() {
|
||||
return this.certificate;
|
||||
}
|
||||
}
|
|
@ -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!");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue