/**
* 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
*/
package org.objectweb.speedo.naming.lib;
import org.objectweb.fractal.api.control.BindingController;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.api.control.LifeCycleController;
import org.objectweb.jorm.api.PException;
import org.objectweb.jorm.api.PMapper;
import org.objectweb.jorm.naming.api.PName;
import org.objectweb.jorm.naming.api.PNameCoder;
import org.objectweb.perseus.cache.api.CacheManager;
import org.objectweb.speedo.api.SpeedoException;
import org.objectweb.speedo.api.SpeedoProperties;
import org.objectweb.speedo.mapper.api.JormFactory;
import org.objectweb.speedo.metadata.SpeedoClass;
import org.objectweb.speedo.naming.api.NamingManager;
import org.objectweb.speedo.naming.api.NamingManagerFactoryItf;
import org.objectweb.speedo.pm.api.POManagerFactoryItf;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import java.util.Arrays;
/**
* <img src="../api/NamingManagerFactory.gif"/>
* This small fractal component is in charge of the naming specialization in
* Speedo. This component is a factory of NamingManager.
* Each NamingManager manages a type of naming. Currently Speedo provides the
* following naming manager implementations:
* - UserIdCompositeNamingManager
* - UserIdSingleNamingManager
* - LongIdNamingManager
* - OLongIdNamingManager
* - RdbSequenceNamingManager
* The NamingManagerFactory has 3 dependencies:
* - The CacheManager permits for some PNamingContext to lookup persistent
* object in the cache before doing I/O (polymorphism case for instance).
* - The POManagerFactory permits to fetch the SequenceManager associated to
* the POMF.
* - The PMapper permits to NamingManager to use some internal persistent
* classes (ex generator).
*
* @see org.objectweb.speedo.naming.api.NamingManager
* @see org.objectweb.speedo.naming.lib.UserIdSingleNamingManager
* @see org.objectweb.speedo.naming.lib.UserIdCompositeNamingManager
* @see org.objectweb.speedo.naming.lib.RdbSequenceNamingManager
* @see org.objectweb.speedo.naming.lib.LongIdNamingManager
* @see org.objectweb.speedo.naming.lib.OLongIdNamingManager
* @see org.objectweb.speedo.naming.lib.PolymorphIdNamingManager
* @author S.Chassande-Barrioz
*/
public class NamingManagerFactory
implements NamingManagerFactoryItf, BindingController, LifeCycleController {
/**
* fractal binding name to the mapper
*/
public final static String MAPPER_BINDING = "mapper";
/**
* fractal binding name to the cache manager
*/
public final static String CACHE_MANAGER_BINDING = "cache-manager";
public final static String PMF_BINDING = "po-manager-factory";
private NamingManager[] namingManagers;
private PMapper mapper;
private CacheManager cache;
private POManagerFactoryItf pmf;
private Logger logger;
public NamingManagerFactory() {
init();
}
private void init() {
namingManagers = new NamingManager[]{
new UserIdSingleNamingManager(),
new RdbSequenceNamingManager(),
new UserIdCompositeNamingManager(),
new LongIdNamingManager(),
new OLongIdNamingManager(),
new PolymorphIdNamingManager()
};
}
public PMapper getMapper() {
return mapper;
}
public void setMapper(PMapper mapper) {
this.mapper = mapper;
if (started) {
for(int i=0; i<namingManagers.length; i++) {
try {
namingManagers[i].setPMapper(mapper);
} catch (PException e) {
if (logger != null) {
logger.log(BasicLevel.WARN, "The naming manager "
+ namingManagers[i] + " does not accept the mapper: ", e);
}
}
}
}
}
public CacheManager getCache() {
return cache;
}
public void setCache(CacheManager cache) {
this.cache = cache;
if (started) {
for(int i=0; i<namingManagers.length; i++) {
namingManagers[i].setCache(cache);
}
}
}
// IMPLEMENTATION OF THE UserBindingController INTERFACE //
//-------------------------------------------------------//
public String[] listFc() {
return new String[]{
MAPPER_BINDING,
CACHE_MANAGER_BINDING,
PMF_BINDING
};
}
public Object lookupFc(String s) {
if (MAPPER_BINDING.equals(s))
return mapper;
else if (CACHE_MANAGER_BINDING.equals(s))
return cache;
else if (PMF_BINDING.equals(s))
return pmf;
else
return null;
}
public void bindFc(String s, Object o) {
if ("logger".equals(s)) {
setLogger((Logger) o);
} else if (MAPPER_BINDING.equals(s)) {
setMapper((PMapper) o);
} else if (CACHE_MANAGER_BINDING.equals(s)) {
setCache((CacheManager) o);
} else if (PMF_BINDING.equals(s)) {
setPmf((POManagerFactoryItf) o);
}
}
public void unbindFc(String s) {
if (MAPPER_BINDING.equals(s)) {
setMapper(null);
} else if (CACHE_MANAGER_BINDING.equals(s)) {
setCache(null);
} else if (PMF_BINDING.equals(s)) {
setPmf(null);
}
}
private boolean started = false;
public String getFcState() {
return started ? STARTED : STOPPED;
}
public void startFc() throws IllegalLifeCycleException {
if (!started) {
started = true;
setPmf(pmf);
setMapper(mapper);
setCache(cache);
}
}
public void stopFc() throws IllegalLifeCycleException {
if (started) {
started = false;
}
}
public POManagerFactoryItf getPmf() {
return pmf;
}
public void setPmf(POManagerFactoryItf pmf) {
this.pmf = pmf;
for(int i=0; i<namingManagers.length; i++) {
namingManagers[i].setPmf(pmf);
}
}
public Logger getLogger() {
return logger;
}
public void setLogger(Logger logger) {
this.logger = logger;
for(int i=0; i<namingManagers.length; i++) {
namingManagers[i].setLogger(logger);
}
}
public synchronized void bindNamingManager(NamingManager nm) {
NamingManager[] neo = new NamingManager[namingManagers.length + 1];
System.arraycopy(namingManagers, 0, neo, 0, namingManagers.length);
neo[namingManagers.length] = nm;
namingManagers = neo;
}
public synchronized boolean unbindNamingManager(NamingManager nm) {
int idx = Arrays.binarySearch(namingManagers, nm);
if (idx >= 0) {
//put the last in place of the removed
namingManagers[idx] = namingManagers[namingManagers.length - 1];
//create a array without the lastest element
NamingManager[] neo = new NamingManager[namingManagers.length - 1];
System.arraycopy(namingManagers, 0, neo, 0, namingManagers.length - 1);
namingManagers = neo;
return true;
} else {
return false;
}
}
public NamingManager getNamingManager(SpeedoClass sc) throws SpeedoException {
for(int i=0; i<namingManagers.length; i++) {
if (namingManagers[i].canManage(sc)) {
return namingManagers[i];
}
}
throw new SpeedoException("No identity manager found for the class '"
+ sc.getFQName() + "', " + sc.getIdentityType() + ", " +
sc.getExtension(SpeedoProperties.VENDOR_NAME, SpeedoProperties.ID));
}
public NamingManager getNamingManager(String hints, ClassLoader classloader) throws PException {
for(int i=0; i<namingManagers.length; i++) {
if (namingManagers[i].canProvidePBinder(hints, classloader)) {
return namingManagers[i];
}
}
throw new PException("No identity manager found for the hints '"
+ hints + "'.");
}
public PName decode(PNameCoder pnc, Object oid, java.lang.Class clazz, JormFactory jf) throws PException {
for(int i=0; i<namingManagers.length; i++) {
PName pn = namingManagers[i].decode(pnc, oid, clazz, jf);
if (pn != null) {
return pn;
}
}
throw new PException("No identity manager able to decode:"
+ "\n\tpnc=" + pnc
+ "\n\toid=" + oid
+ "\n\tclazz=" + clazz);
}
public Object encode(PName pn) throws PException {
for(int i=0; i<namingManagers.length; i++) {
Object o = namingManagers[i].encode(pn);
if (o != null) {
return o;
}
}
throw new PException("No identity manager able to encode ("
+ pn + ")");
}
/**
* Clean the nmf.
*/
public void clean() {
init();
}
}