001: /*
002: * Copyright 2001-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: /*
018: * Modified by Nabh Information Systems, Inc. for Stringbeans Web Services
019: * Framework.
020: *
021: * Modifications (c) 2005 Nabh Information Systems, Inc.
022: */
023: package com.nabhinc.ws.soap;
024:
025: import java.io.IOException;
026: import java.io.ObjectInputStream;
027: import java.io.ObjectOutputStream;
028: import java.net.ServerSocket;
029: import java.net.Socket;
030: import java.util.Enumeration;
031: import java.util.Vector;
032:
033: import org.apache.axis.AxisEngine;
034: import org.apache.axis.Message;
035: import org.apache.axis.MessageContext;
036: import org.apache.axis.SOAPPart;
037: import org.apache.axis.monitor.SOAPMonitorConstants;
038:
039: import com.nabhinc.ws.core.WebServiceException;
040: import com.nabhinc.ws.server.Interceptor;
041: import com.nabhinc.ws.server.InterceptorChain;
042: import com.nabhinc.ws.server.RequestInfo;
043: import com.nabhinc.ws.server.ServerObjectConfig;
044: import com.nabhinc.ws.server.ServerObjectImpl;
045:
046: /**
047: * Stringbeans interceptor that logs SOAP messages. The messages can be viewed
048: * via SOAPMonitor portlet.
049: *
050: * @author Padmanabh Dabke
051: * (c) 2005 Nabh Information Systems, Inc.
052: */
053: public class SOAPMonitor extends ServerObjectImpl implements
054: Interceptor {
055:
056: private static long next_message_id = 1;
057: /**
058: * Private data
059: */
060: public static String smPort = "0";
061: private static ServerSocket server_socket = null;
062: private static Vector connections = null;
063:
064: public void setPort(String p) {
065: smPort = p;
066: }
067:
068: private synchronized Long getID() {
069: next_message_id++;
070: return new Long(next_message_id);
071: }
072:
073: /* (non-Javadoc)
074: * @see com.nabhinc.ws.server.Interceptor#intercept(com.nabhinc.ws.server.RequestInfo, com.nabhinc.ws.server.InterceptorChain)
075: */
076: public void intercept(RequestInfo reqInfo, InterceptorChain chain)
077: throws WebServiceException, IOException {
078:
079: MessageContext msgContext = AxisEngine
080: .getCurrentMessageContext();
081: final Integer reqType = new Integer(
082: SOAPMonitorConstants.SOAP_MONITOR_REQUEST);
083: final Integer respType = new Integer(
084: SOAPMonitorConstants.SOAP_MONITOR_RESPONSE);
085: String target = reqInfo.serviceInfo.name;
086: // Check for null target
087: if (target == null) {
088: target = "";
089: }
090: // Get id, type and content
091: Long id = getID();
092:
093: try {
094: Message msg = msgContext.getRequestMessage();
095: if (msg != null) {
096: String soap = ((SOAPPart) msg.getSOAPPart())
097: .getAsString();
098: if (soap != null) {
099: publishMessage(id, reqType, target, soap);
100: }
101: }
102: chain.doIntercept(reqInfo);
103: } finally {
104: Message msg = msgContext.getResponseMessage();
105: if (msg != null) {
106: String soap = ((SOAPPart) msg.getSOAPPart())
107: .getAsString();
108: if (soap != null) {
109: publishMessage(id, respType, target, soap);
110: }
111: }
112:
113: }
114: }
115:
116: /* (non-Javadoc)
117: * @see com.nabhinc.ws.server.ServerObject#init(com.nabhinc.ws.server.ServerObjectConfig)
118: */
119: public void init(ServerObjectConfig config)
120: throws WebServiceException {
121: super .init(config);
122: if (connections == null) {
123: // Create vector to hold connection information
124: connections = new Vector();
125: }
126: if (server_socket == null) {
127: // Get the server socket port from the init params
128: try {
129: // Try to open the server socket
130: server_socket = new ServerSocket(Integer
131: .parseInt(smPort));
132: smPort = Integer.toString(server_socket.getLocalPort());
133: } catch (Exception e) {
134: // Let someone know we could not open the socket
135: throw new WebServiceException(
136: "Failed to open server socket.", e);
137: }
138: if (server_socket != null) {
139: // Start the server socket thread
140: new Thread(new ServerSocketThread()).start();
141: }
142: }
143: }
144:
145: /* (non-Javadoc)
146: * @see com.nabhinc.ws.core.BaseObject#destroy()
147: */
148: public void destroy() {
149: // End all connection threads
150: Enumeration e = connections.elements();
151: while (e.hasMoreElements()) {
152: ConnectionThread ct = (ConnectionThread) e.nextElement();
153: ct.close();
154: }
155: // End main server socket thread
156: if (server_socket != null) {
157: try {
158: server_socket.close();
159: } catch (Exception x) {
160: }
161: server_socket = null;
162: }
163:
164: }
165:
166: /**
167: * Publish a SOAP message to listeners
168: */
169: public static void publishMessage(Long id, Integer type,
170: String target, String soap) {
171: if (connections != null) {
172: Enumeration e = connections.elements();
173: while (e.hasMoreElements()) {
174: ConnectionThread ct = (ConnectionThread) e
175: .nextElement();
176: ct.publishMessage(id, type, target, soap);
177: }
178: }
179: }
180:
181: /**
182: * Thread class for handling the server socket
183: */
184: class ServerSocketThread implements Runnable {
185:
186: /**
187: * Thread for handling the server socket
188: */
189: public void run() {
190: // Wait for socket connections
191: while (server_socket != null) {
192: try {
193: Socket socket = server_socket.accept();
194: new Thread(new ConnectionThread(socket)).start();
195: } catch (IOException ioe) {
196: }
197: }
198: }
199: }
200:
201: /**
202: * Thread class for handling socket connections
203: */
204: class ConnectionThread implements Runnable {
205:
206: private Socket socket = null;
207: private ObjectInputStream in = null;
208: private ObjectOutputStream out = null;
209: private boolean closed = false;
210:
211: /**
212: * Constructor
213: */
214: @SuppressWarnings("unchecked")
215: public ConnectionThread(Socket s) {
216: socket = s;
217: try {
218: // Use object streams for input and output
219: //
220: // NOTE: We need to be sure to create and flush the
221: // output stream first because the ObjectOutputStream
222: // constructor writes a header to the stream that is
223: // needed by the ObjectInputStream on the other end
224: out = new ObjectOutputStream(socket.getOutputStream());
225: out.flush();
226: in = new ObjectInputStream(socket.getInputStream());
227: } catch (Exception e) {
228: }
229: // Add the connection to our list
230: synchronized (connections) {
231: connections.addElement(this );
232: }
233: }
234:
235: /**
236: * Close the socket connection
237: */
238: public void close() {
239: closed = true;
240: try {
241: socket.close();
242: } catch (IOException ioe) {
243: }
244: }
245:
246: /**
247: * Thread to handle the socket connection
248: */
249: public void run() {
250: try {
251: while (!closed) {
252: /* Object o = */in.readObject();
253: }
254: } catch (Exception e) {
255: }
256: // Cleanup connection list
257: synchronized (connections) {
258: connections.removeElement(this );
259: }
260: // Cleanup I/O streams
261: if (out != null) {
262: try {
263: out.close();
264: } catch (IOException ioe) {
265: }
266: out = null;
267: }
268: if (in != null) {
269: try {
270: in.close();
271: } catch (IOException ioe) {
272: }
273: in = null;
274: }
275: // Be sure the socket is closed
276: close();
277: }
278:
279: /**
280: * Publish SOAP message information
281: */
282: public synchronized void publishMessage(Long id,
283: Integer message_type, String target, String soap) {
284: // If we have a valid output stream, then
285: // send the data to the applet
286: if (out != null) {
287: try {
288: switch (message_type.intValue()) {
289: case SOAPMonitorConstants.SOAP_MONITOR_REQUEST:
290: out.writeObject(message_type);
291: out.writeObject(id);
292: out.writeObject(target);
293: out.writeObject(soap);
294: out.flush();
295: break;
296: case SOAPMonitorConstants.SOAP_MONITOR_RESPONSE:
297: out.writeObject(message_type);
298: out.writeObject(id);
299: out.writeObject(soap);
300: out.flush();
301: break;
302: }
303: } catch (Exception e) {
304: }
305: }
306: }
307: }
308:
309: }
|