Index: topia2/src/java/org/codelutin/topia/service/servers/RemoteClassLoader.java diff -u /dev/null topia2/src/java/org/codelutin/topia/service/servers/RemoteClassLoader.java:1.1 --- /dev/null Wed Apr 18 12:21:30 2007 +++ topia2/src/java/org/codelutin/topia/service/servers/RemoteClassLoader.java Wed Apr 18 12:21:25 2007 @@ -0,0 +1,399 @@ +/* *##% + * Copyright (C) 2006 Code Lutin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.codelutin.topia.service.servers; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.rmi.Remote; +import java.rmi.RemoteException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.topia.service.TopiaServiceFactory; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.CodeVisitor; + +// Tout le code d'utilisation de truezip est present +// mais commente pour ne pas garder une dependance +// supplementaire +/* + * import de.schlichtherle.io.ArchiveException; import de.schlichtherle.io.File; + * import de.schlichtherle.io.FileOutputStream; + */ + +/** + * RMIRemoteHelper.java + * + * Creer une nouvelle classe en transformant la classe passee en parametre. + * + * Ajoute une interface "Remote" Ajoute des exception a toutes les methodes + * "RemoteException" + * + * Utilise les API asm. + * + * @see java.rmi.Remote + * @see java.rmi.RemoteException + * + * @author chatellier + * @version $Revision: 1.1 $ + * + * Last update : $Date: 2007/04/18 12:21:25 $ By : $Author: chatellier $ + */ +public class RemoteClassLoader implements ClassVisitor { + + /** Logger (common logging) */ + private static final Log logger = LogFactory + .getLog(RemoteClassLoader.class); + + /** Ajout au nom de classe */ + public static final String EXTENSION = "Remote"; + + /** + * Le writer (global necessaire parce que parcourt par patron visiteur) + */ + protected ClassWriter cWriter; + + /** + * Constructeur + * + * @param clazz + * la classes a convertir + */ + protected RemoteClassLoader() { + } + + /* + * (non-Javadoc) + * + * @see org.objectweb.asm.ClassVisitor#visit(int, int, java.lang.String, + * java.lang.String, java.lang.String[], java.lang.String) + */ + public void visit(int version, int access, String name, String superName, + String[] interfaces, String sourceFile) { + // creer un writer + cWriter = new ClassWriter(false); + + logger.debug("Converting class " + name + " as remote class"); + + // nouveau nom de fichier + String newSourceFileName = sourceFile.replaceAll("(.*)\\.java$", "$1" + + EXTENSION + ".java"); + + // liste des interfaces + String remoteInterface = Remote.class.getName().replaceAll("\\.", + String.valueOf(File.separatorChar)); + String[] interfacesNew = null; + if (interfaces == null) { + interfacesNew = new String[] { remoteInterface }; + } else { + interfacesNew = new String[interfaces.length + 1]; + for (int i = 0; i < interfaces.length; ++i) + interfacesNew[i] = interfaces[i]; + interfacesNew[interfacesNew.length - 1] = remoteInterface; + } + + cWriter.visit(version, // version de la classe + access, // visibilite + name + EXTENSION, // nom + superName, // superclasse + interfacesNew, // les interface + newSourceFileName); // le fichier sources + } + + /* + * (non-Javadoc) + * + * @see org.objectweb.asm.ClassVisitor#visitAttribute(org.objectweb.asm.Attribute) + */ + public void visitAttribute(Attribute attr) { + logger.warn("Attribute " + attr.toString() + + " found : conversion not supported"); + } + + /* + * (non-Javadoc) + * + * @see org.objectweb.asm.ClassVisitor#visitEnd() + */ + public void visitEnd() { + cWriter.visitEnd(); + } + + /* + * (non-Javadoc) + * + * @see org.objectweb.asm.ClassVisitor#visitField(int, java.lang.String, + * java.lang.String, java.lang.Object, org.objectweb.asm.Attribute) + */ + public void visitField(int access, String name, String desc, Object value, + Attribute attrs) { + logger.warn("Field " + name + " found : conversion not supported"); + } + + /* + * (non-Javadoc) + * + * @see org.objectweb.asm.ClassVisitor#visitInnerClass(java.lang.String, + * java.lang.String, java.lang.String, int) + */ + public void visitInnerClass(String name, String outerName, + String innerName, int access) { + logger.warn("InnerClass " + name + " found : conversion not supported"); + } + + /* + * (non-Javadoc) + * + * @see org.objectweb.asm.ClassVisitor#visitMethod(int, java.lang.String, + * java.lang.String, java.lang.String[], org.objectweb.asm.Attribute) + */ + public CodeVisitor visitMethod(int access, String name, String desc, + String[] exceptions, Attribute attrs) { + logger.debug("Processing method " + name); + + // liste des interfaces + String remoteExceptionName = RemoteException.class.getName() + .replaceAll("\\.", String.valueOf(File.separatorChar)); + String[] exceptionsNew = null; + if (exceptions == null) { + exceptionsNew = new String[] { remoteExceptionName }; + } else { + exceptionsNew = new String[exceptions.length + 1]; + for (int i = 0; i < exceptions.length; ++i) + exceptionsNew[i] = exceptions[i]; + exceptionsNew[exceptionsNew.length - 1] = remoteExceptionName; + } + + cWriter.visitMethod(access, // visibilite + name, // nom + desc, // arguments + exceptionsNew, // les exceptions lancees + attrs); // retour + + return null; + } + + /** + * Retourne le nom d'origine sans l'ajout + * + * @param clazz + * la classe remote + * @return le nom non-remote + */ + public static String getOriginClassName(Class clazz) { + return clazz.getName().replaceAll("(.*)" + EXTENSION + "$", "$1"); + } + + /** + * Retourne la classe version "remote" de celle specifiee + * + * @param clazz + * la classe non remote + * @return la classe remote + * @throws ClassNotFoundException + * si on ne peut pas genere la classe + */ + public static Class getRemoteClass(Class clazz) + throws ClassNotFoundException { + + Class remoteClass = null; + + // onregarde si la ressource existe, + // sinon on la genere + + URL url = ClassLoader.getSystemClassLoader().getResource( + clazz.getName().replaceAll("\\.", "/") + EXTENSION + ".class"); + + if (url == null) { + // classe non trouvee, on la genere + logger.debug("Remote class not found for '" + clazz.getName() + + "', generating a new one"); + + RemoteClassLoader rcl = new RemoteClassLoader(); + // recupere la classe generee + byte[] clazzBytes = rcl.getClassData(clazz); + + try { + // la sauve en dur + rcl.saveOnDisk(clazz, clazzBytes); + } catch (IOException e2) { + logger.debug("Can't save generated class on disk", e2); + throw new ClassNotFoundException("Can't find class : " + + clazz.getName() + EXTENSION, e2); + } + } + + // retente un forName et devrai maintenant la trouver + try { + remoteClass = Class.forName(clazz.getName() + EXTENSION); + } catch (ClassNotFoundException e2) { + logger.debug("Can't find generated class", e2); + throw new ClassNotFoundException("Can't find class : " + + clazz.getName() + EXTENSION, e2); + } + + return remoteClass; + } + + /** + * Sauve la classe generee sur le disque. + * + * Dans un jar, ou ds un fichier... + * + * @param clazz + * La class d'origine + * @param clazzBytes + * La classe generee + * @throws IOException + */ + protected void saveOnDisk(Class clazz, byte[] clazzBytes) + throws IOException { + // ensuite, on la sauve en dur, sur disque + // soit dans un jar, soit sur un fichier physique + // au meme endroit que la classe d'origine + URL originClazzPath = ClassLoader.getSystemClassLoader().getResource( + clazz.getName().replaceAll("\\.", + String.valueOf(File.separatorChar)) + + ".class"); + + // suivant le protocol + // file, jar... + String protocol = originClazzPath.getProtocol(); + + if ("file".equals(protocol)) { + saveInFile(originClazzPath, clazzBytes); + } else if (protocol.matches("ear|jar|war|zip")) { + saveInJarFile(originClazzPath, clazzBytes); + } else { + logger.warn("Unsupported protocol '" + protocol + + "' for saving clazz."); + } + } + + /** + * Sauve le fichier dans un jar. + * + * Java ne supporte pas le modification des jar. On le sauve maintenant dan + * le dossier topiagen. + * + * @param originClazzPath + * @param clazzBytes + * @throws IOException + * si erreur d'ecriture + */ + protected void saveInJarFile(URL originClazzPath, byte[] clazzBytes) + throws IOException { + /* + * TRUEZIP code // write class on disk String path = + * originClazzPath.getFile(); // chemin valid truezip String archive = + * path.replaceAll("^file:(.*)!(.*)\\.class$", "$1"); path = + * path.replaceAll("^file:(.*)!(.*)\\.class$", "$1$2" + EXTENSION + + * ".class"); // File f = new File(path); // f.createNewFile(); + * FileOutputStream out = new FileOutputStream(path); + * out.write(clazzBytes, 0, clazzBytes.length); out.close(); // force + * l'update de l'archive // sinon la modification n'est pas prise en + * compte dans l'excecution // courante de la JVM // File.update(new + * File(archive)); + * + * try { File.umount(new File(archive)); } catch (ArchiveException ouch) { + * logger .debug("ArchiveException , can't umount archive : " + + * archive); // At least one exception occured which is not just an // + * ArchiveWarningException. This is a severe situation that // needs to + * be handled. // Print the sequential chain of exceptions in order of // + * descending priority and ascending appearance. // + * ouch.printStackTrace(); // Print the sequential chain of exceptions + * in order of // appearance instead. + * ouch.sortAppearance().printStackTrace(); } TRUEZIP code + */ + + String path = originClazzPath.getFile().replaceAll( + "^file:(.*)!(.*)\\.class$", "$2" + EXTENSION + ".class"); + + // creer les dossier et fichier + java.io.File fRemoteClass = new java.io.File( + TopiaServiceFactory.TOPIA_GENERATION_DIRECTORY + + String.valueOf(File.separatorChar) + path); + fRemoteClass.getParentFile().mkdirs(); + + // ecrit les donnees + java.io.FileOutputStream out = new java.io.FileOutputStream( + fRemoteClass); + out.write(clazzBytes, 0, clazzBytes.length); + out.close(); + + logger.debug("Remote clazz saved into archive as path : " + + fRemoteClass.getAbsolutePath()); + } + + /** + * Genere la classe dans son fichier phisyque + * + * /home/chatellier/tmp/toto.java file:/home/chatellier/tmp/toto.class + * + * @param originClazzPath + * l'url d'origine + * @param clazzBytes + * les donnees de la classe + * @throws IOException + * si erreur d'ecriture + */ + protected void saveInFile(URL originClazzPath, byte[] clazzBytes) + throws IOException { + // write class on disk + String path = originClazzPath.getFile(); + + // ajout de "Remote" au nom + path = path.replaceAll("\\.class$", EXTENSION + ".class"); + + java.io.File f = new java.io.File(path); + // f.createNewFile(); + java.io.FileOutputStream out = new java.io.FileOutputStream(f); + out.write(clazzBytes, 0, clazzBytes.length); + out.close(); + + logger.debug("Remote class saved to : " + path); + } + + /** + * Convertit la class en class "Remote" + * + * @param clazz + * la classe non remote + * @return la classe remote + */ + private byte[] getClassData(Class clazz) { + byte[] b = null; + + ClassReader cr; + try { + cr = new ClassReader(clazz.getName()); + cr.accept(this, false); + b = cWriter.toByteArray(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return b; + } +} \ No newline at end of file Index: topia2/src/java/org/codelutin/topia/service/servers/SOAPServer.java diff -u /dev/null topia2/src/java/org/codelutin/topia/service/servers/SOAPServer.java:1.1 --- /dev/null Wed Apr 18 12:21:30 2007 +++ topia2/src/java/org/codelutin/topia/service/servers/SOAPServer.java Wed Apr 18 12:21:25 2007 @@ -0,0 +1,106 @@ +/* *##% + * Copyright (C) 2006 Code Lutin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.codelutin.topia.service.servers; + +import java.lang.reflect.Method; + +import org.codehaus.xfire.MessageContext; +import org.codehaus.xfire.XFire; +import org.codehaus.xfire.XFireFactory; +import org.codehaus.xfire.fault.XFireFault; +import org.codehaus.xfire.server.http.XFireHttpServer; +import org.codehaus.xfire.service.Service; +import org.codehaus.xfire.service.binding.ObjectServiceFactory; +import org.codehaus.xfire.service.invoker.Invoker; +import org.codelutin.topia.service.TopiaApplicationService; +import org.codelutin.topia.service.TopiaServiceServerAbstract; + +/** + * SOAPServer.java + * + * @author chatellier + * @version $Revision: 1.1 $ + * + * Last update : $Date: 2007/04/18 12:21:25 $ By : $Author: chatellier $ + */ +public class SOAPServer extends TopiaServiceServerAbstract implements Invoker { + + /** Version UID */ + private static final long serialVersionUID = 3692192673769687321L; + + /** Logger (common logging) */ + //private static final Log logger = LogFactory.getLog(SOAPServer.class); + + /** Port du serveur web */ + protected static final int PORT = 8888; + + /** Server already launched */ + protected boolean alreadyLaunched = false; + + /** + * Constructeur. + */ + public SOAPServer() { + + } + + /* + * (non-Javadoc) + * @see org.codelutin.topia.service.TopiaServiceServer#addService(java.lang.Class) + */ + public void addService(Class clazz) { + + // Create an XFire Service + ObjectServiceFactory serviceFactory = new ObjectServiceFactory(); + Service service = serviceFactory.create(clazz); + //service.setInvoker(new BeanInvoker(new EchoImpl())); + service.setInvoker(this); + + // Register the service in the ServiceRegistry + XFire xfire = XFireFactory.newInstance().getXFire(); + xfire.getServiceRegistry().register(service); + } + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.service.TopiaServiceServer#launch() + */ + public void launch() { + if(!alreadyLaunched) { + // Start the HTTP server + XFireHttpServer server = new XFireHttpServer(); + server.setPort(PORT); + try { + server.start(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + alreadyLaunched = true; + } + } + + /* (non-Javadoc) + * @see org.codehaus.xfire.service.invoker.Invoker#invoke(java.lang.reflect.Method, java.lang.Object[], org.codehaus.xfire.MessageContext) + */ + public Object invoke(Method method, Object[] args, MessageContext ctx) throws XFireFault { + return super.invoke(method, args); + } +} Index: topia2/src/java/org/codelutin/topia/service/servers/RMIServer.java diff -u /dev/null topia2/src/java/org/codelutin/topia/service/servers/RMIServer.java:1.1 --- /dev/null Wed Apr 18 12:21:30 2007 +++ topia2/src/java/org/codelutin/topia/service/servers/RMIServer.java Wed Apr 18 12:21:25 2007 @@ -0,0 +1,173 @@ +/* *##% + * Copyright (C) 2006 Code Lutin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.codelutin.topia.service.servers; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.util.Arrays; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.topia.service.TopiaApplicationService; +import org.codelutin.topia.service.TopiaServiceServerAbstract; + +import sun.rmi.server.UnicastServerRef; + +/** + * RMIServer.java + * + * @author chatellier + * @version $Revision: 1.1 $ + * + * Last update : $Date: 2007/04/18 12:21:25 $ By : $Author: chatellier $ + */ +public class RMIServer extends TopiaServiceServerAbstract implements Runnable, + InvocationHandler { + + /** Logger (common logging) */ + private static final Log logger = LogFactory.getLog(RMIServer.class); + + /** Port de rmiregistry */ + protected final static int PORT = 1099; + + /** instance de registry */ + protected Registry registry; + + /** Server already launched */ + protected boolean alreadyLaunched = false; + + /** + * Constructeur + * @throws RemoteException si la creation echoue + */ + public RMIServer() throws RemoteException { + + // lance rmiregistry + registry = LocateRegistry.createRegistry(PORT); + logger.info("Starting RMIRegistry on port " + PORT + "..."); + } + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.service.TopiaServiceServer#addService(java.lang.Class) + */ + public void addService(final Class clazz) { + // /lDelegationInterfaces.add(clazz); + + // meProxy est le proxy que l'on va bind dans RMI + // meProxy pointe sur this + + // create class that implements Remote and throws RemoteException + // for all methods + try { + Class clazz2 = RemoteClassLoader.getRemoteClass(clazz); + + // logger.debug("Interface list = " + + // Arrays.toString(clazz2.getInterfaces())); + + Remote meProxy = (Remote) Proxy.newProxyInstance(clazz2 + .getClassLoader(), new Class[] { clazz2 }, this); + + Remote stub = new UnicastServerRef(false).exportObject(meProxy, + null, false); + + registry.rebind(clazz.getName(), stub); + + logger.info("Binding new rmi service = " + clazz.getName()); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (RemoteException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + } + + /* + * (non-Javadoc) + * + * @see java.lang.Runnable#run() + */ + public void run() { + + logger.info("RMI Server running..."); + while (true) { + // TODO change (attente passive) + try { + Thread.sleep(Long.MAX_VALUE); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + /* + * (non-Javadoc) + * + * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, + * java.lang.reflect.Method, java.lang.Object[]) + */ + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + + // log + logger.debug("Invoke RMIServer = " + method.getName() + "(" + + Arrays.toString(args) + ")"); + + Class clazzToCall = method.getDeclaringClass(); + // for(Class localClazz : + // lDelegationInterfaces) { + // Class[] interfaces = proxy.getClass().getInterfaces(); + // List asList = Arrays.asList(interfaces); + // if (asList.contains(localClazz)) { // instanceOf marche pas ici + // clazzToCall = localClazz; + // } + // } + + Class realClass = Class.forName(RemoteClassLoader.getOriginClassName(clazzToCall)); + Method realMethod = realClass.getMethod(method.getName(), + (Class[]) method.getParameterTypes()); + + Object result = null; + if (clazzToCall != null) { + logger.debug("Requested class = " + realClass.getName()); + result = super.invoke(realMethod, args); + } + return result; + } + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.service.TopiaServiceServer#launch() + */ + public void launch() { + if(!alreadyLaunched) { + (new Thread(this)).start(); + alreadyLaunched = true; + } + } + +} \ No newline at end of file Index: topia2/src/java/org/codelutin/topia/service/servers/package.html diff -u /dev/null topia2/src/java/org/codelutin/topia/service/servers/package.html:1.1 --- /dev/null Wed Apr 18 12:21:30 2007 +++ topia2/src/java/org/codelutin/topia/service/servers/package.html Wed Apr 18 12:21:25 2007 @@ -0,0 +1,22 @@ + + + + + + + + + + +

Les serveurs par protocole.

+ + Dans ce package, se trouvent les implementation des serveurs suivant les + protocoles. + +

Ils receptionnent les appels et les dispatch sur le TopiaServiceProvider +

+ + + Index: topia2/src/java/org/codelutin/topia/service/servers/XMLRPCServer.java diff -u /dev/null topia2/src/java/org/codelutin/topia/service/servers/XMLRPCServer.java:1.1 --- /dev/null Wed Apr 18 12:21:30 2007 +++ topia2/src/java/org/codelutin/topia/service/servers/XMLRPCServer.java Wed Apr 18 12:21:25 2007 @@ -0,0 +1,143 @@ +/* *##% + * Copyright (C) 2006 Code Lutin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.codelutin.topia.service.servers; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Arrays; + +import org.apache.commons.beanutils.MethodUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.XmlRpcHandler; +import org.apache.xmlrpc.XmlRpcRequest; +import org.apache.xmlrpc.server.XmlRpcHandlerMapping; +import org.apache.xmlrpc.server.XmlRpcServer; +import org.apache.xmlrpc.webserver.WebServer; +import org.codelutin.topia.service.TopiaApplicationService; +import org.codelutin.topia.service.TopiaServiceServerAbstract; + +/** + * XMLRPCServer.java + * + * @author chatellier + * @version $Revision: 1.1 $ + * + * Last update : $Date: 2007/04/18 12:21:25 $ By : $Author: chatellier $ + */ +public class XMLRPCServer extends TopiaServiceServerAbstract implements + XmlRpcHandler, XmlRpcHandlerMapping { + + /** Logger (common logging) */ + private static final Log logger = LogFactory.getLog(XMLRPCServer.class); + + /** Le server Web */ + private WebServer webServer; + + /** Port */ + public static final int port = 9090; + + /** Server already launched */ + protected boolean alreadyLaunched = false; + + /** + * Constructeur. + * + * Initialise le serveur. + */ + public XMLRPCServer() { + webServer = new WebServer(port); + XmlRpcServer xmlRpcServer = webServer.getXmlRpcServer(); + + xmlRpcServer.setHandlerMapping(this); + } + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.service.TopiaServiceServer#addService(java.lang.Class) + */ + public void addService(Class clazz) { + // dans ce cas, rien + } + + /** + * lance le serveur + */ + public void launch() { + if(!alreadyLaunched) { + try { + webServer.start(); + logger.info("XML-RPC server running..."); + } catch (IOException e) { + logger.debug("I/O erreur while launching xml-rpc web serveur", e); + } + alreadyLaunched = true; + } + } + + /* + * (non-Javadoc) + * + * @see org.apache.xmlrpc.XmlRpcHandler#execute(org.apache.xmlrpc.XmlRpcRequest) + */ + public Object execute(XmlRpcRequest xmlrequest) throws XmlRpcException { + Object result = null; + + // conversion des arguments + Object[] args = new Object[xmlrequest.getParameterCount()]; + Class[] argsTypes = new Class[xmlrequest.getParameterCount()]; + for (int i = 0; i < xmlrequest.getParameterCount(); ++i) { + args[i] = xmlrequest.getParameter(i); + argsTypes[i] = xmlrequest.getParameter(i).getClass(); + } + + // conversion class, methode + String call = xmlrequest.getMethodName(); + String className = call.substring(0, call.lastIndexOf(".")); + String methodName = call.substring(call.lastIndexOf(".") + 1); + + logger.debug("Receiving request : " + className + "." + methodName + + "(" + Arrays.toString(args) + ")"); + + Class clazz; + try { + clazz = Class.forName(className); + // get method that matches best via commons beanutils + Method method = MethodUtils.getAccessibleMethod(clazz, methodName, + argsTypes); + result = super.invoke(method, args); + } catch (ClassNotFoundException e) { + logger.debug("Class " + className + " not found !", e); + } + + return result; + } + + /* + * (non-Javadoc) + * + * @see org.apache.xmlrpc.server.XmlRpcHandlerMapping#getHandler(java.lang.String) + */ + public XmlRpcHandler getHandler(String className) throws XmlRpcException { + logger.debug("Request handler for " + className); + return this; + } +}