org.apache.cxf.jaxws.interceptors.MessageModeInInterceptor Maven / Gradle / Ivy
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.cxf.jaxws.interceptors;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Iterator;
import java.util.List;
import javax.activation.DataSource;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
import org.apache.cxf.attachment.AttachmentUtil;
import org.apache.cxf.helpers.LoadingByteArrayOutputStream;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Attachment;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageContentsList;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.staxutils.StaxSource;
import org.apache.cxf.staxutils.StaxUtils;
import org.apache.cxf.staxutils.W3CDOMStreamReader;
public class MessageModeInInterceptor extends AbstractPhaseInterceptor {
Class type;
QName bindingName;
Class soapMsgClass;
public MessageModeInInterceptor(Class c, QName bName) {
super(Phase.POST_LOGICAL);
bindingName = bName;
type = c;
try {
soapMsgClass = Class.forName("javax.xml.soap.SOAPMessage");
} catch (Throwable t) {
soapMsgClass = null;
}
}
public void handleMessage(Message message) throws Fault {
BindingOperationInfo bop = message.getExchange().get(BindingOperationInfo.class);
if (bop == null || !bindingName.equals(bop.getBinding().getName())) {
return;
}
Object o = message.getContent(soapMsgClass);
if (o != null) {
doFromSoapMessage(message, o);
} else if (DataSource.class.isAssignableFrom(type)) {
doDataSource(message);
}
}
private void doDataSource(final Message message) {
MessageContentsList list = (MessageContentsList)message.getContent(List.class);
//reconstitute all the parts into a Mime data source
if (message.getAttachments() != null && !message.getAttachments().isEmpty()
&& list != null
&& !list.isEmpty() && list.get(0) instanceof DataSource) {
list.set(0, new MultiPartDataSource(message, (DataSource)list.get(0)));
}
}
private void doFromSoapMessage(Message message, Object sm) {
SOAPMessage m = (SOAPMessage)sm;
MessageContentsList list = (MessageContentsList)message.getContent(List.class);
if (list == null) {
list = new MessageContentsList();
message.setContent(List.class, list);
}
Object o = m;
if (StreamSource.class.isAssignableFrom(type)) {
try {
CachedOutputStream out = new CachedOutputStream();
try {
XMLStreamWriter xsw = StaxUtils.createXMLStreamWriter(out);
StaxUtils.copy(new DOMSource(m.getSOAPPart()), xsw);
xsw.close();
o = new StreamSource(out.getInputStream());
} finally {
out.close();
}
} catch (Exception e) {
throw new Fault(e);
}
} else if (SAXSource.class.isAssignableFrom(type)) {
o = new StaxSource(new W3CDOMStreamReader(m.getSOAPPart()));
} else if (Source.class.isAssignableFrom(type)) {
o = new DOMSource(m.getSOAPPart());
}
list.set(0, o);
}
private static class MultiPartDataSource implements DataSource {
final Iterator atts;
final String contentType;
final String boundary;
final String start;
final LoadingByteArrayOutputStream bout = new LoadingByteArrayOutputStream();
Writer writer;
DataSource rootPart;
InputStream current;
boolean writingHeaders;
Attachment att;
public MultiPartDataSource(Message message, DataSource root) {
atts = message.getAttachments().iterator();
String s = (String)message.get(Message.CONTENT_TYPE);
boundary = findBoundary(s);
start = findStart(s);
if (!s.contains(boundary)) {
s += "; boundary=\"" + boundary + "\"";
}
contentType = s;
rootPart = root;
try {
writer = new OutputStreamWriter(bout, "ASCII");
writer.append("Content-Type: ").append(contentType).append("\r\n\r\n");
writer.flush();
current = bout.createInputStream();
} catch (Exception e) {
//nothing
}
}
public String getContentType() {
return contentType;
}
public InputStream getInputStream() throws IOException {
return new InputStream() {
public int read() throws IOException {
int i = current.read();
if (i == -1) {
nextCurrent();
i = current.read();
}
return i;
}
};
}
private void nextCurrent() throws IOException {
if (rootPart != null) {
if (writingHeaders) {
writingHeaders = false;
current = rootPart.getInputStream();
rootPart = null;
} else {
writingHeaders = true;
bout.reset();
writer.append("--").append(boundary).append("\r\n");
writer.append("Content-Type: ").append(rootPart.getContentType()).append("\r\n");
writer.append("Content-ID: <").append(start).append(">\r\n\r\n");
writer.flush();
current = bout.createInputStream();
}
} else {
if (writingHeaders) {
writingHeaders = false;
current = att.getDataHandler().getInputStream();
} else if (atts.hasNext()) {
att = atts.next();
writingHeaders = true;
bout.reset();
writer.append("\r\n");
writer.append("--").append(boundary).append("\r\n");
Iterator heads = att.getHeaderNames();
while (heads.hasNext()) {
String s = heads.next();
writer.append(s).append(": ").append(att.getHeader(s)).append("\r\n");
}
writer.append("\r\n");
writer.flush();
current = bout.createInputStream();
}
}
}
public String getName() {
return null;
}
public OutputStream getOutputStream() throws IOException {
return null;
}
private String findStart(String ct) {
int idx = ct.indexOf("start=");
if (idx == -1) {
return "root";
}
ct = ct.substring(idx + 6);
if (ct.charAt(0) == '"') {
ct = ct.substring(1);
idx = ct.indexOf('"');
return ct.substring(0, idx);
}
idx = ct.indexOf(';');
if (idx == -1) {
return ct;
}
return ct.substring(0, idx);
}
private String findBoundary(String ct) {
int idx = ct.indexOf("boundary=");
if (idx == -1) {
return AttachmentUtil.getUniqueBoundaryValue();
}
ct = ct.substring(idx + 9);
if (ct.charAt(0) == '"') {
ct = ct.substring(1);
idx = ct.indexOf('"');
return ct.substring(0, idx);
}
idx = ct.indexOf(';');
if (idx == -1) {
return ct;
}
return ct.substring(0, idx);
}
}
}