/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed 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.axis.message; import org.apache.axis.Constants; import org.apache.axis.encoding.DeserializationContext; import org.apache.axis.soap.SOAPConstants; import org.apache.axis.utils.Messages; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.apache.axis.AxisFault; import org.apache.axis.MessageContext; import javax.xml.namespace.QName; import javax.xml.soap.SOAPException; /** * The EnvelopeBuilder is responsible for parsing the top-level * SOAP envelope stuff (Envelope, Body, Header), and spawning off * HeaderBuilder and BodyBuilders. * * @author Glen Daniels (gdaniels@allaire.com) * @author Andras Avar (andras.avar@nokia.com) */ public class EnvelopeBuilder extends SOAPHandler { private SOAPEnvelope envelope; private SOAPConstants soapConstants = SOAPConstants.SOAP11_CONSTANTS; private boolean gotHeader = false; private boolean gotBody = false; public EnvelopeBuilder(String messageType, SOAPConstants soapConstants) { envelope = new SOAPEnvelope(false, soapConstants); envelope.setMessageType(messageType); myElement = envelope; } public EnvelopeBuilder(SOAPEnvelope env, String messageType) { envelope = env ; envelope.setMessageType(messageType); myElement = envelope; } public SOAPEnvelope getEnvelope() { return envelope; } public void startElement(String namespace, String localName, String prefix, Attributes attributes, DeserializationContext context) throws SAXException { if (!localName.equals(Constants.ELEM_ENVELOPE)) throw new SAXException( Messages.getMessage("badTag00", localName)); // See if we're only supporting a single SOAP version at this endpoint MessageContext msgContext = context.getMessageContext(); SOAPConstants singleVersion = null; if (msgContext != null) { singleVersion = (SOAPConstants)msgContext.getProperty( Constants.MC_SINGLE_SOAP_VERSION); } if (namespace.equals(Constants.URI_SOAP11_ENV)) { // SOAP 1.1 soapConstants = SOAPConstants.SOAP11_CONSTANTS; } else if (namespace.equals(Constants.URI_SOAP12_ENV)) { // SOAP 1.2 soapConstants = SOAPConstants.SOAP12_CONSTANTS; } else { soapConstants = null; } if ((soapConstants == null) || (singleVersion != null && soapConstants != singleVersion)) { // Mismatch of some sort, either an unknown namespace or not // the one we want. Send back an appropriate fault. // Right now we only send back SOAP 1.1 faults for this case. Do // we want to send SOAP 1.2 faults back to SOAP 1.2 endpoints? soapConstants = SOAPConstants.SOAP11_CONSTANTS; if (singleVersion == null) singleVersion = soapConstants; try { AxisFault fault = new AxisFault(soapConstants.getVerMismatchFaultCodeQName(), null, Messages.getMessage("versionMissmatch00"), null, null, null); SOAPHeaderElement newHeader = new SOAPHeaderElement(soapConstants.getEnvelopeURI(), Constants.ELEM_UPGRADE); // TODO: insert soap 1.1 upgrade header in case of soap 1.2 response if // axis supports both simultaneously MessageElement innerHeader = new MessageElement(soapConstants.getEnvelopeURI(), Constants.ELEM_SUPPORTEDENVELOPE); innerHeader.addAttribute(null, Constants.ATTR_QNAME, new QName(singleVersion.getEnvelopeURI(), Constants.ELEM_ENVELOPE)); newHeader.addChildElement(innerHeader); fault.addHeader(newHeader); throw new SAXException(fault); } catch (javax.xml.soap.SOAPException e) { throw new SAXException(e); } } // Indicate what version of SOAP we're using to anyone else involved // in processing this message. if(context.getMessageContext() != null) context.getMessageContext().setSOAPConstants(soapConstants); if (soapConstants == SOAPConstants.SOAP12_CONSTANTS && attributes.getValue(Constants.URI_SOAP12_ENV, Constants.ATTR_ENCODING_STYLE) != null) { AxisFault fault = new AxisFault(Constants.FAULT_SOAP12_SENDER, null, Messages.getMessage("noEncodingStyleAttrAppear", "Envelope"), null, null, null); throw new SAXException(fault); } envelope.setPrefix(prefix); envelope.setNamespaceURI(namespace); envelope.setNSMappings(context.getCurrentNSMappings()); envelope.setSoapConstants(soapConstants); context.pushNewElement(envelope); } public SOAPHandler onStartChild(String namespace, String localName, String prefix, Attributes attributes, DeserializationContext context) throws SAXException { QName thisQName = new QName(namespace, localName); if (thisQName.equals(soapConstants.getHeaderQName())) { if (gotHeader) throw new SAXException(Messages.getMessage("only1Header00")); gotHeader = true; return new HeaderBuilder(envelope); } if (thisQName.equals(soapConstants.getBodyQName())) { if (gotBody) throw new SAXException(Messages.getMessage("only1Body00")); gotBody = true; return new BodyBuilder(envelope); } if (!gotBody) throw new SAXException(Messages.getMessage("noCustomElems00")); if (soapConstants == SOAPConstants.SOAP12_CONSTANTS) { throw new SAXException(Messages.getMessage("noElemAfterBody12")); } try { MessageElement element = new MessageElement(namespace, localName, prefix, attributes, context); if (element.getFixupDeserializer() != null) return (SOAPHandler)element.getFixupDeserializer(); } catch (AxisFault axisFault) { throw new SAXException(axisFault); } return null; } public void onEndChild(String namespace, String localName, DeserializationContext context) { } public void endElement(String namespace, String localName, DeserializationContext context) throws SAXException { // Envelope isn't dirty yet by default... envelope.setDirty(false); envelope.setRecorded(true); envelope.reset(); } }