/******************************************************************************* * Copyright (c) 2009 MATERNA Information & Communications. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html. For further * project-related information visit http://www.ws4d.org. The most recent * version of the JMEDS framework can be obtained from * http://sourceforge.net/projects/ws4d-javame. ******************************************************************************/ package org.ws4d.java.communication.protocol.soap.server; import java.io.IOException; import java.io.InputStream; import org.ws4d.java.DPWSFramework; import org.ws4d.java.communication.ProtocolData; import org.ws4d.java.communication.connection.ip.IPAddress; import org.ws4d.java.communication.monitor.MonitorStreamFactory; import org.ws4d.java.communication.monitor.MonitoredMessageReceiver; import org.ws4d.java.communication.monitor.MonitoringContext; import org.ws4d.java.communication.protocol.http.HTTPGroup; import org.ws4d.java.communication.protocol.http.HTTPResponse; import org.ws4d.java.communication.protocol.http.header.HTTPRequestHeader; import org.ws4d.java.communication.protocol.http.server.HTTPRequestHandler; import org.ws4d.java.communication.protocol.http.server.HTTPServer; import org.ws4d.java.communication.protocol.soap.SOAPResponse; import org.ws4d.java.communication.protocol.soap.generator.MessageReceiver; import org.ws4d.java.communication.protocol.soap.generator.SOAPMessageGeneratorFactory; import org.ws4d.java.message.Message; import org.ws4d.java.structures.HashMap; import org.ws4d.java.types.InternetMediaType; import org.ws4d.java.types.URI; /** * This class allows the creation of a SOAP Server to handle incoming SOAP * message requests. */ public class SOAPServer { /** * The underlying HTTP server. */ private HTTPServer server = null; /** * This table contains the created SOAP servers. */ private static HashMap servers = new HashMap(); /** * Returns a SOAP server based on the given HTTP server implementation. If * no server exists, a new server will be created. * * @param server the HTTP server to use. * @return the new SOAP server. */ public synchronized static SOAPServer get(HTTPServer server) { SOAPServer soapsrv = (SOAPServer) servers.get(server); if (soapsrv != null) return soapsrv; soapsrv = new SOAPServer(server); servers.put(server, soapsrv); return soapsrv; } public synchronized static void unregisterAndStop(SOAPServer server) throws IOException { HTTPServer httpServer = server.getHTTPServer(); servers.remove(httpServer); server.stop(); HTTPServer.unregisterAndStop(httpServer); } /** * Returns a SOAP server and the underlying HTTP server for the given * address and port. If no server exists, a new server will be created. * * @param address the host address for the underlying HTTP server. * @param port the port for the underlying HTTP server. * @return the new SOAP server. * @throws IOException Throws exception if the HTTP server could not listen * to the given address and port. */ public synchronized static SOAPServer get(IPAddress ipAddress, int port, boolean secure, String alias) throws IOException { HTTPServer server = HTTPServer.get(ipAddress, port, secure, alias); return get(server); } /** * Creates the SOAP server with the HTTP server. * * @param server the underlying HTTP server. */ private SOAPServer(HTTPServer server) { this.server = server; } /** * Registers a HTTP path for a given {@link MessageReceiver}. * <p> * The receiver will receive incoming SOAP messages which match the HTTP * path. * </p> * * @param path HTTP path. * @param receiver the SOAP message receiver */ public void register(String path, SOAPHandler handler, HTTPGroup user) { server.register(path, InternetMediaType.getSOAPXML(), handler, user); } /** * Removes the registration of a {@link MessageReceiver} for a given HTTP * path. * * @param path the HTTP path. * @return the removed {@link MessageReceiver}. */ public MessageReceiver unregister(String path) { return (SOAPHandler) server.unregister(path, InternetMediaType.getSOAPXML()); } /** * Returns the underlying HTTP server. * * @return the HTTP server. */ public HTTPServer getHTTPServer() { return server; } /** * Starts the SOAP server. * * @throws IOException */ public synchronized void start() throws IOException { server.start(); } /** * Stops the SOAP Server. * * @throws IOException */ public synchronized void stop() throws IOException { server.stop(); } /** * The default HTTP handler which handles SOAP-over-HTTP requests. */ public static abstract class SOAPHandler implements HTTPRequestHandler, MessageReceiver { // key = thread, value = HTTPResponse private final HashMap responses = new HashMap(); protected SOAPHandler() { super(); } /* * (non-Javadoc) * @see * org.ws4d.java.communication.protocol.httpx.server.HTTPRequestHandler * #handle(org.ws4d.java.types.uri.URI, * org.ws4d.java.communication.protocol.http.HTTPRequestHeader, * java.io.InputStream) */ public final HTTPResponse handle(URI request, HTTPRequestHeader header, InputStream body, ProtocolData protocolData, MonitoringContext context) throws IOException { /* * Gets the HTTP request body if possible */ final MessageReceiver r; MonitorStreamFactory monFac = DPWSFramework.getMonitorStreamFactory(); if (monFac != null) { r = new MonitoredMessageReceiver(this, context); } else { r = this; } SOAPMessageGeneratorFactory.getInstance().getSOAP2MessageGeneratorForCurrentThread().deliverMessage(body, r, protocolData); /* * after delivering the request message, the corresponding response * will be immediately available within field 'response' */ synchronized (responses) { return (HTTPResponse) responses.remove(Thread.currentThread()); } } protected final void respond(int httpStatus, Message responseMessage) { /* * this takes care of attachments sufficiently (concerns Invoke and * Fault messages) */ synchronized (responses) { responses.put(Thread.currentThread(), new SOAPResponse(httpStatus, responseMessage)); } } } }