package org.fosstrak.ale.server.readers.llrp;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import kr.ac.kaist.resl.fosstrak.ale.Adaptor;
import kr.ac.kaist.resl.fosstrak.ale.AdaptorManagement;
import org.apache.log4j.Logger;
/*
import org.fosstrak.llrp.adaptor.Adaptor;
import org.fosstrak.llrp.adaptor.AdaptorManagement;
*/
import org.fosstrak.llrp.adaptor.exception.LLRPRuntimeException;
import org.fosstrak.llrp.client.LLRPExceptionHandler;
import org.fosstrak.llrp.client.LLRPExceptionHandlerTypeMap;
import org.fosstrak.llrp.client.LLRPMessageItem;
import org.fosstrak.llrp.client.MessageHandler;
import org.fosstrak.llrp.client.ROAccessReportsRepository;
import org.fosstrak.llrp.client.Repository;
import org.fosstrak.llrp.client.RepositoryFactory;
import org.llrp.ltk.exceptions.InvalidLLRPMessageException;
import kr.ac.kaist.resl.ltk.generated.messages.RO_ACCESS_REPORT;
import kr.ac.kaist.resl.ltk.generated.parameters.LLRPStatus;
import org.llrp.ltk.types.LLRPMessage;
import org.springframework.stereotype.Service;
/**
* the LLRPManager is a singleton providing access to the llrp-client-adaptor. the
* manager starts an instance of the llrp-client-adaptor and tries to register
* this adaptor into rmi. the adaptor is run on a thread to allow the application
* to proceed. if there occurs an error that does not allow the manager to proceed
* the error condition is signaled by the static error flag.
* @author swieland
*
*/
@Service("llrpManager")
public class LLRPManager implements LLRPExceptionHandler, MessageHandler {
/** the path to the configuration file. */
public static final String CONFIGURATION_FILE = "/llrpAdaptorConfiguration.properties";
/** the name of the property of the adapter management configuration file.*/
public static final String PROP_MGMT_CFG = "mgmt";
/** logger. */
private static final Logger log = Logger.getLogger(LLRPManager.class);
/** the adaptor from the llrp-gui client managing the connections to the llrp-readers. */
private static Adaptor adaptor = null;
public static final String ADAPTOR_NAME_PREFIX = "fc adaptor - ";
/** get a handle on the adaptor management. */
private final AdaptorManagement mgmt = AdaptorManagement.getInstance();
/** if defined, a handle to the LLRP message repository. */
private Repository repository = null;
/**
* a link counter counting the references onto a physical reader.
* the link counter is needed as several logical readers from
* fc can point to the same physical reader in the reader module.
* */
private Map<String, Integer> linkCounter = new ConcurrentHashMap<String, Integer>();
/**
* public constructor.
*/
public LLRPManager() {
try {
initialize();
log.info("llrp adaptor is bound");
} catch (LLRPRuntimeException e) {
log.error("there has been an error when creating the reader management");
throw new IllegalStateException("there has been an error when creating the reader management");
}
}
/**
* try to initialize the adaptor holding the llrp-readers. <br/>
* try to acquire the rmi registry from the localhost. if this fails create a
* new rmi registry and also create a new llrp-adaptor. if everything is ok
* then (registry exists and can be contacted) try to acquire the existing
* adaptor from the registry. if this fails try to create a new adaptor as well.
* @throws LLRPRuntimeException
*/
private void initialize() throws LLRPRuntimeException {
String mgmtConfigFile = null;
Properties props = null;
try {
URL url1 = LLRPManager.class.getResource(CONFIGURATION_FILE);
String resolvedConfig = url1.getFile();
props = new Properties();
props.load(new FileInputStream(new File(resolvedConfig)));
// try to read the configuration file for the adapter management.
mgmtConfigFile = props.getProperty(PROP_MGMT_CFG, null);
// try to read from it ...
File f = new File(mgmtConfigFile);
if (f.exists() && f.canRead() && f.canWrite()) {
log.debug("found config file: " + mgmtConfigFile);
} else {
throw new Exception("config file not found");
}
} catch (Exception e) {
log.error("no config file - therefore using defaults...");
}
// tell the adaptor management to export the adaptor with RMI (last true).
mgmt.initialize(mgmtConfigFile, mgmtConfigFile, false, this, this, true);
// get the first exported adaptor.
if (mgmt.getAdaptorNames().size() > 0) {
adaptor = mgmt.getAdaptor(mgmt.getAdaptorNames().get(0));
} else {
throw new LLRPRuntimeException("no adaptor was found!!!");
}
try {
// if everything is fine, try to open the repository (if defined).
registerRepository(props);
} catch (Exception e) {
log.error("Could not initialize the repository - disabling it.");
}
}
/**
* try to create a new repository and register it as a new message
* handler. if the RO_ACCESS_REPORT is logged, register this repository
* as well.
* @param props the properties file of the adapter.
* @throws Exception when something goes wrong.
*/
private void registerRepository(Properties props) throws Exception {
if (null == props) throw new Exception("Empty properties.");
repository = RepositoryFactory.create(props);
if (null == repository) throw new Exception("Repository is null.");
// create our message handler
mgmt.registerFullHandler(new MessageHandler() {
public void handle(String adapter, String reader,
LLRPMessage msg) {
LLRPMessageItem item = new LLRPMessageItem();
item.setAdapter(adapter);
item.setReader(reader);
String msgName = msg.getName();
item.setMessageType(msgName);
// if the message contains a "LLRPStatus" parameter,
//set the status code (otherwise use empty string)
String statusCode = null;
try {
Method getLLRPStatusMethod =
msg.getClass().getMethod("getLLRPStatus",
new Class[0]);
LLRPStatus status =
(LLRPStatus) getLLRPStatusMethod.invoke(
msg, new Object[0]);
statusCode = status.getStatusCode().toString();
} catch (Exception e) {
statusCode = "";
}
item.setStatusCode(statusCode);
// store the xml string to the repository
try {
item.setContent(msg.toXMLString());
} catch (InvalidLLRPMessageException e) {
log.debug("caught exception", e);
}
try {
repository.put(item);
} catch (Exception e) {
// repository might be null
log.debug("caught exception", e);
}
}
});
ROAccessReportsRepository roAcc = repository.getROAccessRepository();
if ((null != roAcc) && (roAcc instanceof MessageHandler)) {
// register the RO_ACCESS_REPORTS handler
mgmt.registerPartialHandler(
roAcc, RO_ACCESS_REPORT.class);
}
}
/**
* return a reference to the llrp gui client adaptor management.
* @return an instance of the llrp gui client adaptor management.
*/
public Adaptor getAdaptor() {
return adaptor;
}
/**
* increments the link counter on a reader. the link counter is needed as several
* logical readers from fc can point to the same physical reader in the reader
* module.
* @param readerName the name of the reader.
*/
public void incReference(String readerName) {
if (!linkCounter.containsKey(readerName)) {
linkCounter.put(readerName, 0);
}
linkCounter.put(readerName, linkCounter.get(readerName).intValue() + 1);
}
/**
* decrements the link counter of the reader. the link counter is needed as several
* logical readers from fc can point to the same physical reader in the reader
* module. if no logical reader of the fc points to the physical reader, this reader
* is considered to be used no more therefore if counter is zero the reader gets undefined.
* @param readerName the name of the reader.
* @throws LLRPRuntimeException when there is an exception in the reader module.
* @throws RemoteException when there is an rmi exception.
*/
public void decReferenceCount(String readerName) throws RemoteException, LLRPRuntimeException {
if (!linkCounter.containsKey(readerName)) {
return;
}
if (linkCounter.get(readerName).intValue() > 0) {
int newVal = linkCounter.get(readerName) - 1;
if (newVal == 0) {
// undefine the reader from the adaptor.
getAdaptor().undefine(readerName);
}
linkCounter.put(readerName, newVal);
}
}
/**
* receives an asynchronous exception and posts this one. (comes from ExceptionHandler).
*/
public void postExceptionToGUI(LLRPExceptionHandlerTypeMap eTypeMap,
LLRPRuntimeException e, String adaptorName, String readerName) {
log.error("An exception occured:", e);
}
public void handle(String adaptorName, String readerName,
LLRPMessage message) {
log.debug("placeholder. NEVER IMPLEMENTED.");
}
}