/**
* Copyright (C) 2001-2005 France Telecom R&D
*/
package org.objectweb.speedo.pm.lib;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.BindingController;
import org.objectweb.jorm.api.PException;
import org.objectweb.jorm.api.PMapper;
import org.objectweb.perseus.cache.api.CacheException;
import org.objectweb.perseus.cache.api.CacheManager;
import org.objectweb.perseus.cache.api.UnbindManager;
import org.objectweb.perseus.persistence.api.TransactionalPersistenceManager;
import org.objectweb.perseus.pool.api.Pool;
import org.objectweb.speedo.api.ExceptionHelper;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.mapper.api.ConnectionSpecFactory;
import org.objectweb.speedo.mapper.api.JormFactory;
import org.objectweb.speedo.mim.api.PersistentObjectItf;
import org.objectweb.speedo.pm.api.POManagerItf;
import org.objectweb.speedo.pm.api.POManagerFactoryItf;
import org.objectweb.speedo.pm.api.POManagerSwitchItf;
import org.objectweb.speedo.query.api.QueryManager;
import org.objectweb.speedo.sequence.api.SequenceManager;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import java.util.Collection;
import java.util.Properties;
import javax.jdo.JDODataStoreException;
import javax.jdo.JDOFatalInternalException;
/**
* Is a factory of POManagerItf. This primitive component exports the
* POManagerFactoryItf interface, permitting to manage the po manager
* allocations. Due to a high cost of POManagerItf allocation, the unsused
* POManagerItf are pooled. For this reason, the AbstractManagerFactory uses
* a Pool of POManagerItf. The AbstractPOManagerFactory manages also the
* attachement of POManagerItf to the current thread through a
* POManagerSwitchItf.
*
* @see org.objectweb.speedo.pm.api.POManagerItf
* @see org.objectweb.speedo.pm.api.POManagerFactoryItf
* @see org.objectweb.speedo.pm.api.POManagerSwitchItf
*
* @author S.Chassande-Barrioz
*/
public abstract class AbstractPOManagerFactory
implements POManagerFactoryItf, BindingController {
public final static String MAPPER_BINDING = "mapper";
public final static String JORM_FACTORY_BINDING = "jorm-factory";
public final static String PM_POOL_BINDING = "po-manager-pool";
public final static String PO_MANAGER_SWITCH_BINDING = "po-manager-switch";
public final static String TPM_BINDING = "transactional-persistence-manager";
public final static String CACHE_M_BINDING = "cache-manager";
public final static String UNBIND_M_BINDING = "unbind-manager";
public final static String COMPONENT_BINDING = "component";
public final static String SEQUENCE_M_BINDING = "sequence-manager";
public final static String QUERY_M_BINDING = "query-manager";
protected final static int GETMAXPOOL = 100;
protected boolean imbricatedAuthorized = true;
/**
* Pool of PersistenceManager
*/
protected Pool managedPM = null;
/**
* Manages the log's traces
*/
protected Logger logger = null;
/**
* JORM object encapsulating the datastore
*/
protected PMapper mapper = null;
/**
* The properties of the PMF
*/
protected Properties connectionProperties = null;
/**
* The PMS managing the association PM / thread
*/
protected POManagerSwitchItf pms = null;
/**
* The java reference to the current component
*/
protected Object _this = null;
/**
* Information about the data store connection
*/
protected ConnectionSpecFactory csf = null;
/**
* The fractal component status
*/
protected boolean started = false;
/**
* The L2 cache containing persistent objects.
*/
protected CacheManager cacheManager = null;
/**
* The L2 cache containing persistent objects.
*/
protected UnbindManager unbindManager = null;
/**
* The factory initializing JORM structure (Mapping, Binder, PNC, ...)
*/
protected JormFactory jormFactory = null;
/**
* The perseus component managing concurrency, caching and persitency.
*/
protected TransactionalPersistenceManager tpm = null;
/**
* The query manager
*/
protected QueryManager queryManager = null;
/**
* Speedo component managing the sequence (datastore or memory)
*/
protected SequenceManager sequenceManager = null;
protected Personality personality;
public AbstractPOManagerFactory(Personality p) {
connectionProperties = new Properties();
personality = p;
}
protected void start() {
started = true;
}
protected POManagerFactoryItf getThis() {
if (_this == null) {
throw new JDODataStoreException(
"Cannot provides a PersistenceManager without a reference to the component");
} else if (_this instanceof Component) {
try {
_this = ((Component)_this).getFcInterface("po-manager-factory");
} catch (NoSuchInterfaceException e) {
throw new JDODataStoreException(
"Cannot provides a PersistenceManager ", new Exception[]{e});
}
}
return (POManagerFactoryItf) _this;
}
/**
* Verify that an instance is persistence capable.
* @param pc the object to test.
* @exception RuntimeException if the object is not persistence capable.
*/
protected void assertIsPO(Object pc, String cmd) {
if (!(pc instanceof PersistentObjectItf)) {
if (pc == null) {
throw personality.newUserRuntimeException("Null persistent object instance specified");
} else if (pc.getClass().isArray()
|| pc instanceof Collection) {
throw personality.newUserRuntimeException("You must use the " + cmd
+ "All method with a multivalued parameter: " + pc);
} else {
throw personality.newUserRuntimeException("The object is not a PersistentObjectItf, beware to : " + pc);
}
}
}
// IMPLEMENTATION OF THE UserBindingController INTERFACE //
//-------------------------------------------------------//
public String[] listFc() {
return new String[] {
PM_POOL_BINDING,
MAPPER_BINDING,
PO_MANAGER_SWITCH_BINDING,
CACHE_M_BINDING,
UNBIND_M_BINDING,
JORM_FACTORY_BINDING,
TPM_BINDING,
SEQUENCE_M_BINDING
};
}
public Object lookupFc(String s) {
if (PM_POOL_BINDING.equals(s))
return managedPM;
else if (MAPPER_BINDING.equals(s))
return mapper;
else if (PO_MANAGER_SWITCH_BINDING.equals(s))
return pms;
else if (CACHE_M_BINDING.equals(s))
return cacheManager;
else if (UNBIND_M_BINDING.equals(s))
return unbindManager;
else if (JORM_FACTORY_BINDING.equals(s))
return jormFactory;
else if (TPM_BINDING.equals(s))
return tpm;
else if (SEQUENCE_M_BINDING.equals(s))
return sequenceManager;
else if (QUERY_M_BINDING.equals(s))
return queryManager;
else
return null;
}
public void bindFc(String s, Object o) {
if ("logger".equals(s)) {
logger = (Logger) o;
} else if (PM_POOL_BINDING.equals(s)) {
managedPM = (Pool) o;
} else if (MAPPER_BINDING.equals(s)) {
mapper = (PMapper) o;
} else if (PO_MANAGER_SWITCH_BINDING.equals(s)) {
pms = (POManagerSwitchItf) o;
} else if (CACHE_M_BINDING.equals(s)) {
cacheManager = (CacheManager) o;
} else if (UNBIND_M_BINDING.equals(s)) {
unbindManager = (UnbindManager) o;
} else if (COMPONENT_BINDING.equals(s)) {
_this = o;
} else if (JORM_FACTORY_BINDING.equals(s)) {
jormFactory = (JormFactory) o;
} else if (TPM_BINDING.equals(s)) {
tpm = (TransactionalPersistenceManager) o;
} else if (SEQUENCE_M_BINDING.equals(s)) {
sequenceManager = (SequenceManager) o;
} else if (QUERY_M_BINDING.equals(s)) {
queryManager = (QueryManager) o;
}
}
public void unbindFc(String s) {
if (PM_POOL_BINDING.equals(s)) {
managedPM = null;
} else if (MAPPER_BINDING.equals(s)) {
mapper = null;
} else if (PO_MANAGER_SWITCH_BINDING.equals(s)) {
pms = null;
} else if (CACHE_M_BINDING.equals(s)) {
cacheManager = null;
} else if (UNBIND_M_BINDING.equals(s)) {
unbindManager = null;
} else if (JORM_FACTORY_BINDING.equals(s)) {
jormFactory = null;
} else if (TPM_BINDING.equals(s)) {
tpm = null;
} else if (SEQUENCE_M_BINDING.equals(s)) {
sequenceManager = null;
} else if (QUERY_M_BINDING.equals(s)) {
queryManager = null;
}
}
// IMPLEMENTATION OF THE POManagerFactoryItf INTERFACE //
//-----------------------------------------------------//
public POManagerItf lookup() {
return pms.lookup(getThis());
}
public void bindPM2Thread(POManagerItf pm) {
if (logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG, "Bind a pm to the thread: " + pm);
}
pms.bind(pm);
}
public void unbindPM() {
if (logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG, "Unbind the current PM from the thread");
}
pms.unbind(getThis());
}
public void poManagerClosed(POManagerItf pr) {
try {
if (logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG, "Unbind a PM from the thread: " + pr);
}
pms.unbind(pr);
managedPM.releaseResource(pr);
} catch (Exception e) {
throw new JDOFatalInternalException(
"Impossible to release this PersistenceManager in the pool.",
new Exception[]{ExceptionHelper.getNested(e)});
}
}
public SequenceManager getSequenceManager() {
return sequenceManager;
}
public void setSequenceManager(SequenceManager sequenceManager) {
this.sequenceManager = sequenceManager;
}
public QueryManager getQueryManager(){
return queryManager;
}
public void setQueryManager(QueryManager queryManager){
this.queryManager = queryManager;
}
public void clean() {
try {
//clean the cache of objects
cacheManager.unbindAll();
//clean the query manager
queryManager.clean();
//clean the jorm factory
jormFactory.clean();
} catch(CacheException e) {
e.printStackTrace();
logger.log(BasicLevel.ERROR, "Error while cleaning the pmf: " + e.getMessage());
} catch (PException e) {
e.printStackTrace();
logger.log(BasicLevel.ERROR, "Error while cleaning the pmf: " + e.getMessage());
}
}
public Personality getPersonality() {
return personality;
}
/** Return non-configurable properties of this POManagerFactory.
* Properties with keys VendorName and VersionNumber are required. Other
* keys are optional.
* @return the non-configurable properties of this
* PersistenceManagerFactory.
*/
public Properties getProperties() {
return connectionProperties;
}
// IMPLEMENTATION OF THE PoolProvider INTERFACE //
//----------------------------------------------//
/**
* @return the owned <code>Pool</code>
*/
public Pool getPool() {
return managedPM;
}
}