/**
* Copyright (C) 2001-2005 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.objectweb.speedo.pm.lib;
import org.objectweb.fractal.adl.Factory;
import org.objectweb.fractal.adl.FactoryFactory;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.Interface;
import org.objectweb.fractal.api.control.BindingController;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.api.control.LifeCycleController;
import org.objectweb.fractal.util.Fractal;
import org.objectweb.perseus.pool.api.PoolMatchFactory;
import org.objectweb.perseus.pool.api.PoolException;
import org.objectweb.perseus.persistence.api.ConnectionHolderFactory;
import org.objectweb.speedo.pm.api.POManagerInstanciatorAC;
import org.objectweb.speedo.pm.api.POManagerItf;
import org.objectweb.speedo.pm.jdo.lib.JDOPOManager;
import org.objectweb.speedo.workingset.api.TransactionItf;
import org.objectweb.speedo.workingset.lib.AbstractTransaction;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import java.util.HashMap;
import java.util.Map;
import java.util.Arrays;
/**
* is a primitive components in charge of the POManagerItf and the TransactionItf
* allocation. It exports the PoolMatchFactory interface in order to be used by
* a Pool as Factory of pool resource. The pool resource is POManagerItf
* instances.
* It uses a ConnectionHolderFactory for allocating ConnectionHolder to the
* created TransactionItf components.
*
* @see org.objectweb.speedo.pm.api.POManagerItf
* @see org.objectweb.speedo.workingset.api.TransactionItf
* @see org.objectweb.perseus.persistence.api.ConnectionHolder
* @see org.objectweb.perseus.persistence.api.ConnectionHolderFactory
*
* @author S.Chassande-Barrioz
*/
public class POManagerInstanciatorImpl
implements PoolMatchFactory, BindingController, LifeCycleController, POManagerInstanciatorAC {
public final static String CONNECTION_HOLDER_FACTORY_BINDING = "connection-holder-factory";
public final static String COMPONENT_BINDING = "component";
/**
* The factory if ConnectionHolder used at JDOTransactionItf instanciation time.
*
* @see org.objectweb.perseus.persistence.api.ConnectionHolder
* @see org.objectweb.perseus.persistence.api.ConnectionHolderFactory
*/
private ConnectionHolderFactory chf;
/**
* The current component interface.
*/
private Component thisC = null;
/**
* The template of the POManagerItf component to instanciate
*/
private Component pmT;
/**
* The template of the JDOTransactionItf component to instanciate
*/
private Component tT;
/**
* life cycle status of the current component
*/
private boolean started = false;
private String pmTemplate;
private String txTemplate;
private Logger logger;
/**
* The array of common components required by a POManagerItf and JDOTransactionItf
* components. At each index matches a particular component ( see the
* XXX_COMPONENT_IDX fields).
*
* @see #PMF_COMPONENT_IDX
* @see #MAPPER_COMPONENT_IDX
* @see #JF_COMPONENT_IDX
* @see #PNC_COMPONENT_IDX
* @see #QM_COMPONENT_IDX
* @see #TPM_COMPONENT_IDX
*/
Object[] components = new Object[6];
private final static byte PMF_COMPONENT_IDX = 0;
private final static byte MAPPER_COMPONENT_IDX = PMF_COMPONENT_IDX + 1;
private final static byte JF_COMPONENT_IDX = MAPPER_COMPONENT_IDX + 1;
private final static byte PNC_COMPONENT_IDX = JF_COMPONENT_IDX + 1;
private final static byte QM_COMPONENT_IDX = PNC_COMPONENT_IDX + 1;
private final static byte TPM_COMPONENT_IDX = QM_COMPONENT_IDX + 1;
/**
* The reference the composite component containing the POManagerItf and
* JDOTransactionItf components to instanciate.
*/
Component speedoComponent = null;
void clearComponentRef() {
Arrays.fill(components, null);
}
/**
* Fills the components array with components required by a POManagerItf and
* JDOTransactionItf components.
*/
void fetchComponentRef() throws Exception {
speedoComponent = Fractal.getSuperController(thisC).getFcSuperComponents()[0];
Component[] children = Fractal.getContentController(speedoComponent)
.getFcSubComponents();
for (int i = 0; i < children.length; i++) {
String name = Fractal.getNameController(children[i]).getFcName();
if ("po-manager-factory".equals(name)) {
components[PMF_COMPONENT_IDX] = children[i].getFcInterface("po-manager-factory");
} else if ("mapper".equals(name)) {
components[MAPPER_COMPONENT_IDX] = children[i].getFcInterface("mapper");
components[JF_COMPONENT_IDX] = children[i].getFcInterface("jorm-factory");
components[PNC_COMPONENT_IDX] = children[i].getFcInterface("pname-coder");
} else if ("query-manager".equals(name)) {
components[QM_COMPONENT_IDX] = children[i].getFcInterface("query-manager");
} else if ("tpm".equals(name)) {
components[TPM_COMPONENT_IDX] = children[i].getFcInterface("transactional-persistence-manager");
}
}
Factory factory = FactoryFactory.getFactory(FactoryFactory.FRACTAL_BACKEND);
Map ctxt = new HashMap();
ctxt.put("template", "true");
pmT = (Component) factory.newComponent(pmTemplate, ctxt);
tT = (Component) factory.newComponent(txTemplate, ctxt);
}
// IMPLEMENTATION OF THE UserBindingController INTERFACE //
//-------------------------------------------------------//
public String getFcState() {
return started ? STARTED : STOPPED;
}
/**
* Startes the component by computing the components array.
*/
public void startFc() throws IllegalLifeCycleException {
started = true;
try {
fetchComponentRef();
} catch (Exception e) {
if (logger != null) {
logger.log(BasicLevel.ERROR, "Impossible to fetch inner speedo components", e);
}
throw new IllegalLifeCycleException(e.getMessage());
}
}
/**
* Clears the components array.
*/
public void stopFc() throws IllegalLifeCycleException {
started = false;
clearComponentRef();
}
// IMPLEMENTATION OF THE UserBindingController INTERFACE //
//-------------------------------------------------------//
public String[] listFc() {
return new String[]{CONNECTION_HOLDER_FACTORY_BINDING};
}
public Object lookupFc(String c) {
if (CONNECTION_HOLDER_FACTORY_BINDING.equals(c)) {
return chf;
} else {
return null;
}
}
public void bindFc(String c, Object s) {
if ("logger".equals(c)) {
logger = (Logger) s;
} else if (CONNECTION_HOLDER_FACTORY_BINDING.equals(c)) {
chf = (ConnectionHolderFactory) s;
} else if (COMPONENT_BINDING.equals(c)) {
thisC = (Component) s;
}
}
public void unbindFc(String c) {
if (CONNECTION_HOLDER_FACTORY_BINDING.equals(c)) {
chf = null;
}
}
// IMPLEMENTATION OF THE POManagerInstanciatorAC INTERFACE //
//---------------------------------------------------------//
public String getPOManagerTemplateName() {
return pmTemplate;
}
public void setPOManagerTemplateName(String n) {
pmTemplate = n;
}
public String getTransactionTemplateName() {
return txTemplate;
}
public void setTransactionTemplateName(String n) {
txTemplate = n;
}
// IMPLEMENTATION OF THE PoolMathcFactory INTERFACE //
//--------------------------------------------------//
/**
* Creates a new <code>PoolResource</code>.
* This methos is invoked by the owned <code>Pool</code>.
* A new JDOPOManager and a new JDOTransaction component are
* created, and added into the Speedo composite.
*
* @param o params used to build a new PoolResource
* @return the build <code>JDOPOManager</code>
*/
public Object createResource(Object o) throws PoolException {
try {
//instanciate the POManagerItf
Component pmC = Fractal.getFactory(pmT).newFcInstance();
POManagerItf pm = (POManagerItf) pmC.getFcInterface("po-manager");
Fractal.getNameController(pmC).setFcName("po-manager");
BindingController pmBC = Fractal.getBindingController(pmC);
//instanciate the JDOTransactionItf
Component tC = Fractal.getFactory(tT).newFcInstance();
Fractal.getNameController(tC).setFcName("transaction");
TransactionItf t = (TransactionItf) tC.getFcInterface("transaction");
BindingController tBC = Fractal.getBindingController(tC);
//Add the new components into the Speedo composite
Fractal.getContentController(speedoComponent).addFcSubComponent(pmC);
Fractal.getContentController(speedoComponent).addFcSubComponent(tC);
//add bindings on the po manager
pmBC.bindFc(JDOPOManager.JORM_FACTORY_BINDING,
components[JF_COMPONENT_IDX]);
pmBC.bindFc(JDOPOManager.PNAME_CODER_BINDING,
components[PNC_COMPONENT_IDX]);
pmBC.bindFc(JDOPOManager.PO_MANAGER_FACTORY_BINDING,
components[PMF_COMPONENT_IDX]);
pmBC.bindFc(JDOPOManager.QUERY_MANAGER_BINDING,
components[QM_COMPONENT_IDX]);
pmBC.bindFc(JDOPOManager.TRANSACTIONAL_PERSISTENCE_MANAGER_BINDING,
components[TPM_COMPONENT_IDX]);
pmBC.bindFc(JDOPOManager.TRANSACTION_BINDING, t);
//add bindings on the transaction
tBC.bindFc(AbstractTransaction.PO_MANAGER_BINDING, pm);
tBC.bindFc(AbstractTransaction.TRANSACTIONAL_PERSISTENCE_MANAGER_BINDING,
components[TPM_COMPONENT_IDX]);
tBC.bindFc(AbstractTransaction.MAPPER_BINDING,
components[MAPPER_COMPONENT_IDX]);
//Add a ConenctionHolder to the transaction
t.setConnectionHolder(chf.createConnectionHolder());
//start components
Fractal.getLifeCycleController(pmC).startFc();
Fractal.getLifeCycleController(tC).startFc();
return pm;
} catch (Exception e) {
PoolException pe = new PoolException(
"Error during the allocation of a new POManagerItf and its WorkingSet", e);
logger.log(BasicLevel.ERROR, pe.getMessage() + ": " + e.getMessage(), e);
throw pe;
}
}
public boolean matchResource(Object resource, Object o) {
return true;
}
/**
* It removes the POManagerItf and the JDOTransactionItf components from the
* Speedo composite.
* @param resource is the POManagerItf to destroy.
*/
public void destroyResource(Object resource) {
try {
//fetch the PM component
Component pmC = ((Interface) resource).getFcItfOwner();
BindingController pmBC = Fractal.getBindingController(pmC);
//fetch the Tx component
Component tC = ((Interface)
pmBC.lookupFc(AbstractPOManager.TRANSACTION_BINDING))
.getFcItfOwner();
BindingController tBC = Fractal.getBindingController(tC);
//Stop compoenents
Fractal.getLifeCycleController(pmC).stopFc();
Fractal.getLifeCycleController(tC).stopFc();
//remove bindings of the PM component
pmBC.unbindFc(AbstractPOManager.JORM_FACTORY_BINDING);
pmBC.unbindFc(AbstractPOManager.PNAME_CODER_BINDING);
pmBC.unbindFc(AbstractPOManager.PO_MANAGER_FACTORY_BINDING);
pmBC.unbindFc(AbstractPOManager.QUERY_MANAGER_BINDING);
pmBC.unbindFc(AbstractPOManager.TRANSACTIONAL_PERSISTENCE_MANAGER_BINDING);
pmBC.unbindFc(AbstractPOManager.TRANSACTION_BINDING);
//remove bindings of the Tx component
tBC.unbindFc(AbstractTransaction.PO_MANAGER_BINDING);
tBC.unbindFc(AbstractTransaction.TRANSACTIONAL_PERSISTENCE_MANAGER_BINDING);
tBC.unbindFc(AbstractTransaction.MAPPER_BINDING);
//remove both components from the composite
//TODO: find a way to remove sub components without stopping Speedo !!!
//Fractal.getContentController(speedoComponent).removeFcSubComponent(pmC);
//Fractal.getContentController(speedoComponent).removeFcSubComponent(tC);
} catch (Exception e) {
if (logger != null) {
logger.log(BasicLevel.WARN, "Error during the destroying of a POManagerItf", e);
}
}
}
}