| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.axis2.soapmonitor.servlet; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| import javax.servlet.ServletConfig; |
| 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.ObjectInputStream; |
| import java.io.ObjectOutputStream; |
| import java.net.ServerSocket; |
| import java.net.Socket; |
| import java.util.Enumeration; |
| import java.util.Vector; |
| |
| /** |
| * This is a SOAP Monitor Service class. |
| * |
| * During the HTTP server startup, the servlet init method |
| * is invoked. This allows the code to open a server |
| * socket that will be used to communicate with running |
| * applets. |
| * |
| * When an HTTP GET request is received, the servlet |
| * dynamically produces an HTML document to load the SOAP |
| * monitor applet and supply the port number being used by |
| * the server socket (so the applet will know how to |
| * connect back to the server). |
| * |
| * Each time a socket connection is established, a new |
| * thread is created to handle communications from the |
| * applet. |
| * |
| * The publishMethod routine is invoked by the SOAP monitor |
| * handler when a SOAP message request or response is |
| * detected. The information about the SOAP message is |
| * then forwared to all current socket connections for |
| * display by the applet. |
| */ |
| |
| public class SOAPMonitorService extends HttpServlet { |
| |
| /** |
| * Private data |
| */ |
| private static ServerSocket server_socket = null; |
| private static Vector connections = null; |
| |
| private static final Log log = LogFactory.getLog(SOAPMonitorService.class); |
| |
| /** |
| * Constructor |
| */ |
| public SOAPMonitorService() { |
| } |
| |
| |
| /** |
| * Publish a SOAP message to listeners |
| */ |
| public static void publishMessage(Long id, |
| Integer type, |
| String target, |
| String soap) { |
| if (connections != null) { |
| Enumeration e = connections.elements(); |
| while (e.hasMoreElements()) { |
| ConnectionThread ct = (ConnectionThread) e.nextElement(); |
| ct.publishMessage(id,type,target,soap); |
| } |
| } |
| } |
| |
| /** |
| * Servlet initialiation |
| */ |
| public void init() throws ServletException { |
| if (connections == null) { |
| // Create vector to hold connection information |
| connections = new Vector(); |
| } |
| if (server_socket == null) { |
| // Get the server socket port from the init params |
| ServletConfig config = super.getServletConfig(); |
| String port = config.getInitParameter(SOAPMonitorConstants.SOAP_MONITOR_PORT); |
| if (port == null) { |
| log.error("SOAPMonitorService can't find ServletConfig init parameter 'port'"); |
| port = "0"; |
| } |
| try { |
| // Try to open the server socket |
| server_socket = new ServerSocket(Integer.parseInt(port)); |
| } catch (Exception ex) { |
| // Let someone know we could not open the socket |
| log.error("Unable to open server socket using port: " + port); |
| log.error(ex.getMessage(), ex); |
| // Fail as loudly as possible for those without logging configured |
| config.getServletContext().log("Unable to open server socket using port "+port+":", ex); |
| server_socket = null; |
| } |
| if (server_socket != null) { |
| // Start the server socket thread |
| new Thread(new ServerSocketThread()).start(); |
| } |
| } |
| } |
| |
| /** |
| * Servlet termination |
| */ |
| public void destroy() { |
| // End all connection threads |
| Enumeration e = connections.elements(); |
| while (e.hasMoreElements()) { |
| ConnectionThread ct = (ConnectionThread) e.nextElement(); |
| ct.close(); |
| } |
| // End main server socket thread |
| if (server_socket != null) { |
| try { |
| server_socket.close(); |
| } catch (Exception x) {} |
| server_socket = null; |
| } |
| } |
| |
| /** |
| * HTTP GET request |
| */ |
| public void doGet(HttpServletRequest request, HttpServletResponse response) |
| throws IOException, ServletException |
| { |
| // Create HTML to load the SOAP monitor applet |
| int port = 0; |
| if (server_socket != null) { |
| port = server_socket.getLocalPort(); |
| log.debug("Sending param to SOAP monitor applet as port: " + port); |
| } |
| response.setContentType("text/html"); |
| response.getWriter().println("<html>"); |
| response.getWriter().println("<head>"); |
| response.getWriter().println("<title>SOAP Monitor</title>"); |
| response.getWriter().println("</head>"); |
| response.getWriter().println("<body>"); |
| response.getWriter().println("<object classid=\"clsid:8AD9C840-044E-11D1-B3E9-00805F499D93\" width=100% height=100% codebase=\"http://java.sun.com/products/plugin/1.3/jinstall-13-win32.cab#Version=1,3,0,0\">"); |
| response.getWriter().println("<param name=code value=org.apache.axis2.soapmonitor.applet.SOAPMonitorApplet.class>"); |
| response.getWriter().println("<param name=\"type\" value=\"application/x-java-applet;version=1.3\">"); |
| response.getWriter().println("<param name=\"scriptable\" value=\"false\">"); |
| response.getWriter().println("<param name=\"port\" value=\""+port+"\">"); |
| response.getWriter().println("<comment>"); |
| response.getWriter().println("<embed type=\"application/x-java-applet;version=1.3\" code=org.apache.axis2.soapmonitor.applet.SOAPMonitorApplet.class width=100% height=100% port=\""+port+"\" scriptable=false pluginspage=\"http://java.sun.com/products/plugin/1.3/plugin-install.html\">"); |
| response.getWriter().println("<noembed>"); |
| response.getWriter().println("</comment>"); |
| response.getWriter().println("</noembed>"); |
| response.getWriter().println("</embed>"); |
| response.getWriter().println("</object>"); |
| response.getWriter().println("</body>"); |
| response.getWriter().println("</html>"); |
| } |
| |
| /** |
| * Thread class for handling the server socket |
| */ |
| class ServerSocketThread implements Runnable { |
| |
| /** |
| * Thread for handling the server socket |
| */ |
| public void run() { |
| // Wait for socket connections |
| while (server_socket != null) { |
| try { |
| Socket socket = server_socket.accept(); |
| new Thread(new ConnectionThread(socket)).start(); |
| } catch (IOException ioe) {} |
| } |
| } |
| } |
| |
| /** |
| * Thread class for handling socket connections |
| */ |
| class ConnectionThread implements Runnable { |
| |
| private Socket socket = null; |
| private ObjectInputStream in = null; |
| private ObjectOutputStream out = null; |
| private boolean closed = false; |
| |
| /** |
| * Constructor |
| */ |
| public ConnectionThread(Socket s) { |
| socket = s; |
| try { |
| // Use object streams for input and output |
| // |
| // NOTE: We need to be sure to create and flush the |
| // output stream first because the ObjectOutputStream |
| // constructor writes a header to the stream that is |
| // needed by the ObjectInputStream on the other end |
| out = new ObjectOutputStream(socket.getOutputStream()); |
| out.flush(); |
| in = new ObjectInputStream(socket.getInputStream()); |
| } catch (Exception e) {} |
| // Add the connection to our list |
| synchronized (connections) { |
| connections.addElement(this); |
| } |
| } |
| |
| /** |
| * Close the socket connection |
| */ |
| public void close() { |
| closed = true; |
| try { |
| socket.close(); |
| } catch (IOException ioe) {} |
| } |
| |
| /** |
| * Thread to handle the socket connection |
| */ |
| public void run() { |
| try { |
| while (!closed) { |
| Object o = in.readObject(); |
| } |
| } catch (Exception e) {} |
| // Cleanup connection list |
| synchronized (connections) { |
| connections.removeElement(this); |
| } |
| // Cleanup I/O streams |
| if (out != null) { |
| try { |
| out.close(); |
| } catch (IOException ioe) {} |
| out = null; |
| } |
| if (in != null) { |
| try { |
| in.close(); |
| } catch (IOException ioe) {} |
| in = null; |
| } |
| // Be sure the socket is closed |
| close(); |
| } |
| |
| /** |
| * Publish SOAP message information |
| */ |
| public synchronized void publishMessage(Long id, |
| Integer message_type, |
| String target, |
| String soap) { |
| // If we have a valid output stream, then |
| // send the data to the applet |
| if (out != null) { |
| try { |
| switch (message_type.intValue()) { |
| case SOAPMonitorConstants.SOAP_MONITOR_REQUEST: |
| out.writeObject(message_type); |
| out.writeObject(id); |
| out.writeObject(target); |
| out.writeObject(soap); |
| out.flush(); |
| break; |
| case SOAPMonitorConstants.SOAP_MONITOR_RESPONSE: |
| out.writeObject(message_type); |
| out.writeObject(id); |
| out.writeObject(soap); |
| out.flush(); |
| break; |
| } |
| } catch (Exception e) {} |
| } |
| } |
| } |
| } |
| |