/*
* Created on Jan 28, 2005
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package com.idega.repository.data;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
/**
* @author thomas
*
* A container for singletons.
*
* Must be switched on and off by using start() and stop() methods.
*
* Call getInstance for getting a singleton using an Instantiator.
*
* When shutting down call the class method stop.
*
*/
public class SingletonRepository {
private static volatile SingletonRepository singletonRepository = null;
private static volatile boolean hasBeenStopped = false;
//Singleton holder map implementation changed to ConcurrentHashMap to improve synchronization.
private ConcurrentMap<String, SingletonInstantiatorBean> map = new ConcurrentHashMap<String, SingletonInstantiatorBean>();
private SingletonRepository() {
// empty
}
public static synchronized void start() {
if (singletonRepository != null) {
// nothing to do, start already called!
Logger.getLogger(singletonRepository.getClass().getName()).finest("["+ SingletonRepository.class.getName()+"] Note: Tried to start Repository again but it is already running (this is usually not an error or problem)");
return;
}
singletonRepository = new SingletonRepository();
hasBeenStopped=false;
Logger.getLogger(singletonRepository.getClass().getName()).info("["+ SingletonRepository.class.getName()+"] Repository started");
}
public static synchronized void stop() {
hasBeenStopped=true;
if (singletonRepository == null) {
// nothing to do
return;
}
singletonRepository.destroy();
Logger.getLogger(singletonRepository.getClass().getName()).info("["+ SingletonRepository.class.getName()+"] Repository stopped");
singletonRepository = null;
}
/**
* <p>
* This method should be called only after the start() method has been invoked once, and not after the stop() method has been called.
* </p>
* @return An instance of the SingletonRepository if it is correctly initialized
* @throws RuntimeException if no instance is initialized.
*/
public static SingletonRepository getRepository() {
if (singletonRepository == null) {
synchronized (SingletonRepository.class) {
if (hasBeenStopped) {
throw new RuntimeException(
"SingletonRepsitory has been stopped so no instance exists.");
}
start();
}
}
return singletonRepository;
}
public Object getInstance(Class singletonClass, Instantiator instantiator) {
String singletonName = singletonClass.getName();
SingletonInstantiatorBean bean = map.get(singletonName);
if (bean != null) {
return bean.getSingleton();
}
bean = map.putIfAbsent(singletonName,
new SingletonInstantiatorBean(instantiator.getInstance(), instantiator));
//if bean == null, then it's first time it is added, else - another thread put it.
return bean != null ? bean.getSingleton() : map.get(singletonName).getSingleton();
}
public Object getInstanceUsingIdentifier(Class singletonClass, Instantiator instantiator, Object parameter, String identifier) {
String singletonName = singletonClass.getName() + "_" + identifier;
SingletonInstantiatorBean bean = map.get(singletonName);
if (bean != null) {
return bean.getSingleton();
}
bean = map.putIfAbsent(singletonName,
new SingletonInstantiatorBean(instantiator.getInstance(parameter), instantiator));
return bean != null ? bean.getSingleton() : map.get(singletonName).getSingleton();
}
public Object getInstance(Class singletonClass, Instantiator instantiator, Object parameter) {
String singletonName = singletonClass.getName();
SingletonInstantiatorBean bean = map.get(singletonName);
if (bean != null) {
return bean.getSingleton();
}
bean = map.putIfAbsent(singletonName,
new SingletonInstantiatorBean(instantiator.getInstance(parameter), instantiator));
return bean != null ? bean.getSingleton() : map.get(singletonName).getSingleton();
}
public Object getExistingInstanceOrNull(Class singletonClass) {
SingletonInstantiatorBean singletonInstantiatorBean = map.get(singletonClass.getName());
return singletonInstantiatorBean != null ? singletonInstantiatorBean.getSingleton() : null;
}
public void unloadInstance(Class singletonClass) {
String singletonName = singletonClass.getName();
SingletonInstantiatorBean bean = map.remove(singletonName);
if (bean != null) {
unload(bean.getInstantiator());
}
}
public void unloadInstance(Class singletonClass, String identifier) {
String singletonName = singletonClass.getName() + "_" + identifier;
SingletonInstantiatorBean bean = map.remove(singletonName);
if (bean != null) {
unload(bean.getInstantiator());
}
}
private void destroy() {
Iterator<SingletonInstantiatorBean> iterator = this.map.values().iterator();
while (iterator.hasNext()) {
SingletonInstantiatorBean bean = iterator.next();
unload(bean.getInstantiator());
}
}
private void unload(Instantiator instantiator) {
instantiator.unload();
}
/**
* Class for storing singleton/instantiator data.
*
*/
private static class SingletonInstantiatorBean {
private Object singleton;
private Instantiator instantiator;
public SingletonInstantiatorBean(Object singleton, Instantiator instantiator) {
this.singleton = singleton;
this.instantiator = instantiator;
}
public Object getSingleton() {
return singleton;
}
public Instantiator getInstantiator() {
return instantiator;
}
}
}