/*
* 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.xmlpers.impl;
import java.io.File;
import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import li.strolch.utils.helper.PropertiesHelper;
import li.strolch.utils.helper.StringHelper;
import li.strolch.xmlpers.api.IoMode;
import li.strolch.xmlpers.api.PersistenceConstants;
import li.strolch.xmlpers.api.PersistenceContextFactoryDelegator;
import li.strolch.xmlpers.api.PersistenceManager;
import li.strolch.xmlpers.api.PersistenceTransaction;
import li.strolch.xmlpers.api.XmlPersistenceException;
import li.strolch.xmlpers.objref.LockableObject;
import li.strolch.xmlpers.objref.ObjectReferenceCache;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*
*/
public class DefaultPersistenceManager implements PersistenceManager {
protected static final Logger logger = LoggerFactory.getLogger(DefaultPersistenceManager.class);
protected boolean initialized;
protected boolean verbose;
protected IoMode defaultIoMode;
protected Properties properties;
protected Map<String, DefaultPersistenceRealm> realmMap;
private PersistenceContextFactoryDelegator ctxFactory;
public void initialize(Properties properties) {
if (this.initialized)
throw new IllegalStateException("Already initialized!"); //$NON-NLS-1$
String context = DefaultPersistenceManager.class.getSimpleName();
// get properties
boolean verbose = PropertiesHelper.getPropertyBool(properties, context, PersistenceConstants.PROP_VERBOSE,
Boolean.FALSE).booleanValue();
String ioModeS = PropertiesHelper.getProperty(properties, context, PersistenceConstants.PROP_XML_IO_MOD,
IoMode.DOM.name());
IoMode ioMode = IoMode.valueOf(ioModeS);
long lockTime = PropertiesHelper.getPropertyLong(properties, context,
PersistenceConstants.PROP_LOCK_TIME_MILLIS, 10000L);
// set lock time on LockableObject
try {
Field lockTimeField = LockableObject.class.getDeclaredField("tryLockTime");//$NON-NLS-1$
lockTimeField.setAccessible(true);
lockTimeField.setLong(null, lockTime);
logger.info("Using a max lock acquire time of " + StringHelper.formatMillisecondsDuration(lockTime)); //$NON-NLS-1$
} catch (SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("Failed to configure tryLockTime on LockableObject!", e); //$NON-NLS-1$
}
// validate base path
validateBasePath(properties);
this.properties = properties;
this.verbose = verbose;
this.defaultIoMode = ioMode;
this.realmMap = new HashMap<>();
this.ctxFactory = new PersistenceContextFactoryDelegator();
}
private void validateBasePath(Properties properties) {
String context = DefaultPersistenceManager.class.getSimpleName();
String basePath = PropertiesHelper.getProperty(properties, context, PersistenceConstants.PROP_BASEPATH, null);
// validate base path exists and is writable
File basePathF = new File(basePath);
if (!basePathF.exists())
throw new XmlPersistenceException(MessageFormat.format("The database store path does not exist at {0}", //$NON-NLS-1$
basePathF.getAbsolutePath()));
if (!basePathF.canWrite())
throw new XmlPersistenceException(MessageFormat.format("The database store path is not writeable at {0}", //$NON-NLS-1$
basePathF.getAbsolutePath()));
}
@Override
public PersistenceContextFactoryDelegator getCtxFactory() {
return this.ctxFactory;
}
@Override
public PersistenceTransaction openTx() {
return openTx(DEFAULT_REALM);
}
@Override
public synchronized PersistenceTransaction openTx(String realmName) {
DefaultPersistenceRealm persistenceRealm = this.realmMap.get(realmName);
if (persistenceRealm == null) {
PathBuilder pathBuilder = new PathBuilder(realmName, this.properties);
ObjectReferenceCache objectRefCache = new ObjectReferenceCache(realmName);
persistenceRealm = new DefaultPersistenceRealm(realmName, this, this.ctxFactory, pathBuilder,
objectRefCache);
this.realmMap.put(realmName, persistenceRealm);
}
PersistenceTransaction tx = new DefaultPersistenceTransaction(persistenceRealm, this.verbose);
tx.setIoMode(this.defaultIoMode);
return tx;
}
}