org.apache.cxf.binding.soap.tcp.SoapTcpOutputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cxf-bundle-minimal Show documentation
Show all versions of cxf-bundle-minimal Show documentation
Apache CXF Minimal Bundle Jar
/**
* 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.binding.soap.tcp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.apache.cxf.binding.soap.Soap11;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.tcp.frames.SoapTcpFrame;
import org.apache.cxf.binding.soap.tcp.frames.SoapTcpFrameContentDescription;
import org.apache.cxf.binding.soap.tcp.frames.SoapTcpFrameHeader;
import org.apache.cxf.io.AbstractThresholdOutputStream;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.transport.MessageObserver;
/**
* SoapTCPOutPutStream is OutputStream for sending message in SOAP/TCP protocol.
* It sends single message in one or more SOAP/TCP frames.
*/
public class SoapTcpOutputStream extends AbstractThresholdOutputStream {
public static final int CHUNK_SIZE = 4096;
private int channelId;
private OutputStream outStream;
private InputStream inStream;
private boolean messageSent;
private Message outMessage;
private int chunkSize;
private MessageObserver incomingObserver;
public SoapTcpOutputStream(final InputStream inStream, final OutputStream outStream,
final Message message, final String targetWsURI,
final MessageObserver incomingObserver) {
this(inStream, outStream, message, targetWsURI, incomingObserver, CHUNK_SIZE);
}
public SoapTcpOutputStream(final InputStream inStream, final OutputStream outStream,
final Message message, final String targetWsURI,
final MessageObserver incomingObserver, final int chunkSize) {
super(chunkSize);
this.messageSent = false;
this.inStream = inStream;
this.outStream = outStream;
this.outMessage = message;
this.wrappedStream = null;
this.chunkSize = chunkSize;
this.incomingObserver = incomingObserver;
final List mimeTypes = new ArrayList();
SoapMessage m = (SoapMessage)message;
//mimeTypes.add("application/vnd.sun.stateful.fastinfoset");
mimeTypes.add(m.getVersion().getContentType());
//mimeTypes.add("multipart/related");
final List supportedParams = new ArrayList();
supportedParams.add("charset");
if (m.getVersion() == Soap11.getInstance()) {
supportedParams.add("SOAPAction");
} else {
supportedParams.add("action");
}
try {
channelId = openChannel(targetWsURI, mimeTypes, supportedParams);
} catch (IOException e) {
e.printStackTrace();
}
}
private int openChannel(final String targetWsURI, final List supportedMimeTypes,
final List supportedParams) throws IOException {
String openChannelMsg = ""
+ "";
openChannelMsg += "" + targetWsURI + " ";
for (String mimeType : supportedMimeTypes) {
openChannelMsg += "" + mimeType + " ";
}
for (String param : supportedParams) {
openChannelMsg += "" + param + " ";
}
openChannelMsg += " ";
SoapTcpFrameContentDescription contentDesc = new SoapTcpFrameContentDescription();
contentDesc.setContentId(0);
final Map parameters = new Hashtable();
parameters.put(0, "utf-8");
contentDesc.setParameters(parameters);
final SoapTcpFrameHeader header =
new SoapTcpFrameHeader(SoapTcpFrameHeader.SINGLE_FRAME_MESSAGE, contentDesc);
final SoapTcpFrame frame = new SoapTcpFrame();
frame.setHeader(header);
frame.setChannelId(0);
try {
frame.setPayload(openChannelMsg.getBytes("UTF-8"));
SoapTcpUtils.writeMessageFrame(outStream, frame);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
final SoapTcpFrame response = SoapTcpUtils.readMessageFrame(inStream);
if (!SoapTcpUtils.checkSingleFrameResponse(response, "openChannelResponse")) {
throw new IOException("Couldn't open new channel.");
}
//SoapTcpUtils.printSoapTcpFrame(System.out, response);
return getChannelIdFromResponse(response);
}
private int getChannelIdFromResponse(final SoapTcpFrame frame) {
return ChannelIdParser.getChannelId(new ByteArrayInputStream(frame.getPayload()));
}
@Override
public void thresholdNotReached() throws IOException {
//Send single message if didn't send any message yet or end message if already send message
if (messageSent) {
SoapTcpFrameHeader header = new SoapTcpFrameHeader(SoapTcpFrameHeader.MESSAGE_END_CHUNK, null);
header.setChannelId(channelId);
SoapTcpFrame frame = new SoapTcpFrame();
frame.setChannelId(channelId);
frame.setHeader(header);
frame.setPayload(this.buffer.toByteArray());
SoapTcpUtils.writeMessageFrame(outStream, frame);
} else {
final SoapTcpFrameContentDescription contentDesc = new SoapTcpFrameContentDescription();
contentDesc.setContentId(0);
final Map parameters = new Hashtable();
parameters.put(0, "utf-8");
contentDesc.setParameters(parameters);
final SoapTcpFrameHeader header =
new SoapTcpFrameHeader(SoapTcpFrameHeader.SINGLE_FRAME_MESSAGE, contentDesc);
header.setChannelId(channelId);
final SoapTcpFrame frame = new SoapTcpFrame();
frame.setHeader(header);
frame.setChannelId(channelId);
frame.setPayload(this.buffer.toByteArray());
SoapTcpUtils.writeMessageFrame(outStream, frame);
messageSent = true;
}
}
@Override
public void thresholdReached() throws IOException {
//Send start-chunk message if didn't send any message yet or message chunk if already send message
if (messageSent) {
SoapTcpFrameHeader header = new SoapTcpFrameHeader(SoapTcpFrameHeader.MESSAGE_CHUNK, null);
header.setChannelId(channelId);
SoapTcpFrame frame = new SoapTcpFrame();
frame.setChannelId(channelId);
frame.setHeader(header);
frame.setPayload(this.buffer.toByteArray());
SoapTcpUtils.writeMessageFrame(outStream, frame);
} else {
SoapTcpFrameContentDescription contentDesc = new SoapTcpFrameContentDescription();
contentDesc.setContentId(0);
Map parameters = new Hashtable();
parameters.put(0, "utf-8");
contentDesc.setParameters(parameters);
SoapTcpFrameHeader header =
new SoapTcpFrameHeader(SoapTcpFrameHeader.MESSAGE_START_CHUNK, contentDesc);
header.setChannelId(channelId);
SoapTcpFrame frame = new SoapTcpFrame();
frame.setHeader(header);
frame.setChannelId(channelId);
frame.setPayload(this.buffer.toByteArray());
SoapTcpUtils.writeMessageFrame(outStream, frame);
messageSent = true;
}
}
@Override
public void close() throws IOException {
super.close();
if (messageSent) {
InputStream inputStream = getResponse();
Exchange exchange = outMessage.getExchange();
Message inMessage = new MessageImpl();
inMessage.setExchange(exchange);
inMessage.setContent(InputStream.class, inputStream);
incomingObserver.onMessage(inMessage);
}
}
@Override
protected void onFirstWrite() throws IOException {
}
private InputStream getResponse() {
SoapTcpFrame responseMessage = null;
try {
responseMessage = SoapTcpUtils.readMessageFrame(inStream);
} catch (IOException e2) {
e2.printStackTrace();
}
if (responseMessage != null) {
int frameType = responseMessage.getHeader().getFrameType();
if (frameType == SoapTcpFrameHeader.SINGLE_FRAME_MESSAGE
|| frameType == SoapTcpFrameHeader.ERROR_MESSAGE
|| frameType == SoapTcpFrameHeader.NULL_MESSAGE) {
return new ByteArrayInputStream(responseMessage.getPayload());
} else if (frameType == SoapTcpFrameHeader.MESSAGE_START_CHUNK) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(4 * chunkSize);
try {
baos.write(responseMessage.getPayload());
} catch (IOException e1) {
e1.printStackTrace();
}
while (frameType != SoapTcpFrameHeader.MESSAGE_END_CHUNK) {
try {
SoapTcpFrame frame = SoapTcpUtils.readMessageFrame(inStream);
baos.write(frame.getPayload());
frameType = frame.getHeader().getFrameType();
} catch (IOException e) {
break;
}
}
return new ByteArrayInputStream(baos.toByteArray());
}
}
return null;
}
}