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