📄 dimedelimitedinputstream.java
字号:
/* * 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.attachments;import org.apache.axis.components.logger.LogFactory;import org.apache.axis.utils.Messages;import org.apache.commons.logging.Log;import java.io.IOException;/** * This class takes the input stream and turns it multiple streams. DIME version 0 format <pre> 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ --- | VERSION |B|E|C| TYPE_T| OPT_T | OPTIONS_LENGTH | A +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ID_LENGTH | TYPE_LENGTH | Always present 12 bytes +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ even on chunked data. | DATA_LENGTH | V +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ --- | / / OPTIONS + PADDING / / (absent for version 0) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | / / ID + PADDING / / | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | / / TYPE + PADDING / / | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | / / DATA + PADDING / / | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</pre> * This implementation of input stream does not support marking operations. * * @author Rick Rineholt */public class DimeDelimitedInputStream extends java.io.FilterInputStream { protected static Log log = LogFactory.getLog(DimeDelimitedInputStream.class.getName()); java.io.InputStream is = null; //The source input stream. volatile boolean closed = true; //The stream has been closed. boolean theEnd = false; //There are no more streams left. boolean moreChunks = false; //More chunks are a coming! boolean MB = false; //First part of the stream. MUST be SOAP. boolean ME = false; //Last part of stream. DimeTypeNameFormat tnf = null; String type = null; String id = null; long recordLength = 0L; //length of the record. long bytesRead = 0; //How many bytes of the record have been read. int dataPadLength = 0; //How many pad bytes there are. private static byte[] trash = new byte[4]; protected int streamNo = 0; protected IOException streamInError = null; protected static int streamCount = 0; //number of streams produced. protected static synchronized int newStreamNo() { log.debug(Messages.getMessage("streamNo", "" + (streamCount + 1))); return ++streamCount; } static boolean isDebugEnabled = false; /** * Gets the next stream. From the previous using new buffer reading size. * * @return the dime delmited stream, null if there are no more streams * @throws IOException if there was an error loading the data for the next * stream */ synchronized DimeDelimitedInputStream getNextStream() throws IOException { if (null != streamInError) throw streamInError; if (theEnd) return null; if (bytesRead < recordLength || moreChunks) //Stream must be read in succession throw new RuntimeException(Messages.getMessage( "attach.dimeReadFullyError")); dataPadLength -= readPad(dataPadLength); //Create an new dime stream that comes after this one. return new DimeDelimitedInputStream(this.is); } /** * Create a new dime stream. * * @param is the <code>InputStream</code> to wrap * @throws IOException if anything goes wrong */ DimeDelimitedInputStream(java.io.InputStream is) throws IOException { super(null); //we handle everything so this is not necessary, don't won't to hang on to a reference. isDebugEnabled = log.isDebugEnabled(); streamNo = newStreamNo(); closed = false; this.is = is; readHeader(false); } private final int readPad(final int size) throws IOException { if (0 == size) return 0; int read = readFromStream(trash, 0, size); if (size != read) { streamInError = new IOException(Messages.getMessage( "attach.dimeNotPaddedCorrectly")); throw streamInError; } return read; } private final int readFromStream(final byte[] b) throws IOException { return readFromStream(b, 0, b.length); } private final int readFromStream(final byte[] b, final int start, final int length) throws IOException { if (length == 0) return 0; int br = 0; int brTotal = 0; do { try { br = is.read(b, brTotal + start, length - brTotal); } catch (IOException e) { streamInError = e; throw e; } if (br > 0) brTotal += br; } while (br > -1 && brTotal < length); return br > -1 ? brTotal : br; } /** * Get the id for this stream part. * @return the id; */ public String getContentId() { return id; } public DimeTypeNameFormat getDimeTypeNameFormat() { return tnf; } /** * Get the type, as read from the header. * * @return the type of this dime */ public String getType() { return type; } /** * Read from the DIME stream. * * @param b is the array to read into. * @param off is the offset * @return the number of bytes read. -1 if endof stream * @throws IOException if data could not be read from the stream */ public synchronized int read(byte[] b, final int off, final int len) throws IOException { if (closed) { dataPadLength -= readPad(dataPadLength); throw new IOException(Messages.getMessage("streamClosed")); } return _read(b, off, len); } protected int _read(byte[] b, final int off, final int len) throws IOException { if (len < 0) throw new IllegalArgumentException (Messages.getMessage("attach.readLengthError", "" + len)); if (off < 0) throw new IllegalArgumentException (Messages.getMessage("attach.readOffsetError", "" + off)); if (b == null) throw new IllegalArgumentException (Messages.getMessage("attach.readArrayNullError")); if (b.length < off + len) throw new IllegalArgumentException (Messages.getMessage("attach.readArraySizeError", "" + b.length, "" + len, "" + off)); if (null != streamInError) throw streamInError; if (0 == len) return 0; //quick. if(recordLength == 0 && bytesRead == 0 && !moreChunks){ ++bytesRead; //odd case no data to read -- give back 0 next time -1; if(ME){ finalClose(); } return 0; } if (bytesRead >= recordLength && !moreChunks) { dataPadLength -= readPad(dataPadLength); if(ME){ finalClose(); } return -1; } int totalbytesread = 0; int bytes2read = 0; do { if (bytesRead >= recordLength && moreChunks) readHeader(true); bytes2read = (int) Math.min(recordLength - bytesRead, (long) len - totalbytesread); bytes2read = (int) Math.min(recordLength - bytesRead, (long) len - totalbytesread); try { bytes2read = is.read(b, off + totalbytesread, bytes2read); } catch (IOException e) { streamInError = e; throw e; } if (0 < bytes2read) { totalbytesread += bytes2read; bytesRead += bytes2read; } } while (bytes2read > -1 && totalbytesread < len && (bytesRead < recordLength || moreChunks)); if (0 > bytes2read) { if (moreChunks) { streamInError = new IOException(Messages.getMessage( "attach.DimeStreamError0")); throw streamInError; } if (bytesRead < recordLength) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -