org.apache.struts.upload
Class MultipartBoundaryInputStream

java.lang.Object
  |
  +--java.io.InputStream
        |
        +--org.apache.struts.upload.MultipartBoundaryInputStream

public class MultipartBoundaryInputStream
extends java.io.InputStream

This class encapsulates parsing functionality for RFC1867, multipart/form-data. See MultipartBoundaryInputStreamTest and MultipartIterator for usage examples.

Author:
Mike Schachter

Field Summary
protected  java.lang.String boundary
          The boundary.
private  byte[] boundaryBytes
           
protected  boolean boundaryEncountered
          Whether or not the boundary has been encountered.
protected  long bytesRead
          The total number of bytes read so far.
private static byte CARRIAGE_RETURN
           
private static java.lang.String CONTENT_TYPE_APPLICATION_OCTET_STREAM
           
private static java.lang.String CONTENT_TYPE_TEXT_PLAIN
           
private static byte[] CRLF
           
private static java.lang.String DEFAULT_CONTENT_DISPOSITION
           
private static int DEFAULT_LINE_SIZE
           
private static java.lang.String DOUBLE_DASH_STRING
           
protected  java.lang.String elementCharset
          The character encoding of the element, specified in the element's Content-Type header.
protected  java.lang.String elementContentDisposition
          The Content-Disposition for the current form element being read.
protected  java.lang.String elementContentType
          The Content-Type of the current form element being read.
protected  java.lang.String elementFileName
          The filename of the current form element being read, null if the current form element is text data.
protected  java.lang.String elementName
          The name of the current form element being read.
protected  boolean endOfStream
          Whether or not the end of the stream has been read.
private  byte[] finalBoundaryBytes
           
protected  boolean finalBoundaryEncountered
          Whether or not the final boundary has been encountered.
protected  java.io.InputStream inputStream
          The InputStream to read from.
private  byte[] line
           
private  boolean lineHasCarriage
           
private  boolean lineHasNewline
           
private  int lineIndex
           
private  int lineLength
           
private  int lineSize
           
protected  long maxLength
          The maximum length in bytes to read from the stream at a time, or -1 for unlimited length.
protected  boolean maxLengthMet
          Whether or not the maximum length has been met.
private static java.lang.String MESSAGE_INVALID_START
           
private static byte NEWLINE_BYTE
           
private static java.lang.String PARAMETER_CHARSET
           
private static java.lang.String PARAMETER_FILENAME
           
private static java.lang.String PARAMETER_NAME
           
private static char TOKEN_COLON
           
private static java.lang.String TOKEN_EQUALS
           
private static char TOKEN_QUOTE
           
private static char TOKEN_SEMI_COLON
           
private static char TOKEN_SPACE
           
 
Fields inherited from class java.io.InputStream
 
Constructor Summary
MultipartBoundaryInputStream()
           
 
Method Summary
private  int availableInLine()
           
private  void byteRead()
           
private  java.lang.String checkAndFixFilename(java.lang.String filename)
           
private  void checkForBoundary()
           
private  boolean equals(byte[] comp, int offset, int length, byte[] source)
          Checks bytes for equality.
private  void fillLine()
           
private  void fillLineBuffer()
           
 long getBytesRead()
           
 java.lang.String getElementCharset()
          Gets the character encoding of the current element.
 java.lang.String getElementContentDisposition()
          Gets the value for the "Content-Dispositio" header for the current multipart element.
 java.lang.String getElementContentType()
          Gets the "Content-Type" of the current element.
 java.lang.String getElementFileName()
          Gets the filename of the current element, which will be null if the current element isn't a file.
 java.lang.String getElementName()
          Gets the name of the current element.
 long getMaxLength()
           
 boolean isBoundaryEncountered()
          Returns whether or not the boundary has been encountered while reading data.
 boolean isElementFile()
          Gets whether or not the current form element being read is a file.
 boolean isEndOfStream()
          Whether or not an EOF has been read on the stream.
 boolean isFinalBoundaryEncountered()
          Returns whether or not the final boundary has been encountered.
 boolean isMaxLengthMet()
          Whether or not the maximum length has been met.
 void mark(int i)
          Marks the underlying stream.
private  java.lang.String parseForParameter(java.lang.String parameter, java.lang.String parseString)
           
private  java.lang.String parseHeaderValue(java.lang.String headerLine)
           
 int read()
          Reads from the stream.
 int read(byte[] buffer)
           
 int read(byte[] buffer, int offset, int length)
           
private  void readContentDisposition()
           
private  boolean readContentType()
           
private  void readElementHeaders()
           
private  void readFirstElement()
           
private  int readFromLine()
           
private  java.lang.String readLine()
           
 void reset()
          Resets the underlying input stream.
private  void resetCrlf()
           
 void resetForNextBoundary()
          Resets this stream for use with the next element, to be used after a boundary is encountered.
private  void resetLine()
           
private  void resetStream()
           
 void setBoundary(java.lang.String boundary)
          Sets the boundary that terminates the data for the stream, after adding the prefix "--"
 void setInputStream(java.io.InputStream stream)
          Sets the input stream used to read multipart data.
 void setLineSize(int size)
           
 void setMaxLength(long maxLength)
          Set the maximum length in bytes to read, or -1 for an unlimited length.
private  void skipCurrentLineIfBlank()
           
 
Methods inherited from class java.io.InputStream
available, close, markSupported, skip
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

NEWLINE_BYTE

private static final byte NEWLINE_BYTE
See Also:
Constant Field Values

CARRIAGE_RETURN

private static final byte CARRIAGE_RETURN
See Also:
Constant Field Values

CRLF

private static final byte[] CRLF

DOUBLE_DASH_STRING

private static final java.lang.String DOUBLE_DASH_STRING
See Also:
Constant Field Values

DEFAULT_LINE_SIZE

private static final int DEFAULT_LINE_SIZE
See Also:
Constant Field Values

TOKEN_EQUALS

private static final java.lang.String TOKEN_EQUALS
See Also:
Constant Field Values

TOKEN_QUOTE

private static final char TOKEN_QUOTE
See Also:
Constant Field Values

TOKEN_COLON

private static final char TOKEN_COLON
See Also:
Constant Field Values

TOKEN_SEMI_COLON

private static final char TOKEN_SEMI_COLON
See Also:
Constant Field Values

TOKEN_SPACE

private static final char TOKEN_SPACE
See Also:
Constant Field Values

DEFAULT_CONTENT_DISPOSITION

private static final java.lang.String DEFAULT_CONTENT_DISPOSITION
See Also:
Constant Field Values

PARAMETER_NAME

private static final java.lang.String PARAMETER_NAME
See Also:
Constant Field Values

PARAMETER_FILENAME

private static final java.lang.String PARAMETER_FILENAME
See Also:
Constant Field Values

PARAMETER_CHARSET

private static final java.lang.String PARAMETER_CHARSET
See Also:
Constant Field Values

CONTENT_TYPE_TEXT_PLAIN

private static final java.lang.String CONTENT_TYPE_TEXT_PLAIN
See Also:
Constant Field Values

CONTENT_TYPE_APPLICATION_OCTET_STREAM

private static final java.lang.String CONTENT_TYPE_APPLICATION_OCTET_STREAM
See Also:
Constant Field Values

MESSAGE_INVALID_START

private static final java.lang.String MESSAGE_INVALID_START
See Also:
Constant Field Values

inputStream

protected java.io.InputStream inputStream
The InputStream to read from.


boundary

protected java.lang.String boundary
The boundary.


boundaryEncountered

protected boolean boundaryEncountered
Whether or not the boundary has been encountered.


finalBoundaryEncountered

protected boolean finalBoundaryEncountered
Whether or not the final boundary has been encountered.


endOfStream

protected boolean endOfStream
Whether or not the end of the stream has been read.


elementContentDisposition

protected java.lang.String elementContentDisposition
The Content-Disposition for the current form element being read.


elementName

protected java.lang.String elementName
The name of the current form element being read.


elementContentType

protected java.lang.String elementContentType
The Content-Type of the current form element being read.


elementFileName

protected java.lang.String elementFileName
The filename of the current form element being read, null if the current form element is text data.


elementCharset

protected java.lang.String elementCharset
The character encoding of the element, specified in the element's Content-Type header.


maxLength

protected long maxLength
The maximum length in bytes to read from the stream at a time, or -1 for unlimited length.


maxLengthMet

protected boolean maxLengthMet
Whether or not the maximum length has been met.


bytesRead

protected long bytesRead
The total number of bytes read so far.


boundaryBytes

private byte[] boundaryBytes

finalBoundaryBytes

private byte[] finalBoundaryBytes

line

private byte[] line

lineSize

private int lineSize

lineLength

private int lineLength

lineHasNewline

private boolean lineHasNewline

lineHasCarriage

private boolean lineHasCarriage

lineIndex

private int lineIndex
Constructor Detail

MultipartBoundaryInputStream

public MultipartBoundaryInputStream()
Method Detail

setBoundary

public void setBoundary(java.lang.String boundary)
Sets the boundary that terminates the data for the stream, after adding the prefix "--"


resetForNextBoundary

public void resetForNextBoundary()
                          throws java.io.IOException
Resets this stream for use with the next element, to be used after a boundary is encountered.

java.io.IOException

setInputStream

public void setInputStream(java.io.InputStream stream)
                    throws java.io.IOException
Sets the input stream used to read multipart data. For efficiency purposes, make sure that the stream you set on this class is buffered. The way this class reads lines is that it continually calls the read() method until it reaches a newline character. That would be terrible if you were to set a socket's input stream here, but not as bad on a buffered stream.

java.io.IOException

read

public int read()
         throws java.io.IOException
Reads from the stream. Returns -1 if it's the end of the stream or if a boundary is encountered.

Specified by:
read in class java.io.InputStream
java.io.IOException

read

public int read(byte[] buffer)
         throws java.io.IOException
Overrides:
read in class java.io.InputStream
java.io.IOException

read

public int read(byte[] buffer,
                int offset,
                int length)
         throws java.io.IOException
Overrides:
read in class java.io.InputStream
java.io.IOException

mark

public void mark(int i)
Marks the underlying stream.

Overrides:
mark in class java.io.InputStream

reset

public void reset()
           throws java.io.IOException
Resets the underlying input stream.

Overrides:
reset in class java.io.InputStream
java.io.IOException

setMaxLength

public void setMaxLength(long maxLength)
Set the maximum length in bytes to read, or -1 for an unlimited length.


getMaxLength

public long getMaxLength()

isMaxLengthMet

public boolean isMaxLengthMet()
Whether or not the maximum length has been met.


getElementContentDisposition

public java.lang.String getElementContentDisposition()
Gets the value for the "Content-Dispositio" header for the current multipart element. Usually "form-data".


getElementName

public java.lang.String getElementName()
Gets the name of the current element. The name corresponds to the value of the "name" attribute of the form element.


getElementCharset

public java.lang.String getElementCharset()
Gets the character encoding of the current element. The character encoding would have been specified in the Content-Type header for this element, if it wasn't this is null.


getElementContentType

public java.lang.String getElementContentType()
Gets the "Content-Type" of the current element. If this is a text element, the content type will probably be "text/plain", otherwise it will be the content type of the file element.


getElementFileName

public java.lang.String getElementFileName()
Gets the filename of the current element, which will be null if the current element isn't a file.


isElementFile

public boolean isElementFile()
Gets whether or not the current form element being read is a file.


isBoundaryEncountered

public boolean isBoundaryEncountered()
Returns whether or not the boundary has been encountered while reading data.


isFinalBoundaryEncountered

public boolean isFinalBoundaryEncountered()
Returns whether or not the final boundary has been encountered.


isEndOfStream

public boolean isEndOfStream()
Whether or not an EOF has been read on the stream.


setLineSize

public void setLineSize(int size)

getBytesRead

public long getBytesRead()

readFirstElement

private final void readFirstElement()
                             throws java.io.IOException
java.io.IOException

readElementHeaders

private final void readElementHeaders()
                               throws java.io.IOException
java.io.IOException

readContentDisposition

private final void readContentDisposition()
                                   throws java.io.IOException
java.io.IOException

checkAndFixFilename

private final java.lang.String checkAndFixFilename(java.lang.String filename)

parseForParameter

private final java.lang.String parseForParameter(java.lang.String parameter,
                                                 java.lang.String parseString)

readContentType

private final boolean readContentType()
                               throws java.io.IOException
java.io.IOException

parseHeaderValue

private final java.lang.String parseHeaderValue(java.lang.String headerLine)

skipCurrentLineIfBlank

private final void skipCurrentLineIfBlank()
                                   throws java.io.IOException
java.io.IOException

resetCrlf

private final void resetCrlf()

resetStream

private final void resetStream()

readLine

private final java.lang.String readLine()
                                 throws java.io.IOException
java.io.IOException

readFromLine

private final int readFromLine()
                        throws java.io.IOException
java.io.IOException

availableInLine

private final int availableInLine()

fillLine

private final void fillLine()
                     throws java.io.IOException
java.io.IOException

resetLine

private final void resetLine()

fillLineBuffer

private final void fillLineBuffer()
                           throws java.io.IOException
java.io.IOException

byteRead

private final void byteRead()

checkForBoundary

private final void checkForBoundary()

equals

private final boolean equals(byte[] comp,
                             int offset,
                             int length,
                             byte[] source)
Checks bytes for equality. Two byte arrays are equal if each of their elements are the same. This method checks comp[offset] with source[0] to source[length-1] with comp[offset + length - 1]

Parameters:
comp - The byte to compare to source
offset - The offset to start at in comp
length - The length of comp to compare to
source - The reference byte array to test for equality


Copyright © 2000-2003 - Apache Software Foundation