/*******************************************************************************
* 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;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.ws4d.java.DPWSFramework;
import org.ws4d.java.communication.AttachmentStoreHandler;
import org.ws4d.java.communication.CommunicationManager;
import org.ws4d.java.communication.DPWSProtocolInfo;
import org.ws4d.java.communication.ProtocolData;
import org.ws4d.java.communication.ProtocolInfo;
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.HTTPRequest;
import org.ws4d.java.communication.protocol.http.HTTPResponseHandler;
import org.ws4d.java.communication.protocol.http.header.HTTPRequestHeader;
import org.ws4d.java.communication.protocol.http.header.HTTPResponseHeader;
import org.ws4d.java.communication.protocol.mime.DefaultMIMEHandler;
import org.ws4d.java.communication.protocol.mime.MIMEEntityInput;
import org.ws4d.java.communication.protocol.mime.MIMEHandler;
import org.ws4d.java.communication.protocol.soap.generator.MessageReceiver;
import org.ws4d.java.communication.protocol.soap.generator.SOAPMessageGeneratorFactory;
import org.ws4d.java.configuration.DPWSProperties;
import org.ws4d.java.configuration.HTTPProperties;
import org.ws4d.java.constants.DPWSMessageConstants;
import org.ws4d.java.constants.HTTPConstants;
import org.ws4d.java.constants.MIMEConstants;
import org.ws4d.java.dispatch.MessageInformer;
import org.ws4d.java.message.FaultMessage;
import org.ws4d.java.message.InvokeMessage;
import org.ws4d.java.message.Message;
import org.ws4d.java.service.parameter.ParameterValue;
import org.ws4d.java.structures.List;
import org.ws4d.java.structures.Queue;
import org.ws4d.java.types.InternetMediaType;
import org.ws4d.java.util.ParameterUtil;
/**
*
*/
public class SOAPRequest implements HTTPRequest {
private static final MessageInformer MESSAGE_INFORMER = MessageInformer.getInstance();
private final Message request;
private final MessageReceiver receiver;
private final HTTPRequestHeader header;
private String mimeBoundary = null;
private List mimeEntities = null;
/**
* @param targetADdress
* @param request
* @param receiver
*/
public SOAPRequest(String requestPath, Message request, MessageReceiver receiver) {
super();
this.request = request;
this.receiver = receiver;
header = new HTTPRequestHeader(HTTPConstants.HTTP_METHOD_POST, requestPath, HTTPConstants.HTTP_VERSION11);
int chunkedMode = -1;
/*
* Check for HTTP chunk coding global settings.
*/
if (request != null) {
ProtocolInfo pvi = request.getProtocolInfo();
if (pvi instanceof DPWSProtocolInfo) {
DPWSProtocolInfo dpvi = (DPWSProtocolInfo) pvi;
chunkedMode = dpvi.getHttpRequestChunkedMode();
}
}
/*
* Check for HTTP chunk coding address settings.
*/
String adr = request.getTargetAddress().toString();
chunkedMode = HTTPProperties.getInstance().getChunkMode(adr);
if (chunkedMode > -1) {
System.out.println("chunk mode changed to " + chunkedMode + "!");
}
if (chunkedMode == DPWSProperties.HTTP_CHUNKED_ON) {
header.addHeaderFieldValue(HTTPConstants.HTTP_HEADER_TRANSFER_ENCODING, HTTPConstants.HTTP_HEADERVALUE_TRANSFERCODING_CHUNKED);
} else if (chunkedMode == DPWSProperties.HTTP_CHUNKED_ON_FOR_INVOKE) {
if (request.getType() == Message.INVOKE_MESSAGE) {
header.addHeaderFieldValue(HTTPConstants.HTTP_HEADER_TRANSFER_ENCODING, HTTPConstants.HTTP_HEADERVALUE_TRANSFERCODING_CHUNKED);
}
}
String contentType = InternetMediaType.getSOAPXML().getMediaType();
if (request.getType() == DPWSMessageConstants.INVOKE_MESSAGE) {
InvokeMessage invoke = (InvokeMessage) request;
ParameterValue pv = invoke.getContent();
if (pv != null && ParameterUtil.hasAttachment(pv)) {
mimeBoundary = DefaultMIMEHandler.createMimeBoundary();
InternetMediaType mimeType = InternetMediaType.cloneAndSetParameter(InternetMediaType.getMultipartRelated(), MIMEConstants.PARAMETER_BOUNDARY, mimeBoundary);
contentType = mimeType.toString();
mimeEntities = ParameterUtil.getAttachments(pv);
}
}
header.addHeaderFieldValue(HTTPConstants.HTTP_HEADER_CONTENT_TYPE, contentType);
header.addHeaderFieldValue(HTTPConstants.HTTP_HEADER_TE, HTTPConstants.HTTP_HEADERVALUE_TE_TRAILERS);
}
/*
* (non-Javadoc)
* @see
* org.ws4d.java.communication.protocol.http.HTTPRequest#getRequestHeader()
*/
public HTTPRequestHeader getRequestHeader() {
return header;
}
/*
* (non-Javadoc)
* @see
* org.ws4d.java.communication.protocol.http.HTTPRequest#getResponseHandler
* (org.ws4d.java.communication.InternetMediaType)
*/
public HTTPResponseHandler getResponseHandler(InternetMediaType mediaType) throws IOException {
if (InternetMediaType.getSOAPXML().equals(mediaType)) {
return new HTTPResponseHandler() {
/*
* (non-Javadoc)
* @see
* org.ws4d.java.communication.protocol.http.HTTPResponseHandler
* #handle(org.ws4d.java.communication.protocol.http.header.
* HTTPResponseHeader, java.io.InputStream,
* org.ws4d.java.communication.protocol.http.HTTPRequest,
* org.ws4d.java.communication.DPWSProtocolData,
* org.ws4d.java.io.monitor.MonitoringContext)
*/
public void handle(HTTPResponseHeader header, InputStream body, HTTPRequest request, ProtocolData protocolData, MonitoringContext context) throws IOException {
int httpStatus = header.getStatus();
// TODO filter other potentially empty HTTP responses
if (httpStatus == 202 || httpStatus == 204) {
return;
}
MessageReceiver r;
MonitorStreamFactory monFac = DPWSFramework.getMonitorStreamFactory();
if (monFac != null) {
r = new MonitoredMessageReceiver(receiver, context);
} else {
r = receiver;
}
boolean hasBody = false;
String strLen = header.getHeaderFieldValue(HTTPConstants.HTTP_HEADER_CONTENT_LENGTH);
if (strLen != null) {
int len = Integer.parseInt(strLen.trim());
hasBody = len > 0;
} else {
/*
* find out whether there are at least some bytes within
* the body
*/
hasBody = body.available() > 0;
}
if (hasBody) {
SOAPMessageGeneratorFactory.getInstance().getSOAP2MessageGeneratorForCurrentThread().deliverMessage(body, r, protocolData);
} else {
/*
* regardless of the actual HTTP status code (be it a
* 4xx, 5xx or another one), if we get here, this means
* the other side is responding with a content type of
* application/soap+xml, but without a SOAP message
* within the HTTP body; so we can safely assume this is
* a faulty condition and deliver a dummy SOAP fault
* instead
*/
r.receive(FaultMessage.createEndpointUnavailableFault(SOAPRequest.this.request), protocolData);
}
}
};
} else if (InternetMediaType.getMultipartRelated().equals(mediaType)) {
DefaultMIMEHandler mimeHandler = new DefaultMIMEHandler();
mimeHandler.register(InternetMediaType.getApplicationXOPXML(), new MIMEHandler() {
/*
* (non-Javadoc)
* @seeorg.ws4d.java.communication.protocol.mime.MIMEHandler#
* handleResponse
* (org.ws4d.java.communication.protocol.mime.MIMEEntityInput,
* org.ws4d.java.communication.DPWSProtocolData,
* org.ws4d.java.io.monitor.MonitoringContext)
*/
public void handleResponse(MIMEEntityInput part, ProtocolData protocolData, MonitoringContext context) throws IOException {
MessageReceiver r;
MonitorStreamFactory monFac = DPWSFramework.getMonitorStreamFactory();
if (monFac != null) {
r = new MonitoredMessageReceiver(receiver, context);
} else {
r = receiver;
}
SOAPMessageGeneratorFactory.getInstance().getSOAP2MessageGeneratorForCurrentThread().deliverMessage(part.getBodyInputStream(), r, protocolData);
}
/*
* (non-Javadoc)
* @seeorg.ws4d.java.communication.protocol.mime.MIMEHandler#
* handleRequest
* (org.ws4d.java.communication.protocol.mime.MIMEEntityInput,
* org.ws4d.java.structures.Queue,
* org.ws4d.java.communication.DPWSProtocolData,
* org.ws4d.java.io.monitor.MonitoringContext)
*/
public void handleRequest(MIMEEntityInput part, Queue responses, ProtocolData protocolData, MonitoringContext context) throws IOException {
// void
}
});
mimeHandler.register(2, -1, AttachmentStoreHandler.getInstance());
return mimeHandler;
} else if (InternetMediaType.getTextHTML().equals(mediaType)) {
/*
* we may get text/html response e.g. when other side sends a
* HTTP-level error like 404, etc.
*/
return new HTTPResponseHandler() {
/*
* (non-Javadoc)
* @see
* org.ws4d.java.communication.protocol.http.HTTPResponseHandler
* #handle(org.ws4d.java.communication.protocol.http.header.
* HTTPResponseHeader, java.io.InputStream,
* org.ws4d.java.communication.protocol.http.HTTPRequest,
* org.ws4d.java.communication.DPWSProtocolData,
* org.ws4d.java.io.monitor.MonitoringContext)
*/
public void handle(HTTPResponseHeader header, InputStream body, HTTPRequest request, ProtocolData protocolData, MonitoringContext context) throws IOException {
MessageReceiver r;
MonitorStreamFactory monFac = DPWSFramework.getMonitorStreamFactory();
if (monFac != null) {
r = new MonitoredMessageReceiver(receiver, context);
} else {
r = receiver;
}
if (header.getStatus() == 401) {
r.receive(FaultMessage.createAuthenticationFault(SOAPRequest.this.request), protocolData);
} else {
r.receive(FaultMessage.createEndpointUnavailableFault(SOAPRequest.this.request), protocolData);
}
}
};
}
return null;
}
/*
* (non-Javadoc)
* @see
* org.ws4d.java.communication.protocol.http.HTTPRequest#requestSendFailed
* (java.lang.Exception, org.ws4d.java.communication.ProtocolData)
*/
public void requestSendFailed(Exception e, ProtocolData protocolData) {
receiver.sendFailed(e, protocolData);
}
/*
* (non-Javadoc)
* @see
* org.ws4d.java.communication.protocol.http.HTTPRequest#responseReceiveFailed
* (java.lang.Exception, org.ws4d.java.communication.ProtocolData)
*/
public void responseReceiveFailed(Exception e, ProtocolData protocolData) {
receiver.receiveFailed(e, protocolData);
}
/*
* (non-Javadoc)
* @see
* org.ws4d.java.communication.protocol.http.HTTPRequest#serializeRequestBody
* (java.io.OutputStream, org.ws4d.java.communication.ProtocolData,
* org.ws4d.java.io.monitor.MonitoringContext)
*/
public void serializeRequestBody(OutputStream out, ProtocolData protocolData, MonitoringContext context) throws IOException {
CommunicationManager comMan = DPWSFramework.getCommunicationManager(protocolData.getCommunicationManagerId());
comMan.serializeMessageWithAttachments(request, mimeBoundary, mimeEntities, out, protocolData);
MESSAGE_INFORMER.forwardMessage(request, protocolData);
if (context != null) {
context.setMessage(request);
}
}
}