/**
* Speedo: an implementation of JDO compliant personality on top of JORM generic
* I/O sub-system.
* Copyright (C) 2001-2004 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
*
*
*
* Contact: speedo@objectweb.org
*
*/
package org.objectweb.speedo.sequence.lib;
import java.util.HashMap;
import java.util.Map;
import org.objectweb.fractal.api.control.BindingController;
import org.objectweb.jorm.api.PClassMapping;
import org.objectweb.jorm.api.PException;
import org.objectweb.jorm.api.PMapper;
import org.objectweb.jorm.facility.naming.generator.LongGenMgr;
import org.objectweb.jorm.facility.naming.generator.LongGenMgrRegistry;
import org.objectweb.jorm.facility.naming.rdbsequence.RdbSequenceLongGen;
import org.objectweb.jorm.mapper.rdb.lib.PMapperRdb;
import org.objectweb.speedo.sequence.api.SpeedoSequenceItf;
import org.objectweb.speedo.sequence.lib.SpeedoSequence;
import org.objectweb.speedo.api.ExceptionHelper;
import org.objectweb.speedo.pm.api.POManagerFactoryItf;
import org.objectweb.speedo.sequence.api.SequenceManager;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
/**
* The SpeedoSequenceManager
* @author Y.Bersihand
*/
public class SpeedoSequenceManager implements SequenceManager, BindingController {
public final static String PMF_BINDING = "po-manager-factory";
public final static String MAPPER_BINDING = "mapper";
public final static String MAPPER_RDB_BINDING = "mapper-rdb";
/**
* JORM object encapsulating the datastore
*/
private PMapper mapper = null;
/**
* JORM object encapsulating the datastore but in rdb version (optional)
*/
private PMapperRdb mapperRdb = null;
/**
* The PMF
*/
private POManagerFactoryItf pmf = null;
/**
* Manages the log's traces
*/
private Logger logger = null;
public Logger getLogger() {
return logger;
}
public void setLogger(Logger logger) {
this.logger = logger;
}
public PMapper getMapper() {
return mapper;
}
public void setMapper(PMapper mapper) {
this.mapper = mapper;
}
public PMapperRdb getMapperRdb() {
return mapperRdb;
}
public void setMapperRdb(PMapperRdb mapperRdb) {
this.mapperRdb = mapperRdb;
}
// IMPLEMENTATION OF THE UserBindingController INTERFACE //
//-------------------------------------------------------//
public String[] listFc() {
return new String[] {
PMF_BINDING,
MAPPER_BINDING,
MAPPER_RDB_BINDING
};
}
public Object lookupFc(String s) {
if (PMF_BINDING.equals(s)) {
return pmf;
} else if(MAPPER_BINDING.equals(s)) {
return mapper;
} else if (MAPPER_RDB_BINDING.equals(s)) {
return mapperRdb;
} else
return null;
}
public void bindFc(String s, Object o) {
if ("logger".equals(s)) {
logger = (Logger) o;
} else if (PMF_BINDING.equals(s)) {
pmf = (POManagerFactoryItf) o;
} else if (MAPPER_BINDING.equals(s)) {
mapper = (PMapper) o;
} else if (MAPPER_RDB_BINDING.equals(s)) {
mapperRdb = (PMapperRdb) o;
}
}
public void unbindFc(String s) {
if (PMF_BINDING.equals(s)) {
pmf = null;
} else if (MAPPER_BINDING.equals(s)) {
mapper = null;
} else if (MAPPER_RDB_BINDING.equals(s)) {
mapperRdb = null;
}
}
// IMPLEMENTATION OF THE SequenceManager INTERFACE //
//--------------------------------------------------//
/**
* Map of sequences defined for the pmf.
* The Map key is the fully qualified sequence name,
* i.e "packageName.sequenceName".
*/
private Map sequenceName2sequences = new HashMap();
/**
* The long generator manager
*/
private Object longGenMgr = null;
/**
* Get the long generator manager.
*/
public Object getLongGenMgr() {
return longGenMgr;
}
/**
* Set the long generator manager.
*/
public void setLongGenMgr(Object longGenMgr) {
if (longGenMgr instanceof LongGenMgr) {
this.longGenMgr = longGenMgr;
}
}
/**
* Add the sequence if not already registered in the list.
* The key is the fully qualified name of the sequence,
* i.e "packageName.sequenceName".
* @param sequence
*/
public void addSequence(Object sequence) {
if (sequence instanceof SpeedoSequence) {
SpeedoSequence s = (SpeedoSequence) sequence;
String fqName = (s.packageName == null )?(""):(s.packageName + ".") + s.name;
//if the sequence is not already registered
if (!sequenceName2sequences.containsKey(fqName)) {
sequenceName2sequences.put(fqName, s);
s.setSequenceManager(this);
}
}
}
/**
* Try to remove the sequence identified by the sequenceName.
* If the sequence does not exist, nothing is done.
* @param sequenceName the fully qualified name of the sequence,
* i.e "packageName.sequenceName".
*/
public void removeSequence(String sequenceName) {
sequenceName2sequences.remove(sequenceName);
}
/**
* Return the sequence associated to the name parameter.
* If no sequence is found, return null.
* @param name the fully qualified name of the sequence,
* i.e "packageName.sequenceName".
*/
public SpeedoSequenceItf getSequence(String name) {
SpeedoSequence s = (SpeedoSequence) sequenceName2sequences.get(name);
if (s != null) {
try {
initSequence(s);
} catch (Exception e) {
logger.log(BasicLevel.ERROR,
"Impossible to get the sequence "
+ name, ExceptionHelper.getNested(e));
return null;
}
}
return s;
}
public POManagerFactoryItf getPMF() {
return pmf;
}
public void setPMF(POManagerFactoryItf pmf) {
this.pmf = pmf;
}
/**
* Assuming this sequence is registered,
* init the sequence:
* - on the datastore if the sequence has a datastore name
* - in memory if the sequence has no datastore name
* If the sequence does not exist, do nothing.
* @throws PException
*/
private void initSequence(Object sequence) throws PException {
if (sequence instanceof SpeedoSequence) {
try {
SpeedoSequence s = (SpeedoSequence) sequence;
//if the sequence is not a rdb sequence, use jf_longGen table
if (s.datastoreName == null || s.datastoreName.equals("")) {
if (longGenMgr == null) {
//try to find the long gen manager in the registry
synchronized (LongGenMgrRegistry.class) {
longGenMgr = LongGenMgrRegistry.getLongGenMgr(mapper);
if (longGenMgr == null) {
//if not already registered, create it
try {
longGenMgr = (LongGenMgr) Class.forName(getLongGenMgrName()).newInstance();
} catch (Exception e) {
throw new PException(e, "Cannot create LongGenMgr (probably a ClassLoader problem): " + getLongGenMgrName());
}
((LongGenMgr) longGenMgr).init(mapper, PClassMapping.CREATE_STRUCTURE_IF_NEEDED);
// and register it
LongGenMgrRegistry.registerLonGenMgr((LongGenMgr)longGenMgr);
}
}
}
//create the long gen and associate it to the sequence
s.setLongGen(((LongGenMgr) longGenMgr).getLongGen(s.getName()));
} else {
//else, use rdb_sequence_long_gen
if (mapperRdb != null) {
if (s.getLongGen() == null) {
RdbSequenceLongGen rdbLongGen = new RdbSequenceLongGen(mapperRdb, s.datastoreName, false);
if(s.start != null) {
rdbLongGen.setSequenceStart(s.start);
}
if(s.increment != null) {
rdbLongGen.setSequenceIncrement(s.increment);
}
if(s.cache != null) {
rdbLongGen.setSequenceStart(s.cache);
}
//create it
Object conn = mapperRdb.getConnection();
rdbLongGen.createSequence(conn);
//and associate it to the sequence
s.setLongGen(rdbLongGen);
//close the connection
mapperRdb.closeConnection(conn);
}
} else {
throw new PException("Problem while init the sequence "
+ ((SpeedoSequence)sequence).getName() + ": "
+ "a rdb sequence has been defined in a jdo file and no rdb is linked to the application.");
}
}
} catch (Exception e) {
throw new PException(e, "Problem while init the sequence " + ((SpeedoSequence)sequence).getName());
}
}
}
/**
* Calculates the class name of the LongGenMgr from the mapper name. Indeed
* the class is the generated PClassMapping of the persistent class
* org.objectweb.jorm.facility.naming.generator.LongGenIncr.
*/
private String getLongGenMgrName() {
String mn = mapper.getMapperName();
int idx = mn.indexOf('.');
if (idx != -1) {
mn = mn.substring(0, idx);
}
return "org.objectweb.jorm.facility.naming.generator."
+ mn + ".LongGenIncrMapping";
}
}