001: package de.schlund.pfixcore.webservice;
002:
003: import java.io.BufferedInputStream;
004: import java.io.IOException;
005: import java.io.InputStream;
006: import java.io.PrintWriter;
007: import java.lang.reflect.Method;
008: import java.net.HttpURLConnection;
009: import java.text.SimpleDateFormat;
010: import java.util.Date;
011: import java.util.regex.Matcher;
012: import java.util.regex.Pattern;
013:
014: import javax.servlet.ServletException;
015: import javax.servlet.http.HttpServletRequest;
016: import javax.servlet.http.HttpServletResponse;
017: import javax.servlet.http.HttpSession;
018:
019: import de.schlund.pfixcore.webservice.config.GlobalServiceConfig;
020: import de.schlund.pfixcore.webservice.config.ServiceConfig;
021: import de.schlund.pfixcore.webservice.monitor.MonitorHistory;
022: import de.schlund.pfixcore.webservice.monitor.MonitorRecord;
023:
024: public class AdminWebapp {
025:
026: ServiceRuntime runtime;
027:
028: public AdminWebapp(ServiceRuntime runtime) {
029: this .runtime = runtime;
030: }
031:
032: public void doGet(HttpServletRequest req, HttpServletResponse res)
033: throws ServletException, IOException {
034: HttpSession session = req.getSession(false);
035: String qs = req.getQueryString();
036: if (qs == null) {
037: sendBadRequest(req, res);
038: } else if (qs.equalsIgnoreCase("WSDL")) {
039: if (runtime.getConfiguration().getGlobalServiceConfig()
040: .getWSDLSupportEnabled()) {
041: String pathInfo = req.getPathInfo();
042: String serviceName;
043: if (pathInfo.startsWith("/")) {
044: serviceName = pathInfo.substring(1);
045: } else {
046: serviceName = pathInfo;
047: }
048: ServiceConfig conf = runtime.getConfiguration()
049: .getServiceConfig(serviceName);
050: String type = conf.getSessionType();
051: if (type.equals(Constants.SESSION_TYPE_SERVLET)
052: && session == null) {
053: sendForbidden(req, res);
054: return;
055: }
056: res.setContentType("text/xml");
057: String repoPath = runtime.getConfiguration()
058: .getGlobalServiceConfig().getWSDLRepository();
059: InputStream in = session.getServletContext()
060: .getResourceAsStream(
061: repoPath + "/" + serviceName + ".wsdl");
062: if (in != null) {
063: PrintWriter writer = res.getWriter();
064: if (type.equals(Constants.SESSION_TYPE_SERVLET)) {
065: StringBuffer sb = new StringBuffer();
066: BufferedInputStream bis = new BufferedInputStream(
067: in);
068: int ch = 0;
069: while ((ch = bis.read()) != -1) {
070: sb.append((char) ch);
071: }
072: String str = sb.toString();
073: String sid = Constants.SESSION_PREFIX
074: + session.getId();
075: Pattern pat = Pattern
076: .compile("(wsdlsoap:address location=\"[^\"]*)");
077: Matcher mat = pat.matcher(str);
078: sb = new StringBuffer();
079: while (mat.find()) {
080: mat.appendReplacement(sb, mat.group(1)
081: + sid);
082: }
083: mat.appendTail(sb);
084: str = sb.toString();
085: writer.println(str);
086: } else {
087: BufferedInputStream bis = new BufferedInputStream(
088: in);
089: int ch = 0;
090: while ((ch = bis.read()) != -1) {
091: writer.write(ch);
092: }
093: }
094: writer.close();
095: } else
096: sendError(req, res);
097: } else
098: sendForbidden(req, res);
099: } else if (qs.equalsIgnoreCase("monitor")) {
100: if (session != null
101: && runtime.getConfiguration()
102: .getGlobalServiceConfig()
103: .getMonitoringEnabled()) {
104: sendMonitor(req, res);
105: } else
106: sendForbidden(req, res);
107: } else if (qs.equalsIgnoreCase("admin")) {
108: if (session != null
109: && runtime.getConfiguration()
110: .getGlobalServiceConfig().getAdminEnabled()) {
111: sendAdmin(req, res);
112: } else
113: sendForbidden(req, res);
114: } else if (req.getParameter("wsscript") != null) {
115: try {
116: runtime.getStub(req, res);
117: } catch (ServiceException x) {
118: throw new ServletException(
119: "Can't get webservice stub.", x);
120: }
121: } else
122: sendBadRequest(req, res);
123: }
124:
125: protected void sendForbidden(HttpServletRequest req,
126: HttpServletResponse res) throws IOException {
127: PrintWriter writer = res.getWriter();
128: res.setStatus(HttpURLConnection.HTTP_FORBIDDEN);
129: res.setContentType("text/html");
130: writer.println("<h2>Forbidden!</h2>");
131: writer.close();
132: }
133:
134: protected void sendBadRequest(HttpServletRequest req,
135: HttpServletResponse res) throws IOException {
136: PrintWriter writer = res.getWriter();
137: res.setStatus(HttpURLConnection.HTTP_BAD_REQUEST);
138: res.setContentType("text/html");
139: writer.println("<h2>Bad request!</h2>");
140: writer.close();
141: }
142:
143: protected void sendError(HttpServletRequest req,
144: HttpServletResponse res) throws IOException {
145: PrintWriter writer = res.getWriter();
146: res.setStatus(HttpURLConnection.HTTP_INTERNAL_ERROR);
147: res.setContentType("text/html");
148: writer.println("<h2>Internal server error!</h2>");
149: writer.close();
150: }
151:
152: public void sendAdmin(HttpServletRequest req,
153: HttpServletResponse res) throws IOException {
154: PrintWriter writer = res.getWriter();
155:
156: //TODO: source out html
157: HttpSession session = req.getSession(false);
158: if (session != null
159: && runtime.getConfiguration().getGlobalServiceConfig()
160: .getAdminEnabled()) {
161: res.setStatus(HttpURLConnection.HTTP_OK);
162: res.setContentType("text/html");
163: writer
164: .println("<html><head><title>Webservice admin</title>"
165: + getJS() + getCSS() + "</head><body>");
166: writer
167: .println("<div class=\"title\">Webservice admin</div><div class=\"content\">");
168: writer.println("<table>");
169: writer.println("<tr><td>");
170: GlobalServiceConfig globConf = runtime.getConfiguration()
171: .getGlobalServiceConfig();
172: for (ServiceConfig srvConf : runtime.getConfiguration()
173: .getServiceConfig()) {
174: String name = srvConf.getName();
175: writer.println("<p>");
176: writer.println("<b>" + name + "</b>");
177: if (srvConf.getProtocolType().equals(
178: Constants.PROTOCOL_TYPE_ANY)
179: || srvConf.getProtocolType().equals(
180: Constants.PROTOCOL_TYPE_SOAP)) {
181: String wsdlUri = req.getRequestURI() + "/" + name
182: + ";jsessionid=" + session.getId()
183: + "?WSDL";
184: writer
185: .println(" <a style=\"color:#666666\" target=\"_blank\" href=\""
186: + wsdlUri
187: + "\" title=\"Show generated WSDL\">WSDL</a>");
188: String soapUri = req.getContextPath() + "/xml"
189: + globConf.getStubRepository() + "/"
190: + srvConf.getName() + ".js";
191: writer
192: .println(" <a style=\"color:#666666\" target=\"_blank\" href=\""
193: + soapUri
194: + "\" title=\"Show generated SOAP Javascript stub\">SOAP JS</a>");
195: }
196: if (srvConf.getProtocolType().equals(
197: Constants.PROTOCOL_TYPE_ANY)
198: || srvConf.getProtocolType().equals(
199: Constants.PROTOCOL_TYPE_JSONWS)) {
200: String jsonwsUri = req.getRequestURI()
201: + "?wsscript&name=" + srvConf.getName()
202: + "&type=jsonws";
203: writer
204: .println(" <a style=\"color:#666666\" target=\"_blank\" href=\""
205: + jsonwsUri
206: + "\" title=\"Show generated JSONWS Javascript stub\">JSONWS JS</a>");
207: }
208: writer.println("<br/>");
209: try {
210: ServiceDescriptor desc = runtime
211: .getServiceDescriptorCache()
212: .getServiceDescriptor(srvConf);
213: writer.println("<ul>");
214: for (String methName : desc.getMethods()) {
215: for (Method meth : desc.getMethods(methName)) {
216:
217: writer.println("<li>" + meth.getName());
218: }
219: }
220: writer.println("</ul>");
221: } catch (ServiceException x) {
222: writer.println("<p style=\"color:red\">ERROR: "
223: + x.getMessage() + "</p>");
224: }
225: writer.println("</p>");
226: }
227: writer.println("</td></tr>");
228: writer.println("</table");
229: writer.println("</div></body></html>");
230: writer.close();
231: } else
232: sendForbidden(req, res);
233: }
234:
235: public void sendMonitor(HttpServletRequest req,
236: HttpServletResponse res) throws IOException {
237: PrintWriter writer = res.getWriter();
238: //TODO: source out html
239: if (runtime.getConfiguration().getGlobalServiceConfig()
240: .getMonitoringEnabled()) {
241: res.setStatus(HttpURLConnection.HTTP_OK);
242: res.setContentType("text/html");
243: MonitorHistory history = runtime.getMonitor()
244: .getMonitorHistory(req);
245: SimpleDateFormat format = new SimpleDateFormat(
246: "MM-dd-yyyy HH:mm:ss");
247: writer
248: .println("<html><head><title>Webservice monitor</title>"
249: + getJS() + getCSS() + "</head><body>");
250: writer
251: .println("<div class=\"title\">Webservice monitor</div><div class=\"content\">");
252: writer.println("<table class=\"overview\">");
253: writer.println("<tr>");
254: writer
255: .println("<th align=\"left\" title=\"Date/time of receipt\">Start</th>");
256: writer
257: .println("<th align=\"left\" title=\"Service protocol type\">Protocol</th>");
258: writer
259: .println("<th align=\"left\" title=\"Service name\">Service</th>");
260: writer
261: .println("<th align=\"left\" title=\"Service method name\">Method</th>");
262: writer
263: .println("<th align=\"left\" title=\"Service processing time in ms (including delivery)\">Processing</th>");
264: writer
265: .println("<th align=\"left\" title=\"Service method invocation time in ms\">Invocation</th>");
266: writer.println("</tr>");
267: MonitorRecord[] records = history.getRecords();
268: for (int i = 0; i < records.length; i++) {
269: MonitorRecord record = records[i];
270: String id = "entry" + i;
271: String styleClass = "nosel";
272: if (i == records.length - 1)
273: styleClass = "sel";
274: writer.println("<tr class=\"" + styleClass
275: + "\" onclick=\"toggleDetails(this,'" + id
276: + "')\">");
277: writer
278: .println("<td align=\"left\">"
279: + format.format(new Date(record
280: .getStartTime())) + "</td>");
281: writer.println("<td align=\"left\">"
282: + record.getProtocol() + "</td>");
283: writer.println("<td align=\"left\">"
284: + record.getService() + "</td>");
285: writer.println("<td align=\"left\">"
286: + (record.getMethod() == null ? "n/a" : record
287: .getMethod()) + "</td>");
288: writer
289: .println("<td align=\"right\">"
290: + (record.getProcessingTime() == -1 ? "n/a"
291: : record.getProcessingTime())
292: + "</td>");
293: writer
294: .println("<td align=\"right\">"
295: + (record.getInvocationTime() == -1 ? "n/a"
296: : record.getInvocationTime())
297: + "</td>");
298: writer.println("</tr>");
299: }
300: writer.println("</table>");
301: for (int i = 0; i < records.length; i++) {
302: MonitorRecord record = records[i];
303: String id = "entry" + i;
304: String display = "none";
305: if (i == records.length - 1)
306: display = "block";
307: writer.println("<div class=\"detail_entry\" id=\"" + id
308: + "\" style=\"display:" + display + "\">");
309: writer.println("<table width=\"800px\">");
310: writer.println("<tr>");
311: writer
312: .println("<td width=\"400px\"><b>Request:</b><br/><div class=\"body\"><pre>");
313: String reqMsg = record.getRequestMessage();
314: if (reqMsg == null)
315: reqMsg = "Not available";
316: writer.println(htmlEscape(reqMsg));
317: writer.println("</pre></div></td>");
318: writer
319: .println("<td width=\"400px\"><b>Response:</b><br/><div class=\"body\"><pre>");
320: String resMsg = record.getResponseMessage();
321: if (resMsg == null)
322: resMsg = "Not available";
323: writer.println(htmlEscape(resMsg));
324: writer.println("</pre></div></td>");
325: writer.println("</tr>");
326:
327: writer.println("</table>");
328: writer.println("</div>");
329: }
330: writer.println("</div></body></html>");
331: writer.close();
332: } else
333: sendForbidden(req, res);
334: }
335:
336: private String getJS() {
337: //TODO: source out js
338: String js = "<script type=\"text/javascript\">"
339: + " function toggleDetails(src,id) {"
340: + " var elems=document.getElementsByTagName('tr');"
341: + " for(var i=0;i<elems.length;i++) {"
342: + " if(elems[i].className=='sel') {"
343: + " elems[i].className='nosel';" + " }"
344: + " }" + " src.className='sel';"
345: + " elems=document.getElementsByTagName('div');"
346: + " for(var i=0;i<elems.length;i++) {"
347: + " if(elems[i].className=='detail_entry') {"
348: + " if(elems[i].id==id) {"
349: + " elems[i].style.display='block';"
350: + " } else {"
351: + " elems[i].style.display='none';"
352: + " }" + " }" + " }" + " }"
353: + "</script>";
354: return js;
355: }
356:
357: private String htmlEscape(String text) {
358: text = text.replaceAll("&", "&");
359: text = text.replaceAll("<", "<");
360: text = text.replaceAll(">", ">");
361: return text;
362: }
363:
364: private String getCSS() {
365: //TODO: source out css
366: String css = "<style type=\"text/css\">"
367: + " body {margin:0pt;border:0pt;background-color:#b6cfe4}"
368: + " div.content {padding:5pt;}"
369: + " div.title {padding:5pt;font-size:18pt;width:100%;background-color:black;color:white}"
370: + " table.overview td,th {padding-bottom:5pt;padding-right:15pt}"
371: + " table.overview tr.nosel {cursor:pointer;color:#666666;}"
372: + " table.overview tr.sel {cursor:pointer;color:#000000;}"
373: + " div.body {width:500px;height:300px;overflow:auto;background-color:#FFFFFF;border:1px solid #000000;}"
374: + " div.headers {width:500px;height:100px;overflow:auto;background-color:#FFFFFF;border:1px solid #000000;}"
375: + " div.detail_entry {display:none;} " + "</style>";
376: return css;
377: }
378:
379: }
|