📄 boundarydelimitedstream.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;/** * This class takes the input stream and turns it multiple streams. * * @author Rick Rineholt */public class BoundaryDelimitedStream extends java.io.FilterInputStream { /** The <code>Log</code> that this class should log all events to. */ protected static Log log = LogFactory.getLog(BoundaryDelimitedStream.class.getName()); protected byte[] boundary = null; /** The boundary length. */ int boundaryLen = 0; /** The boundary length plus crlf. */ int boundaryBufLen = 0; /** The source input stream. */ java.io.InputStream is = null; /** The stream has been closed. */ boolean closed = true; /** eof has been detected. */ boolean eos = false; /** There are no more streams left. */ boolean theEnd = false; /** Minimum to read at one time. */ int readbufsz = 0; /** The buffer we are reading. */ byte[] readbuf = null; /** Where we have read so far in the stream. */ int readBufPos = 0; /** The number of bytes in array. */ int readBufEnd = 0; /** Field BOUNDARY_NOT_FOUND. */ protected static final int BOUNDARY_NOT_FOUND = Integer.MAX_VALUE; // Where in the stream a boundary is located. /** Field boundaryPos. */ int boundaryPos = BOUNDARY_NOT_FOUND; /** The number of streams produced. */ static int streamCount = 0; /** * Signal that a new stream has been created. * * @return */ protected static synchronized int newStreamNo() { log.debug(Messages.getMessage("streamNo", "" + (streamCount + 1))); return ++streamCount; } /** Field streamNo. */ protected int streamNo = -1; // Keeps track of stream /** Field isDebugEnabled. */ static boolean isDebugEnabled = false; /** * Gets the next stream. From the previous using the same buffer size to * read. * * @return the boundary delmited stream, null if there are no more streams. * @throws java.io.IOException if there was an error loading the data for * the next stream */ public synchronized BoundaryDelimitedStream getNextStream() throws java.io.IOException { return getNextStream(readbufsz); } /** * Gets the next stream. From the previous using new buffer reading size. * * @param readbufsz * @return the boundary delmited stream, null if there are no more streams. * @throws java.io.IOException if there was an error loading the data for * the next stream */ protected synchronized BoundaryDelimitedStream getNextStream( int readbufsz) throws java.io.IOException { BoundaryDelimitedStream ret = null; if (!theEnd) { // Create an new boundary stream that comes after this one. ret = new BoundaryDelimitedStream(this, readbufsz); } return ret; } /** * Constructor to create the next stream from the previous one. * * @param prev the previous stream * @param readbufsz how many bytes to make the read buffer * @throws java.io.IOException if there was a problem reading data from * <code>prev</code> */ protected BoundaryDelimitedStream(BoundaryDelimitedStream prev, int readbufsz) throws java.io.IOException { super(null); streamNo = newStreamNo(); boundary = prev.boundary; boundaryLen = prev.boundaryLen; boundaryBufLen = prev.boundaryBufLen; skip = prev.skip; is = prev.is; closed = false; // The new one is not closed. eos = false; // Its not at th EOS. readbufsz = prev.readbufsz; readbuf = prev.readbuf; // Move past the old boundary. readBufPos = prev.readBufPos + boundaryBufLen; readBufEnd = prev.readBufEnd; // find the new boundary. boundaryPos = boundaryPosition(readbuf, readBufPos, readBufEnd); prev.theEnd = theEnd; // The stream. } /** * Create a new boundary stream. * * @param is * @param boundary is the boundary that separates the individual streams. * @param readbufsz lets you have some control over the amount of buffering. * by buffering you can some effiency in searching. * * @throws org.apache.axis.AxisFault */ BoundaryDelimitedStream( java.io.InputStream is, byte[] boundary, int readbufsz) throws org.apache.axis.AxisFault { // super (is); 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; // Copy the boundary array to make certain it is never altered. this.boundary = new byte[boundary.length]; System.arraycopy(boundary, 0, this.boundary, 0, boundary.length); this.boundaryLen = this.boundary.length; this.boundaryBufLen = boundaryLen + 2; // allways leave room for at least a 2x boundary // Most mime boundaries are 40 bytes or so. this.readbufsz = Math.max((boundaryBufLen) * 2, readbufsz); } private final int readFromStream(final byte[] b) throws java.io.IOException { return readFromStream(b, 0, b.length); } private final int readFromStream( final byte[] b, final int start, final int length) throws java.io.IOException { int minRead = Math.max(boundaryBufLen * 2, length); minRead = Math.min(minRead, length - start); int br = 0; int brTotal = 0; do { br = is.read(b, brTotal + start, length - brTotal); if (br > 0) { brTotal += br; } } while ((br > -1) && (brTotal < minRead)); return (brTotal != 0) ? brTotal : br; } /** * Read from the boundary delimited stream. * @param b is the array to read into. * @param off is the offset * @param len * @return the number of bytes read. -1 if endof stream. * * @throws java.io.IOException */ public synchronized int read(byte[] b, final int off, final int len) throws java.io.IOException { if (closed) { throw new java.io.IOException(Messages.getMessage("streamClosed")); } if (eos) { return -1; } if (readbuf == null) { // Allocate the buffer. readbuf = new byte[Math.max(len, readbufsz)]; readBufEnd = readFromStream(readbuf); if (readBufEnd < 0) { readbuf = null; closed = true; finalClose(); throw new java.io.IOException( Messages.getMessage("eosBeforeMarker")); } readBufPos = 0; // Finds the boundary pos. boundaryPos = boundaryPosition(readbuf, 0, readBufEnd); } int bwritten = 0; // Number of bytes written. // read and copy bytes in. do { // Always allow to have a boundary length left in the buffer. int bcopy = Math.min(readBufEnd - readBufPos - boundaryBufLen, len - bwritten); // never go past the boundary. bcopy = Math.min(bcopy, boundaryPos - readBufPos); if (bcopy > 0) { System.arraycopy(readbuf, readBufPos, b, off + bwritten, bcopy); bwritten += bcopy; readBufPos += bcopy; } if (readBufPos == boundaryPos) { eos = true; // hit the boundary so it the end of the stream. log.debug(Messages.getMessage("atEOS", "" + streamNo));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -