/*
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) {
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);
}*/
}
}
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;
}
}