/* Transit - Remote procedure calls made simple Copyright (c) 2012 Ulrich Hilger This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package de.uhilger.transit; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Set; import java.util.Iterator; /** * Methoden beliebiger Java-Klassen zur Ausfuehrung bringen und * dabei Methodenaufrufe, Parameter und Rueckgabewerte als * Zeichenketten (Strings) verarbeiten. * * @author Copyright (c) Ulrich Hilger, http://uhilger.de * @author Published under the terms and conditions of * the GNU Affero General Public License * * @version 1, September 16, 2012 */ public class JavaServer implements JavaDienst { /** * Die Sammlung von Wandlern, die dieser Server * verwenden soll um Objekte in Java und zuruck * zu verwandeln */ private HashMap wandler; /** * Ein Objekt der Klasse JavaServer erzeugen */ public JavaServer() { super(); wandler = new HashMap(); } /** * Eine Klasse heraussuchen * * @param klassenName voller Name der gesuchten Klasse, z.B. java.lang.String * @return die Klasse oder null, wenn keine Klasse mit diesem Namen gefunden wurde */ @SuppressWarnings("rawtypes") public Class klasseFinden(String klassenName) throws Exception { Class c = null; c = Class.forName(klassenName); return c; } /** * Eine Methode ausfuehren * * Diese Methode sieht vor, dass ein Methodenname nur einmal in einer * Klasse vorkommt. In Faellen, wo mehrere Methoden einer Klasse den * selben Namen haben, wird die erste Methode dieses Namens verwendet. * * @param klassenName Name der Klasse * @param methodenName Name der Methode * @param format das Format, das Parameter und Rueckgabewert haben * @param parameter die Parameter der Methode * @return der Rueckgabewert der Methode nach der Ausfuehrung */ @SuppressWarnings("rawtypes") public Object methodeAusfuehren(String klassenName, String methodenName, String format, Object... parameter) throws Exception { Object resultat = null; Class c = klasseFinden(klassenName); if(c != null) { resultat = methodeAusfuehren(c.newInstance(), methodenName, format, parameter); } return resultat; } /** * Eine Methode ausfuehren * * Diese Methode sieht vor, dass ein Methodenname nur einmal in einer * Klasse vorkommt. In Faellen, wo mehrere Methoden einer Klasse den * selben Namen haben, wird die erste Methode dieses Namens verwendet. * * @param o ein Objekt der Klasse, die die auszufuehrende Methode enthaelt * @param methodenName Name der Methode * @param format das Format, das Parameter und Rueckgabewert haben * @param parameter die Parameter der Methode * @return der Rueckgabewert der Methode nach der Ausfuehrung */ @SuppressWarnings("rawtypes") public Object methodeAusfuehren(Object o, String methodenName, String format, Object... parameter) throws Exception { Object resultat = null; if(o != null) { Class c = o.getClass(); Method m = findeMethode(c.getDeclaredMethods(), methodenName); resultat = methodeAusfuehren(o, m, format, parameter); } return resultat; } /** * Eine Methode ausfuehren * * @param o ein Objekt der Klasse, die die auszufuehrende Methode enthaelt * @param methode das Methodenobjekt, das ausgefuehrt werden soll * @param format das Format, das Parameter und Rueckgabewert haben * @param parameter die Parameter der Methode * @return der Rueckgabewert der Methode nach der Ausfuehrung */ @SuppressWarnings("rawtypes") public Object methodeAusfuehren(Object o, Method methode, String format, Object... parameter) throws Exception { Object resultat = null; if(methode != null) { Access access = methode.getAnnotation(Access.class); if(access != null && access.type().equals(Access.Type.ALLOW)) { resultat = methode.invoke(o, parameterKonvertieren(methode, parameter, format)); Class returnType = methode.getReturnType(); /* * Wenn der Rueckgabewert der Methode nicht vom Typ String ist, * wird das Objekt in das Format verwandelt, das der Standardwandler * liefert, z.B. JSON */ if(!returnType.getName().equals("java.lang.String")) { //resultat = new JsonWandler().vonJava(resultat, returnType); Wandler w = wandler.get(format); if(w != null) { resultat = w.vonJava(resultat, returnType); } /*if(format == Wandler.JSON) { resultat = new JsonWandler().vonJava(resultat, returnType); }*/ } } else { // nicht zum Zugriff vorgesehen } } return resultat; } /** * Zur Vereinfachung wird hier angenommen, dass es nur Eingangsparamter vom Typ String gibt * * @param m * @param parameter * @return */ @SuppressWarnings("rawtypes") protected Object[] parameterKonvertieren(Method m, Object[] parameter, String format) throws Exception { Object[] resultat = null; if(parameter != null && parameter.length > 0) { resultat = new Object[parameter.length]; Class[] types = m.getParameterTypes(); for(int i = 0; i < types.length; i++) { resultat[i] = toType(types[i], parameter[i].toString(), format); } } return resultat; } /** * Umwandlung von String zu einem anderen Typ * * @param c die Klasse, in deren Typ umgewandelt werden soll * @param parameter der Wert, der umgewandelt werden soll * @return der Parameter umgewandelt in den gewuenschten Typ oder null, falls * die Umwandlung nicht gelang */ @SuppressWarnings("rawtypes") protected Object toType(Class c, String parameter, String format) throws Exception { Object o = null; String className = c.getName(); if(className.equals("java.lang.Integer") || className.equals("int")) { o = Integer.parseInt(parameter); } else if(className.equals("java.lang.Short") || className.equals("short")) { o = Short.parseShort(parameter); } else if(className.equals("java.lang.Boolean") || className.equals("boolean")) { o = Boolean.parseBoolean(parameter); } else if(className.equals("java.lang.Character") || className.equals("char")) { o = Character.valueOf(parameter.charAt(0)); } else if(className.equals("java.lang.Byte") || className.equals("byte")) { o = Byte.parseByte(parameter); } else if(className.equals("java.lang.Long") || className.equals("long")) { o = Long.parseLong(parameter); } else if(className.equals("java.lang.Double") || className.equals("double")) { o = Double.parseDouble(parameter); } else if(className.equals("java.lang.String")) { o = parameter; } else { /* * wenn die Ziel-Klasse keine der vorigen Klasse ist wird angenommen, dass * der Standardwandler das Format erzeugen kann, z.B. aus einem JSON-String */ //o = wandler.get(format).zuJava(parameter, c); //o = new JsonWandler().zuJava(parameter, c); Wandler w = wandler.get(format); if(w != null) { o = w.zuJava(parameter, c); } /*if(format == Wandler.JSON) { o = new JsonWandler().zuJava(parameter, c); }*/ } return o; } /** * Eine Methode aus einer Liste von Methoden heraussuchen * @param methoden die Liste der Methoden * @param methodenName der Name der gesuchten Methode * @return die Methode oder null, wenn die gesuchte Methode nicht gefunden wurde */ protected Method findeMethode(Method[] methoden, String methodenName) { Method methode = null; for(int i = 0; methode == null && i < methoden.length; i++) { Method m = methoden[i]; if(m.getName().equals(methodenName)) { methode = m; } } return methode; } /** * Eine Methode heraussuchen * * Diese Methode sieht vor, dass ein Methodenname nur einmal in einer * Klasse vorkommt. In Faellen, wo mehrere Methoden einer Klasse den * selben Namen haben, wird die erste Methode dieses Namens geliefert. * * @param klassenName Name der Klasse * @param methodenName Name der gesuchten Mthode * @return die Methode oder null, wenn keine Methode mit diesem Namen * in der angegebenen Klasse gefunden wurde */ @SuppressWarnings("rawtypes") public Method methodeFinden(String klassenName, String methodenName) throws Exception { Method m = null; Class klasse = Class.forName(klassenName); if(klasse != null) { m = findeMethode(klasse.getDeclaredMethods(), methodenName); } return m; } /** * Einen Wandler entfernen * * @param wandler der Wandler, der entfernt werden soll */ public void wandlerEntfernen(Wandler wandler) { this.wandler.remove(wandler.getFormat()); } /** * Einen Wandler hinzufuegen * * @param wandler der Wandler, der hinzugefuegt werden soll */ public void wandlerHinzufuegen(Wandler wandler) { this.wandler.put(wandler.getFormat(), wandler); } /** * Diese Instanz aufloesen, also alle Ressourcen frei geben */ public void aufloesen() { Set keySet = wandler.keySet(); Iterator i = keySet.iterator(); while(i.hasNext()) { String key = i.next().toString(); Wandler w = wandler.get(key); w.aufloesen(); w = null; } wandler.clear(); wandler = null; } }