fr.dyade.aaa.agent.ServiceManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of a3-rt Show documentation
Show all versions of a3-rt Show documentation
Builds the Joram a3 rt project.
/*
* Copyright (C) 2001 - 2023 ScalAgent Distributed Technologies
* Copyright (C) 1996 - 2000 BULL
* Copyright (C) 1996 - 2000 INRIA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package fr.dyade.aaa.agent;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.NoSuchElementException;
import java.util.Set;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import fr.dyade.aaa.common.Strings;
import fr.dyade.aaa.common.Debug;
/**
* Object which manages services.
* There is only one ServiceManager
object per agent server.
* The ServiceManager
object is initialized in init
,
* called from AgentServer.init
. This classes reuses the
* persistency service provided by Transaction
.
*/
public class ServiceManager implements Serializable {
/** Define serialVersionUID for interoperability. */
private static final long serialVersionUID = 1L;
/** the unique ServiceManager
in the agent server */
static ServiceManager manager;
static Logger xlogmon = Debug.getLogger(ServiceManager.class.getName());
private static String name = null;
public final static String getName() {
if (name == null)
name = AgentServer.getName() + ".ServiceManager";
return name;
}
/**
* Initializes the ServiceManager
object. Synchronize the
* persistent image and the configuration file.
*
* @exception Exception unspecialized exception
*/
static void init() throws Exception {
manager = ServiceManager.load();
if (manager == null) {
manager = new ServiceManager();
}
save();
}
public static String txname = "serviceManager";
/**
* Builds object from persistent image.
*
* @return loaded object or null if no persistent image exists
*
* @exception IOException
* when accessing the stored image
* @exception ClassNotFoundException
* if the corresponding image class may not be found
*/
static ServiceManager load() throws IOException, ClassNotFoundException {
return (ServiceManager) AgentServer.getTransaction().load(txname);
}
/**
* Saves object in persistent storage.
* @throws IOException an error occurs.
*/
static void save() throws IOException {
AgentServer.getTransaction().save(manager, txname);
// with OSGi the service start asynchronously,
// and perhaps without running transaction.
AgentServer.getTransaction().begin();
AgentServer.getTransaction().commit(true);
if (xlogmon.isLoggable(BasicLevel.DEBUG))
xlogmon.log(BasicLevel.DEBUG, getName() + " service manager saved.");
}
/** repository holding Service
s */
Hashtable registry;
/**
* Default constructor.
*/
private ServiceManager() {
registry = new Hashtable<>();
}
/**
* Loads the class of every service.
* @throws Exception if an error occurs
*/
public static void loadServiceClasses() throws Exception {
for (Enumeration e = manager.registry.elements(); e.hasMoreElements() ;) {
ServiceDesc desc = e.nextElement();
try {
loadServiceClass(desc);
} catch (Exception exc) {
if (xlogmon.isLoggable(BasicLevel.DEBUG))
xlogmon.log(BasicLevel.ERROR, getName() + ", cannot load service " + desc.getClassName(), exc);
else
xlogmon.log(BasicLevel.ERROR, getName() + ", cannot load service " + desc.getClassName() + ": " + exc.getMessage());
}
}
}
/**
* Loads the class of a service.
* @param desc the service descriptor
* @throws Exception if an error occurs
*/
public static void loadServiceClass(ServiceDesc desc) throws Exception {
Class.forName(desc.getClassName());
}
/**
* Start a Service
defined by its descriptor.
*
* @param desc service descriptor.
* @throws Exception if an error occurs
*/
public static void start(ServiceDesc desc) throws Exception {
if (xlogmon.isLoggable(BasicLevel.DEBUG))
xlogmon.log(BasicLevel.DEBUG, getName() + " start service: " + desc);
if (desc.running)
throw new Exception("Service already running");
Class ptypes[] = new Class[] { String.class, Boolean.TYPE };
Object args[] = new Object[] { desc.getArguments(), Boolean.valueOf(!desc.isInitialized()) };
Class service = null;
service = Class.forName(desc.getClassName());
Method init = service.getMethod("init", ptypes);
try {
init.invoke(null, args);
} catch (InvocationTargetException exc) {
if (xlogmon.isLoggable(BasicLevel.DEBUG))
xlogmon.log(BasicLevel.DEBUG, getName() + ", cannot start service:", exc.getCause());
throw new Exception(exc.getCause().getMessage());
}
desc.running = true;
desc.initialized = true;
if (xlogmon.isLoggable(BasicLevel.DEBUG)) {
xlogmon.log(BasicLevel.DEBUG, getName() + " service started");
}
save();
}
/**
* Start a Service
identified by its name.
*
* @param scname service class name.
* @throws Exception if an error occurs
*/
static void start(String scname) throws Exception {
ServiceDesc desc = (ServiceDesc) manager.registry.get(scname);
if (desc == null)
throw new NoSuchElementException("Unknown service: " + scname);
start(desc);
}
/**
* Starts all defined services.
* @param exitOnFailure if true exit on failure.
* @throws Exception if an error occurs
*/
static void start(boolean exitOnFailure) throws Exception {
// Launch all services defined in A3CML file
for (Enumeration e = manager.registry.elements(); e.hasMoreElements() ;) {
ServiceDesc desc = e.nextElement();
try {
start(desc);
} catch (Exception exc) {
if (xlogmon.isLoggable(BasicLevel.DEBUG))
xlogmon.log(BasicLevel.ERROR, getName() + ", cannot start service:" + desc.getClassName(), exc);
else
xlogmon.log(BasicLevel.ERROR, getName() + ", cannot start service " + desc.getClassName() + ": " + exc.getMessage());
if (exitOnFailure)
throw new Exception("Cannot start service " + desc.getClassName());
}
}
}
/**
* Stop a Service
defined by its descriptor.
*
* @param desc service descriptor.
* @throws Exception if an error occurs
*/
public static void stop(ServiceDesc desc) throws Exception {
// DF: idempotency (could be done in AgentAdmin)
if (! desc.running) return;
// throw new Exception("Service already stopped");
Class service = Class.forName(desc.getClassName());
Method stop = service.getMethod("stopService", new Class[0]);
stop.invoke(null, (Object[]) null);
desc.running = false;
if (xlogmon.isLoggable(BasicLevel.DEBUG))
xlogmon.log(BasicLevel.DEBUG, "Service " + desc.scname + " stopped.");
}
/**
* Stop a Service
identified by its name.
*
* @param scname service class name.
* @throws Exception if an error occurs
*/
public static void stop(String scname) throws Exception {
ServiceDesc desc = manager.registry.get(scname);
if (desc == null)
throw new NoSuchElementException("Unknown service: " + scname);
stop(desc);
}
/**
* Stops all running services.
*/
static void stop() {
if ((manager == null) || (manager.registry == null))
return;
for (Enumeration e = manager.registry.elements(); e.hasMoreElements();) {
ServiceDesc desc = e.nextElement();
try {
if (xlogmon.isLoggable(BasicLevel.DEBUG))
xlogmon.log(BasicLevel.DEBUG, getName() + ", stops: " + desc);
if (desc.running)
stop(desc);
if (xlogmon.isLoggable(BasicLevel.DEBUG))
xlogmon.log(BasicLevel.DEBUG, getName() + ", service stopped");
} catch (Throwable exc) {
if (xlogmon.isLoggable(BasicLevel.DEBUG))
xlogmon.log(BasicLevel.WARN, getName() + ", cannot stop service " + desc.getClassName(), exc);
else
xlogmon.log(BasicLevel.WARN, getName() + ", cannot stop service " + desc.getClassName() + ": " + exc.getMessage());
}
}
}
/**
* Registers a new Service
object.
*
* @param scname service class name.
* @param args launching arguments.
*/
public static void register(String scname, String args) {
synchronized (manager) {
ServiceDesc desc = (ServiceDesc) manager.registry.get(scname);
if (xlogmon.isLoggable(BasicLevel.DEBUG))
xlogmon.log(BasicLevel.DEBUG, getName() + ", register " + scname + " -> " + desc);
if (desc == null) {
desc = new ServiceDesc(scname, args);
manager.registry.put(scname, desc);
} else {
desc.args = args;
}
try {
save();
} catch (IOException e) {
if (xlogmon.isLoggable(BasicLevel.ERROR))
xlogmon.log(BasicLevel.ERROR, getName() + ", register save service manager." + scname, e);
}
}
}
/**
* Unregisters useless Service
.
*
* @param scname service class name.
*/
static void unregister(String scname) {
if (xlogmon.isLoggable(BasicLevel.DEBUG))
xlogmon.log(BasicLevel.DEBUG, getName() + ", unregister " + scname);
synchronized (manager) {
manager.registry.remove(scname);
try {
save();
} catch (IOException e) {
if (xlogmon.isLoggable(BasicLevel.ERROR))
xlogmon.log(BasicLevel.ERROR, getName() + ", unregister save service manager." + scname, e);
}
}
}
public static ServiceDesc getService(String serviceClassName) {
return (ServiceDesc) manager.registry.get(serviceClassName);
}
static ServiceDesc[] getServices() {
ServiceDesc[] services = new ServiceDesc[manager.registry.size()];
int i = 0;
for (Enumeration e = manager.registry.elements(); e.hasMoreElements();) {
services[i++] = e.nextElement();
}
return services;
}
static Set listServices() {
return new HashSet<>(manager.registry.keySet());
}
/**
* Provides a string image for this object.
*
* @return a string image for this object
*/
public String toString() {
StringBuffer output = new StringBuffer();
output.append('(');
output.append(super.toString());
output.append(",registry=").append(Strings.toString(registry));
output.append(')');
return output.toString();
}
}