Java Web Services via REST bereitstellen
ulrich
2014-11-16 1da1cadfe51b9fc9970091e0d2ee6bedbcfd859b
commit | author | age
ca8e1e 1 /*
1da1ca 2  Transit - Remote procedure calls made simple
U 3  Copyright (c) 2012  Ulrich Hilger
ca8e1e 4
1da1ca 5  This program is free software: you can redistribute it and/or modify
U 6  it under the terms of the GNU Affero General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
ca8e1e 9
1da1ca 10  This program is distributed in the hope that it will be useful,
U 11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  GNU Affero General Public License for more details.
ca8e1e 14
1da1ca 15  You should have received a copy of the GNU Affero General Public License
U 16  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
ca8e1e 18 package de.uhilger.transit.web;
U 19
20 import javax.servlet.ServletException;
21
22 import javax.servlet.http.HttpServletRequest;
23 import javax.servlet.http.HttpServletResponse;
24
25 import java.io.IOException;
26 import java.io.Writer;
27
28 import java.util.Enumeration;
29 import java.util.ArrayList;
30 import java.util.List;
31
32 import de.uhilger.transit.*;
33
34 /**
1da1ca 35  * Das TransitServlet macht beliebige Klassen und Methoden ueber HTTP
U 36  * zugaenglich.
37  *
38  * <p>
39  * <b>Achtung:</b>Das TransitServlet sollte nur in einem per Authentifizierung
40  * und Autorisierung geschuetzten Bereich einer Webanwendung bereitgestellt
41  * werden da andernfalls durchweg alle Klassen und Methoden, die sich auf dem
42  * Server finden, zugaenglich werden.</p>
43  *
44  * <p>
45  * Fuer die Bereitstellung von Funktionen ist eine Berechtigungspruefung noetig,
46  * die am besten in Form eines Filters implementiert wird.</p>
47  *
ca8e1e 48  * @author Copyright (c) Ulrich Hilger, http://uhilger.de
1da1ca 49  * @author Published under the terms and conditions of the
U 50  * <a href="http://www.gnu.org/licenses/agpl-3.0" target="_blank">GNU Affero
51  * General Public License</a>
52  *
ca8e1e 53  * @version 1, September 16, 2012
U 54  */
1da1ca 55 public class TransitServlet extends AbstractServlet {
ca8e1e 56
1da1ca 57   /**
U 58    * Proforma Konstante fuer Schnittstelle Serializable
59    */
ca8e1e 60   public static final long serialVersionUID = 42L;
1da1ca 61
U 62   /**
63    * Name des Parameters Klasse
64    */
ca8e1e 65   public static final String CLASS_NAME = "c";
1da1ca 66   /**
U 67    * Name des Parameters Methode
68    */
ca8e1e 69   public static final String METHOD_NAME = "m";
1da1ca 70   /**
U 71    * Name des Parameters Parameter
72    */
ca8e1e 73   public static final String PARAMETER_NAME = "p";
1da1ca 74   /**
U 75    * Name des Parameters Format
76    */
ca8e1e 77   public static final String FORMAT_NAME = "f";
1da1ca 78
ca8e1e 79   /**
U 80    * Eine Anfrage via HTTP GET verarbeiten
1da1ca 81    *
U 82    * <p>
83    * Folgende Parameter werden erwartet:</p>
84    * <p>
85    * c: Klasse, z.B. de.uhilger.test.EineKlasse<br>
ca8e1e 86    * m: Methode<br>
U 87    * p: Erster Parameter der Methode in der Reihenfolge der Deklaration<br>
88    * p: Zweiter Parameter der Methode in der Reihenfolge der Deklaration<br>
1da1ca 89    * .
U 90    * <br>
91    * .
92    * <br>
ca8e1e 93    * p: Letzter Parameter der Methode in der Reihenfolge der Deklaration</p>
1da1ca 94    *
U 95    * <p>
96    * Das Ergebnis der Verarbeitung wird in Form einer Zeichenkette im Format der
97    * JavaScript Object Notation (JSON) in die Antwort der HTTP-Anfrage
98    * geschrieben.</p>
99    *
ca8e1e 100    * @param req die Anfrage, die verarbeitet werden soll
1da1ca 101    * @param resp das Objekt, mit dem das Ergebnis der Verarbeitung mitgeteilt
U 102    * wird
ca8e1e 103    */
U 104   @Override
105   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
106     anfrageAusfuehren(req, resp);
107   }
1da1ca 108
ca8e1e 109   /**
U 110    * Eine Anfrage via HTTP POST verarbeiten
1da1ca 111    *
U 112    * <p>
113    * Folgende Parameter werden erwartet:</p>
114    * <p>
115    * c: Klasse, z.B. de.uhilger.test.EineKlasse<br>
ca8e1e 116    * m: Methode<br>
U 117    * p: Erster Parameter der Methode in der Reihenfolge der Deklaration<br>
118    * p: Zweiter Parameter der Methode in der Reihenfolge der Deklaration<br>
1da1ca 119    * .
U 120    * <br>
121    * .
122    * <br>
ca8e1e 123    * p: Letzter Parameter der Methode in der Reihenfolge der Deklaration</p>
1da1ca 124    *
U 125    * <p>
126    * Das Ergebnis der Verarbeitung wird in Form einer Zeichenkette im Format der
127    * JavaScript Object Notation (JSON) in die Antwort der HTTP-Anfrage
128    * geschrieben.</p>
129    *
ca8e1e 130    * @param req die Anfrage, die verarbeitet werden soll
1da1ca 131    * @param resp das Objekt, mit dem das Ergebnis der Verarbeitung mitgeteilt
U 132    * wird
ca8e1e 133    */
U 134   @Override
135   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
136     anfrageAusfuehren(req, resp);
137   }
1da1ca 138
ca8e1e 139   /**
1da1ca 140    * Diese Methode verarbeitet die Anfragen, die via HTTP GET und HTTP POST an
U 141    * dieses Servlet gestellt werden.
142    *
ca8e1e 143    * @param req die Anfrage, die verarbeitet werden soll
1da1ca 144    * @param resp das Objekt, mit dem das Ergebnis der Verarbeitung mitgeteilt
U 145    * wird
ca8e1e 146    */
U 147   @SuppressWarnings("unchecked")
148   public void anfrageAusfuehren(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
149     JavaServer server = null;
150     try {
151       String klassenName = null;
152       String methodenName = null;
153       List parameterListe = new ArrayList();
154       String formatName = null;
155       Enumeration en = req.getParameterNames();
1da1ca 156       while (en.hasMoreElements()) {
ca8e1e 157         String pName = en.nextElement().toString();
U 158         String[] pWerte = req.getParameterValues(pName);
1da1ca 159         if (pName.equals(CLASS_NAME)) {
ca8e1e 160           klassenName = pWerte[0];
1da1ca 161         } else if (pName.equals(METHOD_NAME)) {
ca8e1e 162           methodenName = pWerte[0];
1da1ca 163         } else if (pName.equals(FORMAT_NAME)) {
ca8e1e 164           formatName = pWerte[0];
U 165         } else {
1da1ca 166           for (int i = 0; i < pWerte.length; i++) {
ca8e1e 167             parameterListe.add(pWerte[i]);
U 168           }
169         }
170       }
171       Object[] parameter = parameterListe.toArray(new Object[0]);
1da1ca 172       StringBuilder buf = new StringBuilder();
U 173       if (istErlaubt(klassenName)) {
174         server = new JavaServer();
175         server.wandlerHinzufuegen(new JsonWandler());
176         server.wandlerHinzufuegen(new JsonFlatWandler());
177         server.wandlerHinzufuegen(new XmlWandler());
178         Class cls = server.klasseFinden(klassenName);
179         if (cls != null) {
180           Object o = cls.newInstance();
181           if (o != null) {
182             if (o instanceof NutzerKontext) {
183               ((NutzerKontext) o).setNutzerId(getUserName(req));
184             }
185             if (o instanceof WebKontext) {
186               ((WebKontext) o).setServletContext(getServletContext());
187             }
188             if (o instanceof RequestKontext) {
189               ((RequestKontext) o).setRequest(req);
190             }
191             if (o instanceof VerbindungsKontext) {
192               ((VerbindungsKontext) o).setVerbindung(req.getSession());
ca8e1e 193             }
U 194           }
1da1ca 195           Object resultat = null;
U 196           if (formatName != null) {
197             resultat = server.methodeAusfuehren(o, methodenName, formatName, parameter);
198           } else {
199             resultat = server.methodeAusfuehren(o, methodenName, JsonWandler.FORMAT_JSON, parameter);
200           }
201           if (resultat != null) {
202             if (formatName == null) {
203               resp.setContentType(MIME_JSON);
204             } else {
205               if (formatName.equalsIgnoreCase(JsonWandler.FORMAT_JSON) || formatName.equalsIgnoreCase(JsonFlatWandler.FORMAT_FLATJSON)) {
206                 resp.setContentType(MIME_JSON);
207               } else if (formatName.equalsIgnoreCase(XmlWandler.FORMAT_XML)) {
208                 resp.setContentType(MIME_XML);
209               }
210             }
211             buf.append(escapeHtml(resultat.toString()));
212           } else {
213             buf.append("<p>Resultat von server.methodeAusfuehren ist null.</p>");
214           }
ca8e1e 215         } else {
1da1ca 216           buf.append("<p>Ergebnis von server.klasseFinden ist null (Klasse nicht gefunden?).</p>");
ca8e1e 217         }
U 218       } else {
1da1ca 219         buf.append("<p>Klasse " + klassenName + " nicht erlaubt.</p>");
ca8e1e 220       }
U 221       Writer w = resp.getWriter();
222       w.write(buf.toString());
223       w.flush();
224       w.close();
1da1ca 225     } catch (Exception ex) {
ca8e1e 226       throw new ServletException(ex);
U 227     } finally {
1da1ca 228       if (server != null) {
ca8e1e 229         server.aufloesen();
U 230         server = null;
231       }
232     }
233   }
1da1ca 234
U 235 }