MobileAgentFactory.java
package emissary.pool;
import emissary.config.ConfigUtil;
import emissary.config.Configurator;
import emissary.core.Factory;
import emissary.core.IMobileAgent;
import emissary.core.MobileAgent;
import emissary.core.Namespace;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class MobileAgentFactory implements PooledObjectFactory<IMobileAgent> {
// This is the default class when nothing else is
// configured or passed on a constructor. This value
// can be overridden from the AgentPool.cfg file
static final String DEFAULT_CLASS_STRING = "emissary.core.MobileAgent";
public static final String AGENT_NAME = "MobileAgent";
// This is the class we are going to be pooling
// The value can be set by constructor, by public setter
// or from the value in DEFAULT_CLASS_STRING
String classString = DEFAULT_CLASS_STRING;
int maxAgentMoveErrors;
int maxAgentItinerary;
private static final Logger logger = LoggerFactory.getLogger(MobileAgentFactory.class);
// Thread group for every agent produced by this factory
private static final AgentThreadGroup threadGroup = new AgentThreadGroup("Agent Threads");
// True if created objects should be registered in namespace
private boolean useNamespace = true;
// Track how many objects created here
private long objectsCreated = 0;
protected void configure() {
// Setup the DEFAULT_CLASS_STRING value by peeking at the config file
try {
Configurator conf = ConfigUtil.getConfigInfo(AgentPool.class);
classString = conf.findStringEntry("agent.class", DEFAULT_CLASS_STRING);
maxAgentMoveErrors = conf.findIntEntry("agent.move.errors", MobileAgent.DEFAULT_MAX_MOVE_ERRORS);
maxAgentItinerary = conf.findIntEntry("agent.max.itinerary", MobileAgent.DEFAULT_MAX_ITINERARY_STEPS);
} catch (IOException e) {
logger.debug("Cannot read AgentPool.cfg, taking default values");
}
}
/**
* create a new instance of the mobile agent factory for use by the pool
*/
public MobileAgentFactory() {
super();
configure();
logger.debug("Factory will create {} agents", classString);
}
/**
* create a new instance of the mobile agent factory using the specified class as the implementation du jour
*
* @param clazz the class of mobile agent to use
*/
public MobileAgentFactory(String clazz) {
super();
configure();
setClassString(clazz);
logger.debug("Factory will create {} agents", classString);
}
/**
* Set whether created mobile agents should be registered in the global namespace or not
*
* @param arg true if registration in namespace is desired
*/
public void setUseNamespace(boolean arg) {
this.useNamespace = arg;
}
/**
* called by the pool to get an instance of the specified implementation
*
* @return a newly Factory.create()ed instance
*/
@Override
public PooledObject<IMobileAgent> makeObject() {
logger.debug("Calling MobileAgentFactory.makeObject for {}", getClassString());
IMobileAgent agent;
String aname = AGENT_NAME + "-" + (objectsCreated < 10 ? "0" : "") + objectsCreated;
try {
if (useNamespace) {
agent = (IMobileAgent) Factory.createV(getClassString(), aname, threadGroup, aname);
} else {
agent = (IMobileAgent) Factory.create(getClassString(), threadGroup, aname);
}
agent.setMaxItinerarySteps(maxAgentItinerary);
agent.setMaxMoveErrors(maxAgentMoveErrors);
} catch (Throwable t) {
logger.error("Unable to Factory.create(" + getClassString() + ") with a threadGroup argument", t);
if (useNamespace) {
agent = (IMobileAgent) Factory.createV(getClassString(), aname);
} else {
agent = (IMobileAgent) Factory.create(getClassString());
}
}
objectsCreated++;
return new DefaultPooledObject<>(agent);
}
/**
* Called by the pool to activate an object
*
* @param o the object to be activated in the pool
*/
@Override
public void activateObject(PooledObject<IMobileAgent> o) {
logger.trace("Activating {}", o.getObject().getName());
// no code
}
/**
* Called by the pool to passivate an object
*
* @param o the object to be passivated in the pool
*/
@Override
public void passivateObject(PooledObject<IMobileAgent> o) {
logger.trace("Passivating {}", o.getObject().getName());
// no code
}
/**
* called by the pool when it is configured to validate objects
*
* @param o the object to validate, should be instance of the specified implementation for this factory
* @return IMobileAgent.isInUse() with proper checking
*/
@Override
public boolean validateObject(PooledObject<IMobileAgent> o) {
logger.debug("Validating {}", o.getObject().getName());
return !o.getObject().isInUse();
}
/**
* Called by the pool to destroy an object
*
* @param o the object to be removed from the pool and destroyed
*/
@Override
public void destroyObject(PooledObject<IMobileAgent> o) {
IMobileAgent a = o.getObject();
logger.info("Stopping agent {}", a.getName());
a.killAgentAsync();
if (useNamespace) {
Namespace.unbind(o.getObject().getName());
}
logger.info("Stopped agent {}", a.getName());
}
/**
* Set the class implementing IMobileAgent
*
* @param s the name of the implementing class
*/
public void setClassString(String s) {
classString = s;
}
/**
* Get the current class for IMobileAgent we are using
*
* @return the current implementation class string
*/
public String getClassString() {
return classString;
}
/**
* Debug info
*/
@Override
public String toString() {
return "MobileAgentFactory created " + objectsCreated + " " + getClassString() + " instances";
}
}