blob: f7513f66202b98954e149cbe9ed1886c13bd6f12 [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.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Vector;
/**
* This is a SOAP Monitor Service class.
* <p/>
* 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.
* <p/>
* 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).
* <p/>
* Each time a socket connection is established, a new
* thread is created to handle communications from the
* applet.
* <p/>
* 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 serverSocket = 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 (serverSocket == null) {
// Get the server socket port from the init params
ServletConfig config = super.getServletConfig();
String hostName = config.getInitParameter(SOAPMonitorConstants.SOAP_MONITOR_HOST_NAME);
String port = config.getInitParameter(SOAPMonitorConstants.SOAP_MONITOR_PORT);
if (port == null) {
log.error("SOAPMonitorService can't find ServletConfig init parameter 'port'");
port = "0";
}
try {
if (hostName != null) {
serverSocket = new ServerSocket(Integer.parseInt(port),
50,
InetAddress.getByName(hostName));
} else {
serverSocket = 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);
serverSocket = null;
}
if (serverSocket != 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 (serverSocket != null) {
try {
serverSocket.close();
} catch (Exception x) {
}
serverSocket = 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 (serverSocket != null) {
port = serverSocket.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 (serverSocket != null) {
try {
Socket socket = serverSocket.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) {
}
}
}
}
}