package org.fosstrak.ale.server.readers.hal;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import org.fosstrak.hal.HardwareAbstraction;
import org.apache.log4j.Logger;
/**
* the HALManager creates and maintains instances of the HAL readers.
* @author swieland
*
*/
public class HALManager {
/**
* internal helper class to store HardwareAbstraction readers with
* a reference counter.
*
*/
private class HALManagerEntry {
/** the HAL reader itself. */
private HardwareAbstraction hal = null;
/** how many references onto this hal. */
private int referenced = 0;
/**
* creates a helper.
* @param hal the HAL reader.
*/
public HALManagerEntry(HardwareAbstraction hal) {
this.hal = hal;
referenced = 1;
}
/**
* increases the link counter on the stored HAL object.
*/
public void lease() {
referenced++;
}
/**
* decreases the link counter on the stored HAL object.
* @return the number of links on the stored HAL object.
*/
public int unlease() {
referenced--;
return referenced;
}
/**
* returns the stored HAL object.
* @return returns the stored HAL object.
*/
public HardwareAbstraction get() {
return hal;
}
}
/** the singleton of the HALManager. */
private static HALManager instance = null;
/** a hash map that stores the instances of the HAL readers. */
private Map<String, HALManagerEntry> hals = null;
/** logger. */
private static final Logger log = Logger.getLogger(HALAdaptor.class);
/** private constructor. we want only a singleton. */
private HALManager() {
hals = new HashMap<String, HALManagerEntry>();
};
/**
* define a new HardwareAbstraction reader. if the reader already exists
* a reference to the reader is returned. otherwise a new reader is created.
* @param halName the name of the HAL reader that shall be created.
* @param propFile the properties file for the reader.
* @param ImplementingClass the class to invoke that implements the hal
* (eg. org.fosstrak.hal.impl.sim.SimulatorController).
* @return an instance of a HardwareAbstraction reader.
*/
public synchronized HardwareAbstraction define(
String halName, String propFile, String ImplementingClass) {
HardwareAbstraction hal = null;
if (hals.containsKey(halName)) {
HALManagerEntry entry = hals.get(halName);
hal = entry.get();
entry.lease();
log.debug("reusing running HAL instance: " + halName);
} else {
try {
Class<?> cls = Class.forName(ImplementingClass);
// get the constructor
Constructor<?> ctor =
cls.getConstructor(String.class, String.class);
// invoke the constructor
Object instnc = ctor.newInstance(halName, propFile);
if (instnc instanceof HardwareAbstraction) {
hal = (HardwareAbstraction) instnc;
hals.put(halName, new HALManagerEntry(hal));
log.debug("creating new HAL instance: " + halName);
return hal;
}
return null;
} catch (ClassNotFoundException e) {
log.error(String.format(
"implementing class '%s' not found!",
ImplementingClass));
} catch (SecurityException e) {
log.error(String.format(
"security exception when creating " +
"instance of '%s'!",
ImplementingClass));
} catch (NoSuchMethodException e) {
log.error(String.format(
"class '%s' has no constructor of form " +
"(String halName, String configFile)!",
ImplementingClass));
} catch (IllegalArgumentException e) {
log.error(String.format(
"illegal arguments when invoking constructor on " +
"class '%s'!",
ImplementingClass));
} catch (InstantiationException e) {
log.error(String.format(
"could not create instance of class '%s'!",
ImplementingClass));
} catch (IllegalAccessException e) {
log.error(String.format(
"illegal class exception when creating " +
"instance of '%s'!",
ImplementingClass));
} catch (InvocationTargetException e) {
log.error(String.format(
"could not invoke constructor on class '%s'!",
ImplementingClass));
}
return null;
}
return hal;
}
/**
* removes a HAL reader. if there is no other adaptor using the instance
* of this HAL reader, the HAL will be destroyed.
* @param halName the name of the HAL reader that shall be undefined.
*/
public synchronized void undefine(String halName) {
if (hals.containsKey(halName)) {
int leases = hals.get(halName).unlease();
if (leases < 1) {
// need to undefine the hal
hals.remove(halName);
log.debug("there are no other instances using : " +
halName + ". therefor destroy it.");
} else {
log.debug("there are other instances still using : " +
halName + ". therefor do not destroy it.");
}
}
}
/**
* create the singleton instance of the HALManager.
* @return an instance of the singleton HALManager.
*/
public static synchronized HALManager getInstance() {
if (HALManager.instance == null) {
HALManager.instance = new HALManager();
}
return HALManager.instance;
}
}