com.almende.eve.agent.AgentFactory Maven / Gradle / Ivy
package com.almende.eve.agent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.ProtocolException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Logger;
import org.joda.time.DateTime;
import com.almende.eve.agent.annotation.Sender;
import com.almende.eve.agent.annotation.ThreadSafe;
import com.almende.eve.agent.log.EventLogger;
import com.almende.eve.agent.proxy.AsyncProxy;
import com.almende.eve.config.Config;
import com.almende.eve.rpc.RequestParams;
import com.almende.eve.rpc.jsonrpc.JSONRPC;
import com.almende.eve.rpc.jsonrpc.JSONRPCException;
import com.almende.eve.rpc.jsonrpc.JSONRequest;
import com.almende.eve.rpc.jsonrpc.JSONResponse;
import com.almende.eve.scheduler.Scheduler;
import com.almende.eve.scheduler.SchedulerFactory;
import com.almende.eve.state.MemoryStateFactory;
import com.almende.eve.state.State;
import com.almende.eve.state.StateFactory;
import com.almende.eve.transport.AsyncCallback;
import com.almende.eve.transport.TransportService;
import com.almende.eve.transport.http.HttpService;
import com.almende.util.ClassUtil;
/**
* The AgentFactory is a factory to instantiate and invoke Eve Agents within the
* configured state. The AgentFactory can invoke local as well as remote agents.
*
* An AgentFactory must be instantiated with a valid Eve configuration file.
* This configuration is needed to load the configured agent classes and
* instantiate a state for each agent.
*
* Example usage: // generic constructor Config config = new Config("eve.yaml");
* AgentFactory factory = new AgentFactory(config);
*
* // construct in servlet InputStream is =
* getServletContext().getResourceAsStream("/WEB-INF/eve.yaml"); Config config =
* new Config(is); AgentFactory factory = new AgentFactory(config);
*
* // create or get a shared instance of the AgentFactory AgentFactory factory =
* AgentFactory.createInstance(namespace, config); AgentFactory factory =
* AgentFactory.getInstance(namespace);
*
* // invoke a local agent by its id response = factory.invoke(agentId,
* request);
*
* // invoke a local or remote agent by its url response =
* factory.send(senderId, receiverUrl, request);
*
* // create a new agent Agent agent = factory.createAgent(agentType, agentId);
* String desc = agent.getDescription(); // use the agent agent.destroy(); //
* neatly shutdown the agents state
*
* // instantiate an existing agent Agent agent = factory.getAgent(agentId);
* String desc = agent.getDescription(); // use the agent agent.destroy(); //
* neatly shutdown the agents state
*
* @author jos
*/
public class AgentFactory {
// Note: the CopyOnWriteArrayList is inefficient but thread safe.
private List transportServices = new CopyOnWriteArrayList();
private StateFactory stateFactory = null;
private SchedulerFactory schedulerFactory = null;
private Config config = null;
private EventLogger eventLogger = new EventLogger(this);
private static String ENVIRONMENT_PATH[] = new String[] {
"com.google.appengine.runtime.environment",
"com.almende.eve.runtime.environment" };
private static String environment = null;
private static boolean doesShortcut = true;
private final static Map factories = new ConcurrentHashMap(); // namespace:factory
private final static Map STATE_FACTORIES = new HashMap();
static {
STATE_FACTORIES.put("FileStateFactory",
"com.almende.eve.state.FileStateFactory");
STATE_FACTORIES.put("MemoryStateFactory",
"com.almende.eve.state.MemoryStateFactory");
STATE_FACTORIES.put("DatastoreStateFactory",
"com.almende.eve.state.google.DatastoreStateFactory");
}
private final static Map SCHEDULERS = new HashMap();
static {
SCHEDULERS.put("RunnableSchedulerFactory",
"com.almende.eve.scheduler.RunnableSchedulerFactory");
SCHEDULERS.put("ClockSchedulerFactory",
"com.almende.eve.scheduler.ClockSchedulerFactory");
SCHEDULERS.put("GaeSchedulerFactory",
"com.almende.eve.scheduler.google.GaeSchedulerFactory");
}
private final static Map TRANSPORT_SERVICES = new HashMap();
static {
TRANSPORT_SERVICES.put("XmppService",
"com.almende.eve.transport.xmpp.XmppService");
TRANSPORT_SERVICES.put("HttpService",
"com.almende.eve.transport.http.HttpService");
}
private final static RequestParams eveRequestParams = new RequestParams();
static {
eveRequestParams.put(Sender.class, null);
}
private final static Logger logger = Logger.getLogger(AgentFactory.class
.getSimpleName());
protected AgentFactory() {
// ensure there is at least a memory state service
setStateFactory(new MemoryStateFactory());
// ensure there is always an HttpService for outgoing calls
addTransportService(new HttpService());
}
/**
* Construct an AgentFactory and initialize the configuration
*
* @param config
* @throws Exception
*/
protected AgentFactory(Config config) throws Exception {
this.config = config;
if (config != null) {
AgentCache.configCache(config);
// initialize all factories for state, transport, and scheduler
// important to initialize in the correct order: cache first,
// then the state and transport services, and lastly scheduler.
setStateFactory(config);
addTransportServices(config);
// ensure there is always an HttpService for outgoing calls
addTransportService(new HttpService());
setSchedulerFactory(config);
addAgents(config);
} else {
// ensure there is at least a memory state service
setStateFactory(new MemoryStateFactory());
// ensure there is always an HttpService for outgoing calls
addTransportService(new HttpService());
}
}
/**
* Get a shared AgentFactory instance with the default namespace "default"
*
* @return factory Returns the factory instance, or null when not existing
*/
public static AgentFactory getInstance() {
return getInstance(null);
}
/**
* Get a shared AgentFactory instance with a specific namespace
*
* @param namespace
* If null, "default" namespace will be loaded.
* @return factory Returns the factory instance, or null when not existing
*/
public static AgentFactory getInstance(String namespace) {
if (namespace == null) {
namespace = "default";
}
return factories.get(namespace);
}
/**
* Create a shared AgentFactory instance with the default namespace
* "default"
*
* @return factory
*/
public static synchronized AgentFactory createInstance() throws Exception {
return createInstance(null, null);
}
/**
* Create a shared AgentFactory instance with the default namespace
* "default"
*
* @param config
* @return factory
*/
public static synchronized AgentFactory createInstance(Config config)
throws Exception {
return createInstance(null, config);
}
/**
* Create a shared AgentFactory instance with a specific namespace
*
* @param namespace
* @return factory
*/
public static synchronized AgentFactory createInstance(String namespace)
throws Exception {
return createInstance(namespace, null);
}
public static synchronized void registerInstance(AgentFactory factory){
registerInstance(null,factory);
}
public static synchronized void registerInstance(String namespace, AgentFactory factory){
if (namespace == null){
namespace = "default";
}
factories.put(namespace, factory);
}
/**
* Create a shared AgentFactory instance with a specific namespace
*
* @param namespace
* If null, "default" namespace will be loaded.
* @param config
* If null, a non-configured AgentFactory will be created.
* @return factory
* @throws Exception
*/
public static synchronized AgentFactory createInstance(String namespace,
Config config) throws Exception {
if (namespace == null) {
namespace = "default";
}
if (factories.containsKey(namespace)) {
throw new Exception(
"Shared AgentFactory with namespace '"
+ namespace
+ "' already exists. "
+ "A shared AgentFactory can only be created once. "
+ "Use getInstance instead to get the existing shared instance.");
}
AgentFactory factory = new AgentFactory(config);
factories.put(namespace, factory);
factory.boot();
return factory;
}
/**
* Should be called every time a new AgentFactory is started or if new agents become available (through setStateFactory())
*
*/
public void boot() {
if (stateFactory != null){
Iterator iter = stateFactory.getAllAgentIds();
if (iter != null) {
while (iter.hasNext()){
try {
Agent agent = getAgent(iter.next());
if (agent != null){
agent.boot();
}
} catch (Exception e) {}
}
}
}
}
/**
* Get an agent by its id. Returns null if the agent does not exist
*
* Before deleting the agent, the method agent.destroy() must be executed to
* neatly shutdown the instantiated state.
*
* @param agentId
* @return agent
* @throws Exception
*/
public Agent getAgent(String agentId) throws Exception {
if (agentId == null) {
return null;
}
// Check if agent is instantiated already, returning if it is:
Agent agent = AgentCache.get(agentId);
if (agent != null) {
// System.err.println("Agent "+agentId+" found in cache!");
return agent;
}
// No agent found, normal initialization:
// load the State
State state = null;
state = getStateFactory().get(agentId);
if (state == null) {
// agent does not exist
return null;
}
state.init();
// read the agents class name from state
Class> agentType = state.getAgentType();
if (agentType == null) {
throw new Exception("Cannot instantiate agent. "
+ "Class information missing in the agents state "
+ "(agentId='" + agentId + "')");
}
// instantiate the agent
agent = (Agent) agentType.getConstructor().newInstance();
agent.setAgentFactory(this);
agent.setState(state);
agent.init();
if (agentType.isAnnotationPresent(ThreadSafe.class)
&& agentType.getAnnotation(ThreadSafe.class).value()) {
AgentCache.put(agentId, agent);
}
return agent;
}
/**
* Create an agent proxy from an java interface
*
* @param sender
* Sender Agent, used to authentication purposes.
* @param receiverUrl
* Url of the receiving agent
* @param agentInterface
* A java Interface, extending AgentInterface
* @return
*/
@SuppressWarnings("unchecked")
public T createAgentProxy(final AgentInterface sender,
final String receiverUrl, Class agentInterface) {
if (!ClassUtil.hasInterface(agentInterface, AgentInterface.class)) {
throw new IllegalArgumentException("agentInterface must extend "
+ AgentInterface.class.getName());
}
// http://docs.oracle.com/javase/1.4.2/docs/guide/reflection/proxy.html
T proxy = (T) Proxy.newProxyInstance(agentInterface.getClassLoader(),
new Class[] { agentInterface }, new InvocationHandler() {
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
JSONRequest request = JSONRPC.createRequest(method,
args);
JSONResponse response = send(sender, receiverUrl,
request);
JSONRPCException err = response.getError();
if (err != null) {
throw err;
} else if (response.getResult() != null
&& !method.getReturnType().equals(Void.TYPE)) {
return response.getResult(method.getReturnType());
} else {
return null;
}
}
});
// TODO: for optimization, one can cache the created proxy's
return proxy;
}
/**
* Create an asynchronous agent proxy from an java interface, each call will
* return a future for handling the results.
*
* @param senderId
* Internal id of the sender agent. Not required for all
* transport services (for example not for outgoing HTTP
* requests)
* @param receiverUrl
* Url of the receiving agent
* @param agentInterface
* A java Interface, extending AgentInterface
* @return
*/
public AsyncProxy createAsyncAgentProxy(final AgentInterface sender,
final String receiverUrl, Class agentInterface) {
return new AsyncProxy(createAgentProxy(sender, receiverUrl,
agentInterface));
}
/**
* Create an agent.
*
* Before deleting the agent, the method agent.destroy() must be executed to
* neatly shutdown the instantiated state.
*
* @param agentType
* full class path
* @param agentId
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
public T createAgent(String agentType, String agentId) throws Exception {
return (T) createAgent((Class)Class.forName(agentType), agentId);
}
/**
* Create an agent.
*
* Before deleting the agent, the method agent.destroy() must be executed to
* neatly shutdown the instantiated state.
*
* @param agentType
* @param agentId
* @return
* @throws Exception
*/
public T createAgent(Class agentType, String agentId)
throws Exception {
if (!ClassUtil.hasSuperClass(agentType, Agent.class)) {
throw new Exception("Class " + agentType
+ " does not extend class " + Agent.class);
}
// validate the Eve agent and output as warnings
List errors = JSONRPC.validate(agentType, eveRequestParams);
for (String error : errors) {
logger.warning("Validation error class: " + agentType.getName()
+ ", message: " + error);
}
// create the state
State state = getStateFactory().create(agentId);
state.setAgentType(agentType);
state.init();
// instantiate the agent
T agent = (T) agentType.getConstructor().newInstance();
agent.setAgentFactory(this);
agent.setState(state);
agent.create();
agent.init();
if (agentType.isAnnotationPresent(ThreadSafe.class)
&& agentType.getAnnotation(ThreadSafe.class).value()) {
// System.err.println("Agent "+agentId+" is threadSafe, keeping!");
AgentCache.put(agentId, agent);
}
return agent;
}
/**
* Delete an agent
*
* @param agentId
* @throws Exception
*/
public void deleteAgent(String agentId) throws Exception {
Exception e = null;
if (agentId == null) {
return;
}
Agent agent = getAgent(agentId);
if (agent == null) return;
if (getScheduler(agentId) != null) {
schedulerFactory.destroyScheduler(agentId);
}
try {
// get the agent and execute the delete method
agent.destroy();
agent.delete();
AgentCache.delete(agentId);
agent = null;
} catch (Exception err) {
e = err;
}
try {
// delete the state, even if the agent.destroy or agent.delete
// failed.
getStateFactory().delete(agentId);
} catch (Exception err) {
if (e == null) {
e = err;
}
}
// rethrow the first exception
if (e != null) {
throw e;
}
}
/**
* Test if an agent exists
*
* @param agentId
* @return true if the agent exists
* @throws Exception
*/
public boolean hasAgent(String agentId) throws Exception {
return getStateFactory().exists(agentId);
}
/**
* Get the event logger. The event logger is used to temporary log triggered
* events, and display them on the agents web interface.
*
* @return eventLogger
*/
public EventLogger getEventLogger() {
return eventLogger;
}
/**
* Invoke a local agent
*
* @param receiverId
* Id of the receiver agent
* @param request
* @param requestParams
* @return
* @throws Exception
*/
public JSONResponse receive(String receiverId, JSONRequest request,
RequestParams requestParams) throws Exception {
Agent receiver = getAgent(receiverId);
if (receiver != null) {
JSONResponse response = JSONRPC.invoke(receiver, request,
requestParams);
receiver.destroy();
return response;
} else {
throw new Exception("Agent with id '" + receiverId + "' not found");
}
}
// public JSONResponse receive(String SenderId, String receiverUrl,
// JSONRequest request) throws Exception {
//
// String agentId = getAgentId(receiverUrl);
// if (agentId != null){
// String senderUrl = null;
// if (SenderId != null) {
// senderUrl = getSenderUrl(SenderId, receiverUrl);
// }
// RequestParams requestParams = new RequestParams();
// requestParams.put(Sender.class, senderUrl);
// JSONResponse response = invoke(agentId, request, requestParams);
// return response;
// } else {
// throw new Exception("Agent for '" + receiverUrl + "' not found");
// }
// }
/**
* Invoke a local or remote agent. In case of an local agent, the agent is
* invoked immediately. In case of an remote agent, an HTTP Request is sent
* to the concerning agent.
*
* @param senderId
* Internal id of the sender agent Not required for all transport
* services (for example not for outgoing HTTP requests)
* @param receiverUrl
* @param request
* @return
* @throws Exception
*/
public JSONResponse send(AgentInterface sender, String receiverUrl,
JSONRequest request) throws Exception {
String receiverId = getAgentId(receiverUrl);
String senderUrl = null;
if (sender != null) {
senderUrl = getSenderUrl(sender.getId(), receiverUrl);
}
if (doesShortcut && receiverId != null) {
//local shortcut
RequestParams requestParams = new RequestParams();
requestParams.put(Sender.class, senderUrl);
return receive(receiverId,request,requestParams);
} else {
TransportService service = null;
String protocol = null;
int separator = receiverUrl.indexOf(":");
if (separator != -1) {
protocol = receiverUrl.substring(0, separator);
service = getTransportService(protocol);
}
if (service != null) {
JSONResponse response = service.send(
senderUrl,
receiverUrl,
request);
return response;
} else {
throw new ProtocolException(
"No transport service configured for protocol '"
+ protocol + "'.");
}
}
}
/**
* Asynchronously invoke a request on an agent.
*
* @param senderId
* Internal id of the sender agent. Not required for all
* transport services (for example not for outgoing HTTP
* requests)
* @param receiverUrl
* @param request
* @param callback
* @throws Exception
*/
public void sendAsync(final AgentInterface sender,
final String receiverUrl, final JSONRequest request,
final AsyncCallback callback) throws Exception {
final String receiverId = getAgentId(receiverUrl);
if (doesShortcut && receiverId != null) {
//local shortcut
new Thread(new Runnable() {
@Override
public void run() {
JSONResponse response;
try {
String senderUrl = null;
if (sender != null) {
senderUrl = getSenderUrl(sender.getId(), receiverUrl);
}
RequestParams requestParams = new RequestParams();
requestParams.put(Sender.class, senderUrl);
response = receive(receiverId,request,requestParams);
callback.onSuccess(response);
} catch (Exception e) {
callback.onFailure(e);
}
}
}).start();
} else {
TransportService service = null;
String protocol = null;
String senderUrl = null;
if (sender != null) {
senderUrl = getSenderUrl(sender.getId(), receiverUrl);
}
int separator = receiverUrl.indexOf(":");
if (separator != -1) {
protocol = receiverUrl.substring(0, separator);
service = getTransportService(protocol);
}
if (service != null) {
service.sendAsync(senderUrl, receiverUrl, request,
callback);
} else {
throw new ProtocolException(
"No transport service configured for protocol '"
+ protocol + "'.");
}
}
}
/**
* Get the agentId from given agentUrl. The url can be any protocol. If the
* url matches any of the registered transport services, an agentId is
* returned. This means that the url represents a local agent. It is
* possible that no agent with this id exists.
*
* @param agentUrl
* @return agentId
*/
private String getAgentId(String agentUrl) {
// System.err.println("Looking up agent:"+agentUrl);
if (agentUrl.startsWith("local:")) {
return agentUrl.replaceFirst("local:/?/?", "");
}
for (TransportService service : transportServices) {
String agentId = service.getAgentId(agentUrl);
if (agentId != null) {
return agentId;
}
}
return null;
}
/**
* Determines best senderUrl for this agent, match receiverUrl transport method if possible. (fallback from HTTPS to HTTP included)
*
* @param agentUrl
* @return agentId
*/
private String getSenderUrl(String agentId, String receiverUrl) {
if (receiverUrl.startsWith("local:")) {
return "local://" + agentId;
}
for (TransportService service : transportServices) {
List protocols = service.getProtocols();
for (String protocol: protocols){
// System.err.println("Checking:"+protocol+ " on "+receiverUrl+ " Would be:'"+service.getAgentUrl(agentId)+"'");
if (receiverUrl.startsWith(protocol+":")){
String senderUrl = service.getAgentUrl(agentId);
if (senderUrl != null){
// System.err.println("Returning:'"+service.getAgentUrl(agentId)+"'");
return senderUrl;
}
}
}
}
return null;
}
/**
* Retrieve the current environment, using the configured State. Can return
* values like "Production", "Development". If no environment variable is
* found, "Production" is returned.
*
* @return environment
*/
public static String getEnvironment() {
if (environment == null) {
for (String path : ENVIRONMENT_PATH) {
environment = System.getProperty(path);
if (environment != null) {
logger.info("Current environment: '" + environment
+ "' (read from path '" + path + "')");
break;
}
}
if (environment == null) {
// no environment variable found. Fall back to "Production"
environment = "Production";
String msg = "No environment variable found. "
+ "Environment set to '" + environment
+ "'. Checked paths: ";
for (String path : ENVIRONMENT_PATH) {
msg += path + ", ";
}
logger.warning(msg);
}
}
return environment;
}
/**
* Programmatically set the environment
*
* @param env
* The environment, for example "Production" or "Development"
* @return
*/
public static void setEnvironment(String env) {
environment = env;
}
/**
* Get the loaded config file
*
* @return config A configuration file
*/
public void setConfig(Config config) {
this.config = config;
}
/**
* Get the loaded config file
*
* @return config A configuration file
*/
public Config getConfig() {
return config;
}
public static boolean isDoesShortcut() {
return doesShortcut;
}
public static void setDoesShortcut(boolean doesShortcut) {
AgentFactory.doesShortcut = doesShortcut;
}
/**
* Load a state factory from config
*
* @param config
* @throws Exception
*/
public void setStateFactory(Config config) {
// get the class name from the config file
// first read from the environment specific configuration,
// if not found read from the global configuration
String className = config.get("state", "class");
String configName = "state";
if (className == null) {
className = config.get("context", "class");
if (className == null) {
throw new IllegalArgumentException(
"Config parameter 'state.class' missing in Eve configuration.");
} else {
logger.warning("Use of config parameter 'context' is deprecated, please use 'state' instead.");
configName = "context";
}
}
// TODO: deprecated since "2013-02-20"
if ("FileContextFactory".equals(className)) {
logger.warning("Use of Classname FileContextFactory is deprecated, please use 'FileStateFactory' instead.");
className = "FileStateFactory";
}
if ("MemoryContextFactory".equals(className)) {
logger.warning("Use of Classname MemoryContextFactory is deprecated, please use 'MemoryStateFactory' instead.");
className = "MemoryStateFactory";
}
if ("DatastoreContextFactory".equals(className)) {
logger.warning("Use of Classname DatastoreContextFactory is deprecated, please use 'DatastoreStateFactory' instead.");
className = "DatastoreStateFactory";
}
// Recognize known classes by their short name,
// and replace the short name for the full class path
for (String name : STATE_FACTORIES.keySet()) {
if (className.toLowerCase().equals(name.toLowerCase())) {
className = STATE_FACTORIES.get(name);
break;
}
}
try {
// get the class
Class> stateClass = Class.forName(className);
if (!ClassUtil.hasInterface(stateClass, StateFactory.class)) {
throw new IllegalArgumentException("State factory class "
+ stateClass.getName() + " must extend "
+ State.class.getName());
}
// instantiate the state factory
Map params = config.get(configName);
StateFactory stateFactory = (StateFactory) stateClass
.getConstructor(AgentFactory.class, Map.class).newInstance(
this, params);
setStateFactory(stateFactory);
logger.info("Initialized state factory: " + stateFactory.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Create agents from a config (only when they do not yet exist). Agents
* will be read from the configuration path bootstrap.agents, which must
* contain a map where the keys are agentId's and the values are the agent
* types (full java class path).
*
* @param config
*/
public void addAgents(Config config) {
Map agents = config.get("bootstrap", "agents");
if (agents != null) {
for (Entry entry : agents.entrySet()) {
String agentId = entry.getKey();
String agentType = entry.getValue();
try {
Agent agent = getAgent(agentId);
if (agent == null) {
// agent does not yet exist. create it
agent = createAgent(agentType, agentId);
agent.destroy();
logger.info("Bootstrap created agent id=" + agentId
+ ", type=" + agentType);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* Set a state factory. The state factory is used to get/create/delete an
* agents state.
*
* @param stateFactory
*/
public void setStateFactory(StateFactory stateFactory) {
this.stateFactory = stateFactory;
}
/**
* Get the configured state factory.
*
* @return stateFactory
*/
public StateFactory getStateFactory() throws Exception {
if (stateFactory == null) {
throw new Exception("No state factory initialized.");
}
return stateFactory;
}
/**
* Load a scheduler factory from a config file
*
* @param config
* @throws Exception
*/
public void setSchedulerFactory(Config config) {
// get the class name from the config file
// first read from the environment specific configuration,
// if not found read from the global configuration
String className = config.get("scheduler", "class");
if (className == null) {
throw new IllegalArgumentException(
"Config parameter 'scheduler.class' missing in Eve configuration.");
}
// TODO: remove warning some day (added 2013-01-22)
if (className.toLowerCase().equals("RunnableScheduler".toLowerCase())) {
logger.warning("Deprecated class RunnableScheduler configured. Use RunnableSchedulerFactory instead to configure a scheduler factory.");
className = "RunnableSchedulerFactory";
}
if (className.toLowerCase().equals("AppEngineScheduler".toLowerCase())) {
logger.warning("Deprecated class AppEngineScheduler configured. Use GaeSchedulerFactory instead to configure a scheduler factory.");
className = "GaeSchedulerFactory";
}
if (className.toLowerCase().equals(
"AppEngineSchedulerFactory".toLowerCase())) {
logger.warning("Deprecated class AppEngineSchedulerFactory configured. Use GaeSchedulerFactory instead to configure a scheduler factory.");
className = "GaeSchedulerFactory";
}
// Recognize known classes by their short name,
// and replace the short name for the full class path
for (String name : SCHEDULERS.keySet()) {
if (className.toLowerCase().equals(name.toLowerCase())) {
className = SCHEDULERS.get(name);
break;
}
}
// read all scheduler params (will be fed to the scheduler factory
// on construction)
Map params = config.get("scheduler");
try {
// get the class
Class> schedulerClass = Class.forName(className);
if (!ClassUtil.hasInterface(schedulerClass, SchedulerFactory.class)) {
throw new IllegalArgumentException("Scheduler class "
+ schedulerClass.getName() + " must implement "
+ SchedulerFactory.class.getName());
}
// initialize the scheduler factory
SchedulerFactory schedulerFactory = (SchedulerFactory) schedulerClass
.getConstructor(AgentFactory.class, Map.class).newInstance(
this, params);
setSchedulerFactory(schedulerFactory);
logger.info("Initialized scheduler factory: "
+ schedulerFactory.getClass().getName());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Load transport services for incoming and outgoing messages from a config
* (for example http and xmpp services).
*
* @param config
*/
public void addTransportServices(Config config) {
if (config == null) {
Exception e = new Exception("Configuration uninitialized");
e.printStackTrace();
return;
}
// read global service params
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy