blob: 04ddb34bd0ebd53e7472950937ca101655228324 [file] [log] [blame]
/*
* 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) {}
}
}
}
}