You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by jo...@apache.org on 2008/10/25 03:02:38 UTC

svn commit: r707802 - in /poi/trunk/src: java/org/apache/poi/hssf/record/ java/org/apache/poi/poifs/filesystem/ java/org/apache/poi/util/ testcases/org/apache/poi/poifs/filesystem/

Author: josh
Date: Fri Oct 24 18:02:37 2008
New Revision: 707802

URL: http://svn.apache.org/viewvc?rev=707802&view=rev
Log:
Further simplification to RecordInputStream.  Mostly regarding Strings, ContinueRecords and LittleEndianInput

Modified:
    poi/trunk/src/java/org/apache/poi/hssf/record/RecordInputStream.java
    poi/trunk/src/java/org/apache/poi/hssf/record/SupBookRecord.java
    poi/trunk/src/java/org/apache/poi/hssf/record/TextObjectRecord.java
    poi/trunk/src/java/org/apache/poi/hssf/record/UnicodeString.java
    poi/trunk/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java
    poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java
    poi/trunk/src/java/org/apache/poi/util/LittleEndianInput.java
    poi/trunk/src/java/org/apache/poi/util/LittleEndianInputStream.java
    poi/trunk/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/RecordInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/RecordInputStream.java?rev=707802&r1=707801&r2=707802&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/RecordInputStream.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/RecordInputStream.java Fri Oct 24 18:02:37 2008
@@ -18,7 +18,6 @@
 package org.apache.poi.hssf.record;
 
 import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 import java.io.InputStream;
 
 import org.apache.poi.util.LittleEndian;
@@ -35,20 +34,37 @@
 	/** Maximum size of a single record (minus the 4 byte header) without a continue*/
 	public final static short MAX_RECORD_DATA_SIZE = 8224;
 	private static final int INVALID_SID_VALUE = -1;
+	/**
+	 * When {@link #_currentDataLength} has this value, it means that the previous BIFF record is
+	 * finished, the next sid has been properly read, but the data size field has not been read yet.
+	 */
 	private static final int DATA_LEN_NEEDS_TO_BE_READ = -1;
 	private static final byte[] EMPTY_BYTE_ARRAY = { };
 
-	private final InputStream _in;
-	/** {@link LittleEndianInput} facet of field {@link #_in} */
+	/** {@link LittleEndianInput} facet of the wrapped {@link InputStream} */
 	private final LittleEndianInput _le;
-	private int currentSid;
+	/** the record identifier of the BIFF record currently being read */
+	private int _currentSid;
+	/** 
+	 * Length of the data section of the current BIFF record (always 4 less than the total record size).
+	 * When uninitialised, this field is set to {@link #DATA_LEN_NEEDS_TO_BE_READ}.
+	 */
 	private int _currentDataLength;
-	private int nextSid;
-	private int recordOffset;
-	private boolean autoContinue; // TODO - remove this
+	/** 
+	 * The BIFF record identifier for the next record is read when just as the current record
+	 * is finished.
+	 * This field is only really valid during the time that ({@link #_currentDataLength} == 
+	 * {@link #DATA_LEN_NEEDS_TO_BE_READ}).  At most other times its value is not really the 
+	 * 'sid of the next record'.  Wwhile mid-record, this field coincidentally holds the sid 
+	 * of the current record.
+	 */
+	private int _nextSid;
+	/** 
+	 * index within the data section of the current BIFF record
+	 */
+	private int _currentDataOffset;
 
 	public RecordInputStream(InputStream in) throws RecordFormatException {
-		_in = in;
 		if (in instanceof LittleEndianInput) {
 			// accessing directly is an optimisation
 			_le = (LittleEndianInput) in;
@@ -56,22 +72,20 @@
 			// less optimal, but should work OK just the same. Often occurs in junit tests.
 			_le = new LittleEndianInputStream(in);
 		}
-		try {
-		      if (_in.available() < LittleEndian.SHORT_SIZE) {
-		          nextSid = INVALID_SID_VALUE;
-		      } else {
-		    	  nextSid = LittleEndian.readShort(in);
-		      }
-		} catch (IOException ex) {
-			throw new RecordFormatException("Error reading bytes", ex);
-		}
-		_currentDataLength = DATA_LEN_NEEDS_TO_BE_READ;
-		autoContinue = true;
+		_nextSid = readNextSid();
+	}
+	
+	/**
+	 * @returns the number of bytes available in the current BIFF record
+	 * @see #remaining()
+	 */
+	public int available() {
+		return remaining();
 	}
 
 	public int read() {
 		checkRecordPosition(LittleEndian.BYTE_SIZE);
-		recordOffset += LittleEndian.BYTE_SIZE;
+		_currentDataOffset += LittleEndian.BYTE_SIZE;
 		return _le.readUByte();
 	}
 	public int read(byte[] b, int off, int len) {
@@ -83,14 +97,9 @@
 		return limit;
 	}
 
-  public short getSid() {
-    return (short) currentSid;
-  }
-
-  public short getLength() { // TODO - remove
-    return (short) _currentDataLength;
-  }
-
+	public short getSid() {
+		return (short) _currentSid;
+	}
 
 	/**
 	 * Note - this method is expected to be called only when completed reading the current BIFF record.
@@ -98,18 +107,17 @@
 	 * discarded
 	 */
 	public boolean hasNextRecord() {
-		if (_currentDataLength != -1 && _currentDataLength != recordOffset) {
-			System.out.println("WARN. Unread "+remaining()+" bytes of record 0x"+Integer.toHexString(currentSid));
+		if (_currentDataLength != -1 && _currentDataLength != _currentDataOffset) {
+			System.out.println("WARN. Unread "+remaining()+" bytes of record 0x"+Integer.toHexString(_currentSid));
 			// discard unread data
-			while (recordOffset < _currentDataLength) {
+			while (_currentDataOffset < _currentDataLength) {
 				readByte();
 			}
 		}
 		if (_currentDataLength != DATA_LEN_NEEDS_TO_BE_READ) {
-			nextSid = readNextSid();
-			_currentDataLength = DATA_LEN_NEEDS_TO_BE_READ;
+			_nextSid = readNextSid();
 		}
-		return nextSid != INVALID_SID_VALUE;
+		return _nextSid != INVALID_SID_VALUE;
 	}
 
 	/**
@@ -117,12 +125,7 @@
 	 * @return the sid of the next record or {@link #INVALID_SID_VALUE} if at end of stream
 	 */
 	private int readNextSid() {
-		int nAvailable;
-		try {
-			nAvailable = _in.available();
-		} catch (IOException e) {
-			throw new RecordFormatException("Error checking stream available bytes", e);
-		}
+		int nAvailable  = _le.available();
 		if (nAvailable < EOFRecord.ENCODED_SIZE) {
 			if (nAvailable > 0) {
 				// some scrap left over?
@@ -135,6 +138,7 @@
 		if (result == INVALID_SID_VALUE) {
 			throw new RecordFormatException("Found invalid sid (" + result + ")");
 		}
+		_currentDataLength = DATA_LEN_NEEDS_TO_BE_READ;
 		return result;
 	}
 
@@ -143,12 +147,14 @@
 	 * <i>Note: The auto continue flag is reset to true</i>
 	 */
 	public void nextRecord() throws RecordFormatException {
-		if (nextSid == INVALID_SID_VALUE) {
+		if (_nextSid == INVALID_SID_VALUE) {
 			throw new IllegalStateException("EOF - next record not available");
 		}
-		currentSid = nextSid;
-		autoContinue = true;
-		recordOffset = 0;
+		if (_currentDataLength != DATA_LEN_NEEDS_TO_BE_READ) {
+			throw new IllegalStateException("Cannot call nextRecord() without checking hasNextRecord() first");
+		}
+		_currentSid = _nextSid;
+		_currentDataOffset = 0;
 		_currentDataLength = _le.readUShort();
 		if (_currentDataLength > MAX_RECORD_DATA_SIZE) {
 			throw new RecordFormatException("The content of an excel record cannot exceed "
@@ -156,19 +162,19 @@
 		}
 	}
 
-  public void setAutoContinue(boolean enable) {
-    this.autoContinue = enable;
-  }
-
 	private void checkRecordPosition(int requiredByteCount) {
 
-		if (remaining() < requiredByteCount) {
-			if (isContinueNext() && autoContinue) {
-				nextRecord();
-			} else {
-			   throw new ArrayIndexOutOfBoundsException();
-			}
+		int nAvailable = remaining();
+		if (nAvailable >= requiredByteCount) {
+			// all OK
+			return;
+		}
+		if (nAvailable == 0 && isContinueNext()) {
+			nextRecord();
+			return;
 		}
+		throw new RecordFormatException("Not enough data (" + nAvailable 
+				+ ") to read requested (" + requiredByteCount +") bytes");
 	}
 
 	/**
@@ -176,7 +182,7 @@
 	 */
 	public byte readByte() {
 		checkRecordPosition(LittleEndian.BYTE_SIZE);
-		recordOffset += LittleEndian.BYTE_SIZE;
+		_currentDataOffset += LittleEndian.BYTE_SIZE;
 		return _le.readByte();
 	}
 
@@ -185,19 +191,19 @@
 	 */
 	public short readShort() {
 		checkRecordPosition(LittleEndian.SHORT_SIZE);
-		recordOffset += LittleEndian.SHORT_SIZE;
+		_currentDataOffset += LittleEndian.SHORT_SIZE;
 		return _le.readShort();
 	}
 
 	public int readInt() {
 		checkRecordPosition(LittleEndian.INT_SIZE);
-		recordOffset += LittleEndian.INT_SIZE;
+		_currentDataOffset += LittleEndian.INT_SIZE;
 		return _le.readInt();
 	}
 
 	public long readLong() {
 		checkRecordPosition(LittleEndian.LONG_SIZE);
-		recordOffset += LittleEndian.LONG_SIZE;
+		_currentDataOffset += LittleEndian.LONG_SIZE;
 		return _le.readLong();
 	}
 
@@ -214,13 +220,13 @@
 	 */
 	public int readUShort() {
 		checkRecordPosition(LittleEndian.SHORT_SIZE);
-		recordOffset += LittleEndian.SHORT_SIZE;
+		_currentDataOffset += LittleEndian.SHORT_SIZE;
 		return _le.readUShort();
 	}
 
 	public double readDouble() {
 		checkRecordPosition(LittleEndian.DOUBLE_SIZE);
-		recordOffset += LittleEndian.DOUBLE_SIZE;
+		_currentDataOffset += LittleEndian.DOUBLE_SIZE;
 		long valueLongBits = _le.readLong();
 		double result = Double.longBitsToDouble(valueLongBits);
 		if (Double.isNaN(result)) {
@@ -235,7 +241,7 @@
 	public void readFully(byte[] buf, int off, int len) {
 		checkRecordPosition(len);
 		_le.readFully(buf, off, len);
-		recordOffset+=len;
+		_currentDataOffset+=len;
 	}
 
 	public String readString() {
@@ -369,20 +375,25 @@
 			// already read sid of next record. so current one is finished
 			return 0;
 		}
-		return (_currentDataLength - recordOffset);
+		return _currentDataLength - _currentDataOffset;
 	}
 
 	/**
 	 *
 	 * @return <code>true</code> when a {@link ContinueRecord} is next.
 	 */
-	public boolean isContinueNext() {
-		if (_currentDataLength != DATA_LEN_NEEDS_TO_BE_READ && recordOffset != _currentDataLength) {
+	private boolean isContinueNext() {
+		if (_currentDataLength != DATA_LEN_NEEDS_TO_BE_READ && _currentDataOffset != _currentDataLength) {
 			throw new IllegalStateException("Should never be called before end of current record");
 		}
 		if (!hasNextRecord()) {
 			return false;
 		}
-		return nextSid == ContinueRecord.sid;
+		// At what point are records continued?
+		//  - Often from within the char data of long strings (caller is within readStringCommon()).
+		//  - From UnicodeString construction (many different points - call via checkRecordPosition)
+		//  - During TextObjectRecord construction (just before the text, perhaps within the text, 
+		//    and before the formatting run data)
+		return _nextSid == ContinueRecord.sid;
 	}
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/SupBookRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/SupBookRecord.java?rev=707802&r1=707801&r2=707802&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/SupBookRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/SupBookRecord.java Fri Oct 24 18:02:37 2008
@@ -84,9 +84,11 @@
      * @param offset of the record's data (provided a big array of the file)
      */
     public SupBookRecord(RecordInputStream in) {
+    	int recLen = in.remaining();
+    	
         field_1_number_of_sheets = in.readShort();
         
-        if(in.getLength() > SMALL_RECORD_SIZE) {
+        if(recLen > SMALL_RECORD_SIZE) {
             // 5.38.1 External References
             _isAddInFunctions = false;
 

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/TextObjectRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/TextObjectRecord.java?rev=707802&r1=707801&r2=707802&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/TextObjectRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/TextObjectRecord.java Fri Oct 24 18:02:37 2008
@@ -131,13 +131,7 @@
 		_text = new HSSFRichTextString(text);
 
 		if (field_7_formattingDataLength > 0) {
-			if (in.isContinueNext() && in.remaining() == 0) {
-				in.nextRecord();
-				processFontRuns(in, _text, field_7_formattingDataLength);
-			} else {
-				throw new RecordFormatException(
-						"Expected Continue Record to hold font runs for TextObjectRecord");
-			}
+			processFontRuns(in, _text, field_7_formattingDataLength);
 		}
 	}
 
@@ -156,10 +150,6 @@
 			throw new RecordFormatException("Bad format run data length " + formattingRunDataLength
 					+ ")");
 		}
-		if (in.remaining() != formattingRunDataLength) {
-			throw new RecordFormatException("Expected " + formattingRunDataLength
-					+ " bytes but got " + in.remaining());
-		}
 		int nRuns = formattingRunDataLength / FORMAT_RUN_ENCODED_SIZE;
 		for (int i = 0; i < nRuns; i++) {
 			short index = in.readShort();

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/UnicodeString.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/UnicodeString.java?rev=707802&r1=707801&r2=707802&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/UnicodeString.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/UnicodeString.java Fri Oct 24 18:02:37 2008
@@ -36,13 +36,8 @@
  * @author  Andrew C. Oliver
  * @author Marc Johnson (mjohnson at apache dot org)
  * @author Glen Stampoultzis (glens at apache.org)
- * @version 2.0-pre
  */
-
-public class UnicodeString
-    implements Comparable
-{
-    public final static short sid = 0xFFF;
+public final class UnicodeString implements Comparable {
     private short             field_1_charCount;     // = 0;
     private byte              field_2_optionflags;   // = 0;
     private String            field_3_string;        // = null;
@@ -53,8 +48,8 @@
     private  static final BitField   richText  = BitFieldFactory.getInstance(0x8);
 
     public static class FormatRun implements Comparable {
-      private short character;
-      private short fontIndex;
+      short character;
+      short fontIndex;
 
       public FormatRun(short character, short fontIndex) {
         this.character = character;
@@ -102,15 +97,6 @@
       setString(str);
     }
 
-    /**
-     * construct a unicode string record and fill its fields, ID is ignored
-     * @param in the RecordInputstream to read the record from
-     */
-
-    public UnicodeString(RecordInputStream in)
-    {
-      fillFields(in); // TODO - inline
-    }
 
 
     public int hashCode()
@@ -142,9 +128,9 @@
                 && field_3_string.equals(other.field_3_string));
         if (!eq) return false;
 
-        //Ok string appears to be equal but now lets compare formatting runs
+        //OK string appears to be equal but now lets compare formatting runs
         if ((field_4_format_runs == null) && (other.field_4_format_runs == null))
-          //Strings are equal, and there are not formtting runs.
+          //Strings are equal, and there are not formatting runs.
           return true;
         if (((field_4_format_runs == null) && (other.field_4_format_runs != null)) ||
              (field_4_format_runs != null) && (other.field_4_format_runs == null))
@@ -186,10 +172,10 @@
     }
 
     /**
+     * construct a unicode string record and fill its fields, ID is ignored
      * @param in the RecordInputstream to read the record from
      */
-    protected void fillFields(RecordInputStream in)
-        {
+    public UnicodeString(RecordInputStream in) {
         field_1_charCount   = in.readShort();
         field_2_optionflags = in.readByte();
 
@@ -206,35 +192,13 @@
             extensionLength = in.readInt();
         }
 
-        //Now need to get the string data.
-        //Turn off autocontinuation so that we can catch the continue boundary
-        in.setAutoContinue(false);
-        StringBuffer tmpString = new StringBuffer(field_1_charCount);
-        int stringCharCount = field_1_charCount;
         boolean isCompressed = ((field_2_optionflags & 1) == 0);
-        while (stringCharCount != 0) {
-          if (in.remaining() == 0) {
-            if (in.isContinueNext()) {
-              in.nextRecord();
-              //Check if we are now reading, compressed or uncompressed unicode.
-              byte optionflags = in.readByte();
-              isCompressed = ((optionflags & 1) == 0);
-            } else
-              throw new RecordFormatException("Expected continue record.");
-          }
-          if (isCompressed) {
-            char ch = (char)in.readUByte(); // avoid sex
-            tmpString.append(ch);
-          } else {
-            char ch = (char) in.readShort();
-            tmpString.append(ch);
-          }
-          stringCharCount --;
+        if (isCompressed) {
+        	field_3_string = in.readCompressedUnicode(field_1_charCount);
+        } else {
+        	field_3_string = in.readUnicodeLEString(field_1_charCount);
         }
-        field_3_string = tmpString.toString();
-        //Turn back on autocontinuation
-        in.setAutoContinue(true);
-
+ 
 
         if (isRichText() && (runCount > 0)) {
           field_4_format_runs = new ArrayList(runCount);
@@ -305,13 +269,8 @@
     }
 
     /**
-     * get the actual string this contains as a java String object
-     *
-     *
-     * @return String
-     *
+     * @return the actual string this contains as a java String object
      */
-
     public String getString()
     {
         return field_3_string;
@@ -341,7 +300,7 @@
             }
         }
         if (useUTF16)
-          //Set the uncomressed bit
+          //Set the uncompressed bit
           field_2_optionflags = highByte.setByte(field_2_optionflags);
         else field_2_optionflags = highByte.clearByte(field_2_optionflags);
     }
@@ -392,7 +351,7 @@
 
       //Make sure that we now say that we are a rich string
       field_2_optionflags = richText.setByte(field_2_optionflags);
-        }
+    }
 
     public Iterator formatIterator() {
       if (field_4_format_runs != null)
@@ -497,8 +456,8 @@
 
         LittleEndian.putShort(data, offset, ContinueRecord.sid);
         offset+=2;
-        //Record the location of the last continue legnth position, but dont write
-        //anything there yet (since we dont know what it will be!)
+        //Record the location of the last continue length position, but don't write
+        //anything there yet (since we don't know what it will be!)
         stats.lastLengthPos = offset;
         offset += 2;
 
@@ -506,7 +465,7 @@
         stats.remainingSize = SSTRecord.MAX_RECORD_SIZE-4;
       }
       return offset;
-        }
+    }
 
     public int serialize(UnicodeRecordStats stats, final int offset, byte [] data)
     {
@@ -514,7 +473,6 @@
 
       //Basic string overhead
       pos = writeContinueIfRequired(stats, 3, pos, data);
-        // byte[] retval = new byte[ 3 + (getString().length() * charsize)];
       LittleEndian.putShort(data, pos, getCharCount());
       pos += 2;
       data[ pos ] = getOptionFlags();
@@ -568,39 +526,39 @@
       //Check to see if the offset occurs mid string, if so then we need to add
       //the byte to start with that represents the first byte of the continue record.
       if (strSize > stats.remainingSize) {
-        //Ok the offset occurs half way through the string, that means that
+        //OK the offset occurs half way through the string, that means that
         //we need an extra byte after the continue record ie we didnt finish
         //writing out the string the 1st time through
 
         //But hang on, how many continue records did we span? What if this is
         //a REALLY long string. We need to work this all out.
-        int ammountThatCantFit = strSize;
+        int amountThatCantFit = strSize;
         int strPos = 0;
-        while (ammountThatCantFit > 0) {
-          int ammountWritten = Math.min(stats.remainingSize, ammountThatCantFit);
-          //Make sure that the ammount that cant fit takes into account
+        while (amountThatCantFit > 0) {
+          int amountWritten = Math.min(stats.remainingSize, amountThatCantFit);
+          //Make sure that the amount that can't fit takes into account
           //whether we are writing double byte unicode
           if (isUncompressedUnicode()) {
             //We have the '-1' here because whether this is the first record or
             //subsequent continue records, there is always the case that the
-            //number of bytes in a string on doube byte boundaries is actually odd.
-            if ( ( (ammountWritten ) % 2) == 1)
-              ammountWritten--;
-          }
-          System.arraycopy(strBytes, strPos, data, pos, ammountWritten);
-          pos += ammountWritten;
-          strPos += ammountWritten;
-          stats.recordSize += ammountWritten;
-          stats.remainingSize -= ammountWritten;
+            //number of bytes in a string on double byte boundaries is actually odd.
+            if ( ( (amountWritten ) % 2) == 1)
+              amountWritten--;
+          }
+          System.arraycopy(strBytes, strPos, data, pos, amountWritten);
+          pos += amountWritten;
+          strPos += amountWritten;
+          stats.recordSize += amountWritten;
+          stats.remainingSize -= amountWritten;
 
           //Ok lets subtract what we can write
-          ammountThatCantFit -= ammountWritten;
+          amountThatCantFit -= amountWritten;
 
           //Each iteration of this while loop is another continue record, unless
           //everything  now fits.
-          if (ammountThatCantFit > 0) {
+          if (amountThatCantFit > 0) {
             //We know that a continue WILL be requied, but use this common method
-            pos = writeContinueIfRequired(stats, ammountThatCantFit, pos, data);
+            pos = writeContinueIfRequired(stats, amountThatCantFit, pos, data);
 
             //The first byte after a continue mid string is the extra byte to
             //indicate if this run is compressed or not.
@@ -686,7 +644,7 @@
         return highByte.isSet(getOptionFlags());
     }
 
-    /** Returns the size of this record, given the ammount of record space
+    /** Returns the size of this record, given the amount of record space
      * remaining, it will also include the size of writing a continue record.
      */
 
@@ -833,13 +791,6 @@
       }
     }
 
-
-
-    public short getSid()
-    {
-        return sid;
-    }
-
     public int compareTo(Object obj)
     {
         UnicodeString str = ( UnicodeString ) obj;
@@ -877,7 +828,7 @@
         }
 
         //Well the format runs are equal as well!, better check the ExtRst data
-        //Which by the way we dont know how to decode!
+        //Which by the way we don't know how to decode!
         if ((field_5_ext_rst == null) && (str.field_5_ext_rst == null))
           return 0;
         if ((field_5_ext_rst == null) && (str.field_5_ext_rst != null))

Modified: poi/trunk/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java?rev=707802&r1=707801&r2=707802&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java Fri Oct 24 18:02:37 2008
@@ -89,8 +89,10 @@
 		_currentBlock = getDataInputBlock(0);
 	}
 
-	public int available() throws IOException {
-		dieIfClosed();
+	public int available() {
+		if (_closed) {
+			throw new IllegalStateException("cannot perform requested operation on a closed stream");
+		}
 		return _document_size - _current_offset;
 	}
 
@@ -194,7 +196,7 @@
 
 	private void checkAvaliable(int requestedSize) {
 		if (_closed) {
-			throw new RuntimeException("cannot perform requested operation on a closed stream");
+			throw new IllegalStateException("cannot perform requested operation on a closed stream");
 		}
 		if (requestedSize > _document_size - _current_offset) {
 			throw new RuntimeException("Buffer underrun - requested " + requestedSize

Modified: poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java?rev=707802&r1=707801&r2=707802&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java (original)
+++ poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java Fri Oct 24 18:02:37 2008
@@ -40,6 +40,9 @@
 		this(buf, 0, buf.length);
 	}
 
+	public int available() {
+		return _endIndex - _readIndex;
+	}
 	private void checkPosition(int i) {
 		if (i > _endIndex - _readIndex) {
 			throw new RuntimeException("Buffer overrun");

Modified: poi/trunk/src/java/org/apache/poi/util/LittleEndianInput.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/LittleEndianInput.java?rev=707802&r1=707801&r2=707802&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/LittleEndianInput.java (original)
+++ poi/trunk/src/java/org/apache/poi/util/LittleEndianInput.java Fri Oct 24 18:02:37 2008
@@ -21,6 +21,7 @@
  * @author Josh Micich
  */
 public interface LittleEndianInput {
+	int available();
 	byte readByte();
 	int readUByte();
 	short readShort();

Modified: poi/trunk/src/java/org/apache/poi/util/LittleEndianInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/LittleEndianInputStream.java?rev=707802&r1=707801&r2=707802&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/LittleEndianInputStream.java (original)
+++ poi/trunk/src/java/org/apache/poi/util/LittleEndianInputStream.java Fri Oct 24 18:02:37 2008
@@ -22,6 +22,10 @@
 import java.io.InputStream;
 
 /**
+ * Wraps an {@link InputStream} providing {@link LittleEndianInput}<p/>
+ * 
+ * This class does not buffer any input, so the stream read position maintained 
+ * by this class is consistent with that of the inner stream.
  * 
  * @author Josh Micich
  */
@@ -29,7 +33,13 @@
 	public LittleEndianInputStream(InputStream is) {
 		super(is);
 	}
-
+	public int available() {
+		try {
+			return super.available();
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
 	public byte readByte() {
 		return (byte)readUByte();
 	}

Modified: poi/trunk/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java?rev=707802&r1=707801&r2=707802&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java Fri Oct 24 18:02:37 2008
@@ -1,4 +1,3 @@
-
 /* ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -15,18 +14,16 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 ==================================================================== */
-        
 
 package org.apache.poi.poifs.filesystem;
 
-import java.io.*;
-
-import java.util.*;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Arrays;
 
-import junit.framework.*;
+import junit.framework.TestCase;
 
 import org.apache.poi.poifs.property.DirectoryProperty;
-import org.apache.poi.poifs.property.DocumentProperty;
 import org.apache.poi.poifs.storage.RawDataBlock;
 
 /**
@@ -35,22 +32,9 @@
  * @author Marc Johnson
  */
 
-public class TestDocumentInputStream
-    extends TestCase
-{
-
-    /**
-     * Constructor TestDocumentInputStream
-     *
-     * @param name
-     *
-     * @exception IOException
-     */
+public final class TestDocumentInputStream extends TestCase {
 
-    public TestDocumentInputStream(String name)
-        throws IOException
-    {
-        super(name);
+	protected void setUp() throws Exception {
         int blocks = (_workbook_size + 511) / 512;
 
         _workbook_data = new byte[ 512 * blocks ];
@@ -86,13 +70,8 @@
 
     /**
      * test constructor
-     *
-     * @exception IOException
      */
-
-    public void testConstructor()
-        throws IOException
-    {
+    public void testConstructor() throws IOException {
         DocumentInputStream stream = new DocumentInputStream(_workbook);
 
         assertEquals(_workbook_size, stream.available());
@@ -100,13 +79,8 @@
 
     /**
      * test available() behavior
-     *
-     * @exception IOException
      */
-
-    public void testAvailable()
-        throws IOException
-    {
+    public void testAvailable() throws IOException {
         DocumentInputStream stream = new DocumentInputStream(_workbook);
 
         assertEquals(_workbook_size, stream.available());
@@ -115,9 +89,7 @@
         {
             stream.available();
             fail("Should have caught IOException");
-        }
-        catch (IOException ignored)
-        {
+        } catch (IllegalStateException ignored) {
 
             // as expected
         }
@@ -125,13 +97,8 @@
 
     /**
      * test mark/reset/markSupported.
-     *
-     * @exception IOException
      */
-
-    public void testMarkFunctions()
-        throws IOException
-    {
+    public void testMarkFunctions() throws IOException {
         DocumentInputStream stream = new DocumentInputStream(_workbook);
         byte[]              buffer = new byte[ _workbook_size / 5 ];
 
@@ -169,13 +136,8 @@
 
     /**
      * test simple read method
-     *
-     * @exception IOException
      */
-
-    public void testReadSingleByte()
-        throws IOException
-    {
+    public void testReadSingleByte() throws IOException {
         DocumentInputStream stream    = new DocumentInputStream(_workbook);
         int                 remaining = _workbook_size;
 
@@ -205,13 +167,8 @@
 
     /**
      * Test buffered read
-     *
-     * @exception IOException
      */
-
-    public void testBufferRead()
-        throws IOException
-    {
+    public void testBufferRead() throws IOException {
         DocumentInputStream stream = new DocumentInputStream(_workbook);
 
         try
@@ -275,13 +232,8 @@
 
     /**
      * Test complex buffered read
-     *
-     * @exception IOException
      */
-
-    public void testComplexBufferRead()
-        throws IOException
-    {
+    public void testComplexBufferRead() throws IOException {
         DocumentInputStream stream = new DocumentInputStream(_workbook);
 
         try {
@@ -387,13 +339,8 @@
 
     /**
      * test skip
-     *
-     * @exception IOException
      */
-
-    public void testSkip()
-        throws IOException
-    {
+    public void testSkip() throws IOException {
         DocumentInputStream stream = new DocumentInputStream(_workbook);
 
         assertEquals(_workbook_size, stream.available());
@@ -418,17 +365,4 @@
                      stream.skip(2 + ( long ) Integer.MAX_VALUE));
         assertEquals(0, stream.available());
     }
-
-    /**
-     * main method to run the unit tests
-     *
-     * @param ignored_args
-     */
-
-    public static void main(String [] ignored_args)
-    {
-        System.out.println(
-            "Testing org.apache.poi.poifs.filesystem.DocumentInputStream");
-        junit.textui.TestRunner.run(TestDocumentInputStream.class);
-    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org