Source code: org/apache/axis/monitor/SOAPMonitorService.java
1 /*
2 * Copyright 2001-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.apache.axis.monitor;
18
19 import javax.servlet.ServletConfig;
20 import javax.servlet.ServletException;
21 import javax.servlet.http.HttpServlet;
22 import javax.servlet.http.HttpServletRequest;
23 import javax.servlet.http.HttpServletResponse;
24 import java.io.IOException;
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27 import java.net.ServerSocket;
28 import java.net.Socket;
29 import java.util.Enumeration;
30 import java.util.Vector;
31
32 /**
33 * This is a SOAP Monitor Service class.
34 *
35 * During the HTTP server startup, the servlet init method
36 * is invoked. This allows the code to open a server
37 * socket that will be used to communicate with running
38 * applets.
39 *
40 * When an HTTP GET request is received, the servlet
41 * dynamically produces an HTML document to load the SOAP
42 * monitor applet and supply the port number being used by
43 * the server socket (so the applet will know how to
44 * connect back to the server).
45 *
46 * Each time a socket connection is established, a new
47 * thread is created to handle communications from the
48 * applet.
49 *
50 * The publishMethod routine is invoked by the SOAP monitor
51 * handler when a SOAP message request or response is
52 * detected. The information about the SOAP message is
53 * then forwared to all current socket connections for
54 * display by the applet.
55 *
56 * @author Brian Price (pricebe@us.ibm.com)
57 * xdoclet tags are not active yet; keep web.xml in sync
58 * @web.servlet name="SOAPMonitorService" display-name="SOAPMonitorService" load-on-startup="100"
59 * @web.servlet-mapping url-pattern="/SOAPMonitor"
60 * @web.servlet-init-param name="SOAPMonitorPort" value="5001"
61 */
62
63 public class SOAPMonitorService extends HttpServlet {
64
65 /**
66 * Private data
67 */
68 private static ServerSocket server_socket = null;
69 private static Vector connections = null;
70
71 /**
72 * Constructor
73 */
74 public SOAPMonitorService() {
75 }
76
77
78 /**
79 * Publish a SOAP message to listeners
80 */
81 public static void publishMessage(Long id,
82 Integer type,
83 String target,
84 String soap) {
85 if (connections != null) {
86 Enumeration e = connections.elements();
87 while (e.hasMoreElements()) {
88 ConnectionThread ct = (ConnectionThread) e.nextElement();
89 ct.publishMessage(id,type,target,soap);
90 }
91 }
92 }
93
94 /**
95 * Servlet initialiation
96 */
97 public void init() throws ServletException {
98 if (connections == null) {
99 // Create vector to hold connection information
100 connections = new Vector();
101 }
102 if (server_socket == null) {
103 // Get the server socket port from the init params
104 ServletConfig config = super.getServletConfig();
105 String port = config.getInitParameter(SOAPMonitorConstants.SOAP_MONITOR_PORT);
106 if (port == null) {
107 // No port defined, so let the system assign a port
108 port = "0";
109 }
110 try {
111 // Try to open the server socket
112 server_socket = new ServerSocket(Integer.parseInt(port));
113 } catch (Exception e) {
114 // Let someone know we could not open the socket
115 // System. out.println("Unable to open server socket using port "+port+".");
116 server_socket = null;
117 }
118 if (server_socket != null) {
119 // Start the server socket thread
120 new Thread(new ServerSocketThread()).start();
121 }
122 }
123 }
124
125 /**
126 * Servlet termination
127 */
128 public void destroy() {
129 // End all connection threads
130 Enumeration e = connections.elements();
131 while (e.hasMoreElements()) {
132 ConnectionThread ct = (ConnectionThread) e.nextElement();
133 ct.close();
134 }
135 // End main server socket thread
136 if (server_socket != null) {
137 try {
138 server_socket.close();
139 } catch (Exception x) {}
140 server_socket = null;
141 }
142 }
143
144 /**
145 * HTTP GET request
146 */
147 public void doGet(HttpServletRequest request, HttpServletResponse response)
148 throws IOException, ServletException
149 {
150 // Create HTML to load the SOAP monitor applet
151 int port = 0;
152 if (server_socket != null) {
153 port = server_socket.getLocalPort();
154 }
155 response.setContentType("text/html");
156 response.getWriter().println("<html>");
157 response.getWriter().println("<head>");
158 response.getWriter().println("<title>SOAP Monitor</title>");
159 response.getWriter().println("</head>");
160 response.getWriter().println("<body>");
161 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\">");
162 response.getWriter().println("<param name=code value=SOAPMonitorApplet.class>");
163 response.getWriter().println("<param name=\"type\" value=\"application/x-java-applet;version=1.3\">");
164 response.getWriter().println("<param name=\"scriptable\" value=\"false\">");
165 response.getWriter().println("<param name=\"port\" value=\""+port+"\">");
166 response.getWriter().println("<comment>");
167 response.getWriter().println("<embed type=\"application/x-java-applet;version=1.3\" code=SOAPMonitorApplet.class width=100% height=100% port=\""+port+"\" scriptable=false pluginspage=\"http://java.sun.com/products/plugin/1.3/plugin-install.html\">");
168 response.getWriter().println("<noembed>");
169 response.getWriter().println("</comment>");
170 response.getWriter().println("</noembed>");
171 response.getWriter().println("</embed>");
172 response.getWriter().println("</object>");
173 response.getWriter().println("</body>");
174 response.getWriter().println("</html>");
175 }
176
177 /**
178 * Thread class for handling the server socket
179 */
180 class ServerSocketThread implements Runnable {
181
182 /**
183 * Thread for handling the server socket
184 */
185 public void run() {
186 // Wait for socket connections
187 while (server_socket != null) {
188 try {
189 Socket socket = server_socket.accept();
190 new Thread(new ConnectionThread(socket)).start();
191 } catch (IOException ioe) {}
192 }
193 }
194 }
195
196 /**
197 * Thread class for handling socket connections
198 */
199 class ConnectionThread implements Runnable {
200
201 private Socket socket = null;
202 private ObjectInputStream in = null;
203 private ObjectOutputStream out = null;
204 private boolean closed = false;
205
206 /**
207 * Constructor
208 */
209 public ConnectionThread(Socket s) {
210 socket = s;
211 try {
212 // Use object streams for input and output
213 //
214 // NOTE: We need to be sure to create and flush the
215 // output stream first because the ObjectOutputStream
216 // constructor writes a header to the stream that is
217 // needed by the ObjectInputStream on the other end
218 out = new ObjectOutputStream(socket.getOutputStream());
219 out.flush();
220 in = new ObjectInputStream(socket.getInputStream());
221 } catch (Exception e) {}
222 // Add the connection to our list
223 synchronized (connections) {
224 connections.addElement(this);
225 }
226 }
227
228 /**
229 * Close the socket connection
230 */
231 public void close() {
232 closed = true;
233 try {
234 socket.close();
235 } catch (IOException ioe) {}
236 }
237
238 /**
239 * Thread to handle the socket connection
240 */
241 public void run() {
242 try {
243 while (!closed) {
244 Object o = in.readObject();
245 }
246 } catch (Exception e) {}
247 // Cleanup connection list
248 synchronized (connections) {
249 connections.removeElement(this);
250 }
251 // Cleanup I/O streams
252 if (out != null) {
253 try {
254 out.close();
255 } catch (IOException ioe) {}
256 out = null;
257 }
258 if (in != null) {
259 try {
260 in.close();
261 } catch (IOException ioe) {}
262 in = null;
263 }
264 // Be sure the socket is closed
265 close();
266 }
267
268 /**
269 * Publish SOAP message information
270 */
271 public synchronized void publishMessage(Long id,
272 Integer message_type,
273 String target,
274 String soap) {
275 // If we have a valid output stream, then
276 // send the data to the applet
277 if (out != null) {
278 try {
279 switch (message_type.intValue()) {
280 case SOAPMonitorConstants.SOAP_MONITOR_REQUEST:
281 out.writeObject(message_type);
282 out.writeObject(id);
283 out.writeObject(target);
284 out.writeObject(soap);
285 out.flush();
286 break;
287 case SOAPMonitorConstants.SOAP_MONITOR_RESPONSE:
288 out.writeObject(message_type);
289 out.writeObject(id);
290 out.writeObject(soap);
291 out.flush();
292 break;
293 }
294 } catch (Exception e) {}
295 }
296 }
297 }
298 }
299