| | |
| | | /* |
| | | Transit - Remote procedure calls made simple |
| | | Copyright (c) 2012 Ulrich Hilger |
| | | 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 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. |
| | | 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 <http://www.gnu.org/licenses/>. |
| | | */ |
| | | |
| | | You should have received a copy of the GNU Affero General Public License |
| | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
| | | */ |
| | | package de.uhilger.transit.web; |
| | | |
| | | import de.uhilger.transit.JavaServer; |
| | | import de.uhilger.transit.JsonFlatWandler; |
| | | import de.uhilger.transit.JsonWandler; |
| | | import de.uhilger.transit.NutzerKontext; |
| | | import de.uhilger.transit.XmlWandler; |
| | | import javax.servlet.ServletException; |
| | | |
| | | import javax.servlet.http.HttpServlet; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.Writer; |
| | | import java.io.InputStream; |
| | | import java.io.BufferedReader; |
| | | import java.io.InputStreamReader; |
| | | |
| | | import java.util.Enumeration; |
| | | import java.util.Map; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | import de.uhilger.transit.*; |
| | | |
| | | /** |
| | | * Das TransitServlet macht beliebige Klassen und Methoden |
| | | * ueber HTTP zugaenglich. |
| | | * |
| | | * <p><b>Achtung:</b>Das TransitServlet sollte nur in einem |
| | | * per Authentifizierung und Autorisierung geschuetzten |
| | | * Bereich einer Webanwendung bereitgestellt werden da andernfalls |
| | | * durchweg alle Klassen und Methoden, die sich auf dem Server |
| | | * finden, zugaenglich werden.</p> |
| | | * |
| | | * <p>Fuer die Bereitstellung von Funktionen ist eine Berechtigungspruefung |
| | | * noetig, die am besten in Form eines Filters implementiert wird.</p> |
| | | * |
| | | * Das TransitServlet macht beliebige Klassen und Methoden ueber HTTP |
| | | * zugaenglich. |
| | | * |
| | | * <p> |
| | | * <b>Achtung:</b>Das TransitServlet sollte nur in einem per Authentifizierung |
| | | * und Autorisierung geschuetzten Bereich einer Webanwendung bereitgestellt |
| | | * werden da andernfalls durchweg alle Klassen und Methoden, die sich auf dem |
| | | * Server finden, zugaenglich werden.</p> |
| | | * |
| | | * <p> |
| | | * Fuer die Bereitstellung von Funktionen ist eine Berechtigungspruefung noetig, |
| | | * die am besten in Form eines Filters implementiert wird.</p> |
| | | * |
| | | * @author Copyright (c) Ulrich Hilger, http://uhilger.de |
| | | * @author Published under the terms and conditions of |
| | | * the <a href="http://www.gnu.org/licenses/agpl-3.0" target="_blank">GNU Affero General Public License</a> |
| | | * |
| | | * @author Published under the terms and conditions of the |
| | | * <a href="http://www.gnu.org/licenses/agpl-3.0" target="_blank">GNU Affero |
| | | * General Public License</a> |
| | | * |
| | | * @version 1, September 16, 2012 |
| | | */ |
| | | public class TransitServlet extends HttpServlet { |
| | | public class TransitServlet extends AbstractServlet { |
| | | |
| | | /** Proforma Konstante fuer Schnittstelle Serializable */ |
| | | /** |
| | | * Proforma Konstante fuer Schnittstelle Serializable |
| | | */ |
| | | public static final long serialVersionUID = 42L; |
| | | |
| | | /** Name des Parameters Klasse */ |
| | | |
| | | /** |
| | | * Name des Parameters Klasse |
| | | */ |
| | | public static final String CLASS_NAME = "c"; |
| | | /** Name des Parameters Methode */ |
| | | /** |
| | | * Name des Parameters Methode |
| | | */ |
| | | public static final String METHOD_NAME = "m"; |
| | | /** Name des Parameters Parameter */ |
| | | /** |
| | | * Name des Parameters Parameter |
| | | */ |
| | | public static final String PARAMETER_NAME = "p"; |
| | | /** Name des Parameters Format */ |
| | | /** |
| | | * Name des Parameters Format |
| | | */ |
| | | public static final String FORMAT_NAME = "f"; |
| | | |
| | | public static final String MIME_JSON = "application/json"; |
| | | |
| | | public static final String MIME_XML = "text/xml"; |
| | | |
| | | private static final String[] specialChars = {new String("\u00c4"), new String("\u00d6"), |
| | | new String("\u00dc"), new String("\u00e4"), new String("\u00f6"), new String("\u00fc"), new String("\u00df")}; |
| | | |
| | | |
| | | /** |
| | | * Eine Anfrage via HTTP GET verarbeiten |
| | | * |
| | | * <p>Folgende Parameter werden erwartet:</p> |
| | | * <p>c: Klasse, z.B. de.uhilger.test.EineKlasse<br> |
| | | * |
| | | * <p> |
| | | * Folgende Parameter werden erwartet:</p> |
| | | * <p> |
| | | * c: Klasse, z.B. de.uhilger.test.EineKlasse<br> |
| | | * m: Methode<br> |
| | | * p: Erster Parameter der Methode in der Reihenfolge der Deklaration<br> |
| | | * p: Zweiter Parameter der Methode in der Reihenfolge der Deklaration<br> |
| | | * .<br> |
| | | * .<br> |
| | | * . |
| | | * <br> |
| | | * . |
| | | * <br> |
| | | * p: Letzter Parameter der Methode in der Reihenfolge der Deklaration</p> |
| | | * |
| | | * <p>Das Ergebnis der Verarbeitung wird in Form einer Zeichenkette im |
| | | * Format der JavaScript Object Notation (JSON) in die Antwort der |
| | | * HTTP-Anfrage geschrieben.</p> |
| | | * |
| | | * |
| | | * <p> |
| | | * Das Ergebnis der Verarbeitung wird in Form einer Zeichenkette im Format der |
| | | * JavaScript Object Notation (JSON) in die Antwort der HTTP-Anfrage |
| | | * geschrieben.</p> |
| | | * |
| | | * @param req die Anfrage, die verarbeitet werden soll |
| | | * @param resp das Objekt, mit dem das Ergebnis der Verarbeitung mitgeteilt wird |
| | | * @param resp das Objekt, mit dem das Ergebnis der Verarbeitung mitgeteilt |
| | | * wird |
| | | */ |
| | | @Override |
| | | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { |
| | | anfrageAusfuehren(req, resp); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Eine Anfrage via HTTP POST verarbeiten |
| | | * |
| | | * <p>Folgende Parameter werden erwartet:</p> |
| | | * <p>c: Klasse, z.B. de.uhilger.test.EineKlasse<br> |
| | | * |
| | | * <p> |
| | | * Folgende Parameter werden erwartet:</p> |
| | | * <p> |
| | | * c: Klasse, z.B. de.uhilger.test.EineKlasse<br> |
| | | * m: Methode<br> |
| | | * p: Erster Parameter der Methode in der Reihenfolge der Deklaration<br> |
| | | * p: Zweiter Parameter der Methode in der Reihenfolge der Deklaration<br> |
| | | * .<br> |
| | | * .<br> |
| | | * . |
| | | * <br> |
| | | * . |
| | | * <br> |
| | | * p: Letzter Parameter der Methode in der Reihenfolge der Deklaration</p> |
| | | * |
| | | * <p>Das Ergebnis der Verarbeitung wird in Form einer Zeichenkette im |
| | | * Format der JavaScript Object Notation (JSON) in die Antwort der |
| | | * HTTP-Anfrage geschrieben.</p> |
| | | * |
| | | * |
| | | * <p> |
| | | * Das Ergebnis der Verarbeitung wird in Form einer Zeichenkette im Format der |
| | | * JavaScript Object Notation (JSON) in die Antwort der HTTP-Anfrage |
| | | * geschrieben.</p> |
| | | * |
| | | * @param req die Anfrage, die verarbeitet werden soll |
| | | * @param resp das Objekt, mit dem das Ergebnis der Verarbeitung mitgeteilt wird |
| | | * @param resp das Objekt, mit dem das Ergebnis der Verarbeitung mitgeteilt |
| | | * wird |
| | | */ |
| | | @Override |
| | | protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { |
| | | anfrageAusfuehren(req, resp); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Diese Methode verarbeitet die Anfragen, die via HTTP GET und HTTP POST |
| | | * an dieses Servlet gestellt werden. |
| | | * |
| | | * Diese Methode verarbeitet die Anfragen, die via HTTP GET und HTTP POST an |
| | | * dieses Servlet gestellt werden. |
| | | * |
| | | * @param req die Anfrage, die verarbeitet werden soll |
| | | * @param resp das Objekt, mit dem das Ergebnis der Verarbeitung mitgeteilt wird |
| | | * @param resp das Objekt, mit dem das Ergebnis der Verarbeitung mitgeteilt |
| | | * wird |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public void anfrageAusfuehren(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { |
| | |
| | | List parameterListe = new ArrayList(); |
| | | String formatName = null; |
| | | Enumeration en = req.getParameterNames(); |
| | | while(en.hasMoreElements()) { |
| | | while (en.hasMoreElements()) { |
| | | String pName = en.nextElement().toString(); |
| | | String[] pWerte = req.getParameterValues(pName); |
| | | if(pName.equals(CLASS_NAME)) { |
| | | klassenName = pWerte[0]; |
| | | } else if(pName.equals(METHOD_NAME)) { |
| | | methodenName = pWerte[0]; |
| | | } else if(pName.equals(FORMAT_NAME)) { |
| | | formatName = pWerte[0]; |
| | | } else { |
| | | for(int i = 0; i < pWerte.length; i++) { |
| | | parameterListe.add(pWerte[i]); |
| | | } |
| | | switch (pName) { |
| | | case CLASS_NAME: |
| | | klassenName = pWerte[0]; |
| | | break; |
| | | case METHOD_NAME: |
| | | methodenName = pWerte[0]; |
| | | break; |
| | | case FORMAT_NAME: |
| | | formatName = pWerte[0]; |
| | | break; |
| | | default: |
| | | for (String pWerte1 : pWerte) { |
| | | parameterListe.add(pWerte1); |
| | | } break; |
| | | } |
| | | } |
| | | Object[] parameter = parameterListe.toArray(new Object[0]); |
| | | |
| | | StringBuffer buf = new StringBuffer(); |
| | | server = new JavaServer(); |
| | | server.wandlerHinzufuegen(new JsonWandler()); |
| | | server.wandlerHinzufuegen(new JsonFlatWandler()); |
| | | server.wandlerHinzufuegen(new XmlWandler()); |
| | | Class cls = server.klasseFinden(klassenName); |
| | | if(cls != null) { |
| | | Object o = cls.newInstance(); |
| | | if(o != null) { |
| | | if(o instanceof NutzerKontext) { |
| | | ((NutzerKontext) o).setNutzerId(Waechter.getUserName(req)); |
| | | } |
| | | if(o instanceof WebKontext) { |
| | | ((WebKontext) o).setServletContext(getServletContext()); |
| | | } |
| | | if(o instanceof RequestKontext) { |
| | | ((RequestKontext) o).setRequest(req); |
| | | } |
| | | if(o instanceof VerbindungsKontext) { |
| | | ((VerbindungsKontext) o).setVerbindung(req.getSession()); |
| | | } |
| | | } |
| | | Object resultat = null; |
| | | if(formatName != null) { |
| | | resultat = server.methodeAusfuehren(o, methodenName, formatName, parameter); |
| | | } else { |
| | | resultat = server.methodeAusfuehren(o, methodenName, JsonWandler.FORMAT_JSON, parameter); |
| | | } |
| | | if(resultat != null) { |
| | | if(formatName == null) { |
| | | resp.setContentType(MIME_JSON); |
| | | } else { |
| | | if(formatName.equalsIgnoreCase(JsonWandler.FORMAT_JSON) || formatName.equalsIgnoreCase(JsonFlatWandler.FORMAT_FLATJSON)) { |
| | | resp.setContentType(MIME_JSON); |
| | | } else if(formatName.equalsIgnoreCase(XmlWandler.FORMAT_XML)) { |
| | | resp.setContentType(MIME_XML); |
| | | StringBuilder buf = new StringBuilder(); |
| | | if (istErlaubt(klassenName)) { |
| | | server = new JavaServer(); |
| | | server.wandlerHinzufuegen(new JsonWandler()); |
| | | server.wandlerHinzufuegen(new JsonFlatWandler()); |
| | | server.wandlerHinzufuegen(new XmlWandler()); |
| | | Class cls = server.klasseFinden(klassenName); |
| | | if (cls != null) { |
| | | Object o = cls.newInstance(); |
| | | if (o != null) { |
| | | if (o instanceof NutzerKontext) { |
| | | ((NutzerKontext) o).setNutzerId(getUserName(req)); |
| | | } |
| | | if (o instanceof WebKontext) { |
| | | ((WebKontext) o).setServletContext(getServletContext()); |
| | | } |
| | | if (o instanceof RequestKontext) { |
| | | ((RequestKontext) o).setRequest(req); |
| | | } |
| | | if (o instanceof VerbindungsKontext) { |
| | | ((VerbindungsKontext) o).setVerbindung(req.getSession()); |
| | | } |
| | | } |
| | | buf.append(escapeHtml(resultat.toString())); |
| | | Object resultat = null; |
| | | if (formatName != null) { |
| | | resultat = server.methodeAusfuehren(o, methodenName, formatName, parameter); |
| | | } else { |
| | | resultat = server.methodeAusfuehren(o, methodenName, JsonWandler.FORMAT_JSON, parameter); |
| | | } |
| | | if (resultat != null) { |
| | | if (formatName == null) { |
| | | resp.setContentType(MIME_JSON); |
| | | } else { |
| | | if (formatName.equalsIgnoreCase(JsonWandler.FORMAT_JSON) || formatName.equalsIgnoreCase(JsonFlatWandler.FORMAT_FLATJSON)) { |
| | | resp.setContentType(MIME_JSON); |
| | | } else if (formatName.equalsIgnoreCase(XmlWandler.FORMAT_XML)) { |
| | | resp.setContentType(MIME_XML); |
| | | } |
| | | } |
| | | buf.append(escapeHtml(resultat.toString())); |
| | | } else { |
| | | buf.append("<p>Resultat von server.methodeAusfuehren ist null.</p>"); |
| | | } |
| | | } else { |
| | | buf.append("<p>Resultat von server.methodeAusfuehren ist null.</p>"); |
| | | buf.append("<p>Ergebnis von server.klasseFinden ist null (Klasse nicht gefunden?).</p>"); |
| | | } |
| | | } else { |
| | | buf.append("<p>Ergebnis von server.klasseFinden ist null (Klasse nicht gefunden?).</p>"); |
| | | buf.append("<p>Klasse " + klassenName + " nicht erlaubt.</p>"); |
| | | } |
| | | Writer w = resp.getWriter(); |
| | | w.write(buf.toString()); |
| | | w.flush(); |
| | | w.close(); |
| | | } catch(Exception ex) { |
| | | } catch (Exception ex) { |
| | | throw new ServletException(ex); |
| | | } finally { |
| | | if(server != null) { |
| | | if (server != null) { |
| | | server.aufloesen(); |
| | | server = null; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public String escapeHtml(String text) { |
| | | text = text.replace(specialChars[0], "Ä"); |
| | | text = text.replace(specialChars[1], "Ö"); |
| | | text = text.replace(specialChars[2], "Ü"); |
| | | text = text.replace(specialChars[3], "ä"); |
| | | text = text.replace(specialChars[4], "ö"); |
| | | text = text.replace(specialChars[5], "ü"); |
| | | text = text.replace(specialChars[6], "ß"); |
| | | return text; |
| | | } |
| | | } |
| | | |
| | | } |