blob: 7c3c1492ffb40cd6130e8f21204ace34adb304d3 [file] [log] [blame]
/*
* Portions Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.xml.internal.ws.encoding.soap.server;
import com.sun.xml.internal.ws.handler.MessageContextUtil;
import com.sun.xml.internal.ws.model.JavaMethod;
import com.sun.xml.internal.ws.model.RuntimeModel;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.ws.soap.SOAPFaultException;
import javax.xml.ws.soap.SOAPBinding;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.Source;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamConstants;
import com.sun.xml.internal.ws.pept.ept.MessageInfo;
import com.sun.xml.internal.ws.encoding.soap.SOAPConstants;
import com.sun.xml.internal.ws.encoding.soap.SOAPDecoder;
import com.sun.xml.internal.ws.encoding.soap.internal.InternalMessage;
import com.sun.xml.internal.ws.encoding.soap.message.SOAPFaultInfo;
import com.sun.xml.internal.ws.handler.HandlerContext;
import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil;
import com.sun.xml.internal.ws.streaming.SourceReaderFactory;
import com.sun.xml.internal.ws.util.MessageInfoUtil;
import com.sun.xml.internal.ws.util.SOAPUtil;
import com.sun.xml.internal.ws.server.*;
import com.sun.xml.internal.ws.streaming.XMLStreamReaderException;
import javax.xml.stream.XMLStreamException;
import javax.xml.ws.handler.MessageContext;
/**
* @author WS Development Team
*/
public class SOAPXMLDecoder extends SOAPDecoder {
private static final Set<String> requiredRoles = new HashSet<String>();
private static final QName emptyBodyName = new QName("");
public SOAPXMLDecoder() {
requiredRoles.add("http://schemas.xmlsoap.org/soap/actor/next");
requiredRoles.add("");
}
/*
*
* @throws ServerRtException
* @see SOAPDecoder#toInternalMessage(SOAPMessage)
*/
public InternalMessage toInternalMessage(SOAPMessage soapMessage, MessageInfo messageInfo) {
// TODO handle exceptions, attachments
XMLStreamReader reader = null;
try {
InternalMessage request = new InternalMessage();
processAttachments(messageInfo, request, soapMessage);
Source source = soapMessage.getSOAPPart().getContent();
reader = SourceReaderFactory.createSourceReader(source, true,getSOAPMessageCharsetEncoding(soapMessage));
XMLStreamReaderUtil.nextElementContent(reader);
decodeEnvelope(reader, request, false, messageInfo);
return request;
} catch(Exception e) {
if (isBadXML(e)) {
RuntimeContext rtCtxt = MessageInfoUtil.getRuntimeContext(messageInfo);
HandlerContext handlerCtxt = rtCtxt.getHandlerContext();
raiseBadXMLFault(handlerCtxt);
}
throw new ServerRtException("soapdecoder.err", new Object[]{e});
} finally {
if (reader != null) {
XMLStreamReaderUtil.close(reader);
}
}
}
protected boolean isBadXML(Exception e) {
while (e != null) {
if (e instanceof XMLStreamException) {
return true;
}
e = (e.getCause() instanceof Exception) ? (Exception)e.getCause() : null;
}
return false;
}
/*
* Headers from SOAPMesssage are mapped to HeaderBlocks in InternalMessage
* Body from SOAPMessage is skipped
* BodyBlock in InternalMessage is converted to JAXBTypeInfo or RpcLitPayload
*
* @throws ServerRtException
* @see SOAPDecoder#toInternalMessage(SOAPMessage, InternalMessage)
*/
public InternalMessage toInternalMessage(SOAPMessage soapMessage,
InternalMessage request, MessageInfo messageInfo) {
// TODO handle exceptions, attachments
XMLStreamReader reader = null;
try {
processAttachments(messageInfo, request, soapMessage);
Source source = soapMessage.getSOAPPart().getContent();
reader = SourceReaderFactory.createSourceReader(source, true,getSOAPMessageCharsetEncoding(soapMessage));
XMLStreamReaderUtil.nextElementContent(reader);
decodeEnvelope(reader, request, true, messageInfo);
convertBodyBlock(request, messageInfo);
} catch(Exception e) {
if (isBadXML(e)) {
RuntimeContext rtCtxt = MessageInfoUtil.getRuntimeContext(messageInfo);
HandlerContext handlerCtxt = rtCtxt.getHandlerContext();
raiseBadXMLFault(handlerCtxt);
}
throw new ServerRtException("soapdecoder.err", new Object[]{e});
} finally {
if (reader != null) {
XMLStreamReaderUtil.close(reader);
}
}
return request;
}
@Override
public void decodeDispatchMethod(XMLStreamReader reader, InternalMessage request, MessageInfo messageInfo) {
// Operation's QName. takes care of <body/>
QName name = (reader.getEventType() == XMLStreamConstants.START_ELEMENT) ? reader.getName() : emptyBodyName;
RuntimeContext rtCtxt = MessageInfoUtil.getRuntimeContext(messageInfo);
RuntimeModel rtModel = rtCtxt.getModel();
JavaMethod javaMethod = rtModel.getJavaMethod(name);
Method method = (javaMethod == null) ? null : javaMethod.getMethod();
if (method == null) {
raiseFault(getSenderFaultCode(), "Cannot find the dispatch method");
}
MessageContext msgCtxt = MessageInfoUtil.getMessageContext(messageInfo);
if (msgCtxt != null) {
String opNsUri = rtModel.getPortTypeName().getNamespaceURI();
String opName = javaMethod.getOperationName();
MessageContextUtil.setWsdlOperation(msgCtxt, new QName(opNsUri, opName));
}
messageInfo.setMethod(method);
}
protected SOAPFaultInfo decodeFault(XMLStreamReader reader, InternalMessage internalMessage,
MessageInfo messageInfo) {
raiseFault(getSenderFaultCode(), "Server cannot handle fault message");
return null;
}
@Override
protected void raiseBadXMLFault(HandlerContext ctxt) {
MessageContextUtil.setHttpStatusCode(ctxt.getMessageContext(), 400);
raiseFault(getSenderFaultCode(), "Bad request");
}
public Set<String> getRequiredRoles() {
return requiredRoles;
}
@Override
public String getBindingId() {
return SOAPBinding.SOAP11HTTP_BINDING;
}
@Override
protected QName getSenderFaultCode() {
return SOAPConstants.FAULT_CODE_CLIENT;
}
@Override
protected QName getReceiverFaultCode() {
return SOAPConstants.FAULT_CODE_SERVER;
}
@Override
protected QName getVersionMismatchFaultCode() {
return SOAPConstants.FAULT_CODE_VERSION_MISMATCH;
}
}