001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.binding.soap.saaj;
019:
020: import java.io.ByteArrayOutputStream;
021: import java.io.IOException;
022: import java.io.OutputStream;
023: import java.util.ResourceBundle;
024:
025: import javax.xml.soap.MessageFactory;
026: import javax.xml.soap.SOAPConstants;
027: import javax.xml.soap.SOAPException;
028: import javax.xml.soap.SOAPMessage;
029: import javax.xml.soap.SOAPPart;
030: import javax.xml.stream.XMLStreamException;
031: import javax.xml.stream.XMLStreamWriter;
032:
033: import org.apache.cxf.binding.soap.SoapFault;
034: import org.apache.cxf.binding.soap.SoapMessage;
035: import org.apache.cxf.binding.soap.SoapVersion;
036: import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
037: import org.apache.cxf.common.i18n.BundleUtils;
038: import org.apache.cxf.common.i18n.Message;
039: import org.apache.cxf.interceptor.Fault;
040: import org.apache.cxf.phase.Phase;
041: import org.apache.cxf.staxutils.StaxUtils;
042: import org.apache.cxf.staxutils.W3CDOMStreamWriter;
043:
044: /**
045: * Sets up the outgoing chain to build a SAAJ tree instead of writing
046: * directly to the output stream. First it will replace the XMLStreamWriter
047: * with one which writes to a SOAPMessage. Then it will add an interceptor
048: * at the end of the chain in the SEND phase which writes the resulting
049: * SOAPMessage.
050: */
051: public class SAAJOutInterceptor extends AbstractSoapInterceptor {
052: private static final ResourceBundle BUNDLE = BundleUtils
053: .getBundle(SAAJOutInterceptor.class);
054:
055: public SAAJOutInterceptor() {
056: super (Phase.PRE_PROTOCOL);
057: }
058:
059: public void handleMessage(SoapMessage message) throws Fault {
060: SOAPMessage saaj = message.getContent(SOAPMessage.class);
061: if (saaj == null) {
062: SoapVersion version = message.getVersion();
063: try {
064: MessageFactory factory = null;
065: if (version.getVersion() == 1.1) {
066: factory = MessageFactory.newInstance();
067: } else {
068: factory = MessageFactory
069: .newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
070: }
071: SOAPMessage soapMessage = factory.createMessage();
072:
073: SOAPPart soapPart = soapMessage.getSOAPPart();
074: W3CDOMStreamWriter writer = new W3CDOMStreamWriter(
075: soapPart);
076: // Replace stax writer with DomStreamWriter
077: message.setContent(XMLStreamWriter.class, writer);
078: message.setContent(SOAPMessage.class, soapMessage);
079: } catch (SOAPException e) {
080: throw new SoapFault(
081: new Message("SOAPEXCEPTION", BUNDLE), e,
082: version.getSender());
083: }
084: } else {
085: //as the SOAPMessage already has everything in place, we do not need XMLStreamWriter to write
086: //anything for us, so we just set XMLStreamWriter's output to a dummy output stream.
087: try {
088: XMLStreamWriter dummyWriter = StaxUtils
089: .getXMLOutputFactory().createXMLStreamWriter(
090: new ByteArrayOutputStream());
091: message.setContent(XMLStreamWriter.class, dummyWriter);
092: } catch (XMLStreamException e) {
093: // do nothing
094: }
095: }
096:
097: // Add a final interceptor to write the message
098: message.getInterceptorChain().add(
099: new SAAJOutEndingInterceptor());
100: }
101:
102: public class SAAJOutEndingInterceptor extends
103: AbstractSoapInterceptor {
104: public SAAJOutEndingInterceptor() {
105: super (SAAJOutEndingInterceptor.class.getName(),
106: Phase.PRE_PROTOCOL_ENDING);
107: }
108:
109: public void handleMessage(SoapMessage message) throws Fault {
110: SOAPMessage soapMessage = message
111: .getContent(SOAPMessage.class);
112:
113: if (soapMessage != null) {
114:
115: OutputStream os = message
116: .getContent(OutputStream.class);
117: try {
118: setMessageContent(message, soapMessage);
119: soapMessage.writeTo(os);
120: os.flush();
121: } catch (IOException e) {
122: throw new SoapFault(new Message("SOAPEXCEPTION",
123: BUNDLE), e, message.getVersion()
124: .getSender());
125: } catch (SOAPException e) {
126: throw new SoapFault(new Message("SOAPEXCEPTION",
127: BUNDLE), e, message.getVersion()
128: .getSender());
129: }
130: }
131: }
132:
133: private void setMessageContent(SoapMessage message,
134: SOAPMessage soapMessage) throws SOAPException {
135:
136: if (soapMessage.getAttachments().hasNext()) {
137: StringBuffer sb = new StringBuffer();
138: for (String str : soapMessage.getMimeHeaders()
139: .getHeader("Content-Type")) {
140: sb.append(str);
141: }
142: String contentType = sb.toString();
143: if (contentType != null && contentType.length() > 0) {
144: message
145: .put(
146: org.apache.cxf.message.Message.CONTENT_TYPE,
147: contentType);
148: }
149:
150: }
151:
152: }
153:
154: }
155: }
|