poi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From n...@apache.org
Subject svn commit: r1050607 - in /poi/trunk/src: java/org/apache/poi/poifs/nio/ java/org/apache/poi/poifs/storage/ java/org/apache/poi/util/ testcases/org/apache/poi/poifs/nio/
Date Sat, 18 Dec 2010 10:18:44 GMT
Author: nick
Date: Sat Dec 18 10:18:43 2010
New Revision: 1050607

URL: http://svn.apache.org/viewvc?rev=1050607&view=rev
Log:
Start on lower memory POIFS implementation - data source to provide common access to array
of bytes and files

Added:
    poi/trunk/src/java/org/apache/poi/poifs/nio/
    poi/trunk/src/java/org/apache/poi/poifs/nio/ByteArrayBackedDataSource.java
    poi/trunk/src/java/org/apache/poi/poifs/nio/DataSource.java
    poi/trunk/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java
    poi/trunk/src/testcases/org/apache/poi/poifs/nio/
    poi/trunk/src/testcases/org/apache/poi/poifs/nio/TestDataSource.java
Modified:
    poi/trunk/src/java/org/apache/poi/poifs/storage/HeaderBlockReader.java
    poi/trunk/src/java/org/apache/poi/util/IOUtils.java

Added: poi/trunk/src/java/org/apache/poi/poifs/nio/ByteArrayBackedDataSource.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/nio/ByteArrayBackedDataSource.java?rev=1050607&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/nio/ByteArrayBackedDataSource.java (added)
+++ poi/trunk/src/java/org/apache/poi/poifs/nio/ByteArrayBackedDataSource.java Sat Dec 18
10:18:43 2010
@@ -0,0 +1,83 @@
+/* ====================================================================
+   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.poi.poifs.nio;
+
+import java.nio.ByteBuffer;
+
+/**
+ * A POIFS {@link DataSource} backed by a byte array.
+ */
+public class ByteArrayBackedDataSource extends DataSource {
+   private byte[] buffer;
+   private long size;
+   
+   public ByteArrayBackedDataSource(byte[] data) {
+      this.buffer = data;
+      this.size = data.length;
+   }
+                
+   public void read(ByteBuffer dst, long position) {
+      if(position + dst.capacity() > size) {
+         throw new IndexOutOfBoundsException(
+               "Unable to read " + dst.capacity() + " bytes from " +
+               position + " in stream of length " + size
+         );
+      }
+      dst.put(buffer, (int)position, dst.capacity());
+   }
+   
+   public void write(ByteBuffer src, long position) {
+      // Extend if needed
+      long endPosition = position + src.capacity(); 
+      if(endPosition > buffer.length) {
+         extend(endPosition);
+      }
+      
+      // Now copy
+      src.get(buffer, (int)position, src.capacity());
+      
+      // Update size if needed
+      if(endPosition > size) {
+         size = endPosition;
+      }
+   }
+   
+   private void extend(long length) {
+      // Consider extending by a bit more than requested
+      long difference = length - buffer.length;
+      if(difference < buffer.length*0.25) {
+         difference = (long)(buffer.length*0.25);
+      }
+      if(difference < 4096) {
+         difference = 4096;
+      }
+
+      byte[] nb = new byte[(int)(difference+buffer.length)];
+      System.arraycopy(buffer, 0, nb, 0, (int)size);
+      buffer = nb;
+   }
+   
+   public long size() {
+      return size;
+   }
+   
+   public void close() {
+      buffer = null;
+      size = -1;
+   }
+}

Added: poi/trunk/src/java/org/apache/poi/poifs/nio/DataSource.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/nio/DataSource.java?rev=1050607&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/nio/DataSource.java (added)
+++ poi/trunk/src/java/org/apache/poi/poifs/nio/DataSource.java Sat Dec 18 10:18:43 2010
@@ -0,0 +1,31 @@
+/* ====================================================================
+   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.poi.poifs.nio;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * Common definition of how we read and write bytes
+ */
+public abstract class DataSource {
+   abstract void read(ByteBuffer dst, long position) throws IOException;
+   abstract void write(ByteBuffer src, long position) throws IOException;
+   abstract long size() throws IOException;
+   abstract void close() throws IOException;
+}

Added: poi/trunk/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java?rev=1050607&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java (added)
+++ poi/trunk/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java Sat Dec 18 10:18:43
2010
@@ -0,0 +1,48 @@
+/* ====================================================================
+   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.poi.poifs.nio;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+
+/**
+ * A POIFS {@link DataSource} backed by a File
+ */
+public class FileBackedDataSource extends DataSource {
+   private FileChannel file;
+   public FileBackedDataSource(FileChannel file) {
+      this.file = file;
+   }
+   
+   public void read(ByteBuffer dst, long position) throws IOException {
+      file.read(dst, position);
+   }
+   
+   public void write(ByteBuffer src, long position) throws IOException {
+      file.write(src, position);
+   }
+   
+   public long size() throws IOException {
+      return file.size();
+   }
+   
+   public void close() throws IOException {
+      file.close();
+   }
+}

Modified: poi/trunk/src/java/org/apache/poi/poifs/storage/HeaderBlockReader.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/storage/HeaderBlockReader.java?rev=1050607&r1=1050606&r2=1050607&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/storage/HeaderBlockReader.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/storage/HeaderBlockReader.java Sat Dec 18 10:18:43
2010
@@ -30,6 +30,7 @@ import static org.apache.poi.poifs.stora
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.ByteBuffer;
 
 import org.apache.poi.poifs.common.POIFSBigBlockSize;
 import org.apache.poi.poifs.common.POIFSConstants;
@@ -83,6 +84,10 @@ public final class HeaderBlockReader {
 	 * (Number of DIFAT Sectors in Microsoft parlance)
 	 */
 	private final int _xbat_count;
+	
+	/**
+	 * The data
+	 */
 	private final byte[] _data;
 
 	/**
@@ -93,26 +98,36 @@ public final class HeaderBlockReader {
 	 * @exception IOException on errors or bad data
 	 */
 	public HeaderBlockReader(InputStream stream) throws IOException {
-		// At this point, we don't know how big our
-		//  block sizes are
-		// So, read the first 32 bytes to check, then
-		//  read the rest of the block
-		byte[] blockStart = new byte[32];
-		int bsCount = IOUtils.readFully(stream, blockStart);
-		if(bsCount != 32) {
-			throw alertShortRead(bsCount, 32);
-		}
-
+		// Grab the first 512 bytes
+	   // (For 4096 sized blocks, the remaining 3584 bytes are zero)
+		// Then, process the contents
+		this(readFirst512(stream));
+		
+		// Fetch the rest of the block if needed
+		if(bigBlockSize.getBigBlockSize() != 512) {
+		   int rest = bigBlockSize.getBigBlockSize() - 512;
+		   byte[] tmp = new byte[rest];
+		   IOUtils.readFully(stream, tmp);
+		}
+	}
+	
+	public HeaderBlockReader(ByteBuffer buffer) throws IOException {
+	   this(buffer.array());
+	}
+	
+	private HeaderBlockReader(byte[] data) throws IOException {
+	   this._data = data;
+	   
 		// verify signature
-		long signature = LittleEndian.getLong(blockStart, _signature_offset);
+		long signature = LittleEndian.getLong(_data, _signature_offset);
 
 		if (signature != _signature) {
 			// Is it one of the usual suspects?
 			byte[] OOXML_FILE_HEADER = POIFSConstants.OOXML_FILE_HEADER;
-			if(blockStart[0] == OOXML_FILE_HEADER[0] &&
-				blockStart[1] == OOXML_FILE_HEADER[1] &&
-				blockStart[2] == OOXML_FILE_HEADER[2] &&
-				blockStart[3] == OOXML_FILE_HEADER[3]) {
+			if(_data[0] == OOXML_FILE_HEADER[0] &&
+				_data[1] == OOXML_FILE_HEADER[1] &&
+				_data[2] == OOXML_FILE_HEADER[2] &&
+				_data[3] == OOXML_FILE_HEADER[3]) {
 				throw new OfficeXmlFileException("The supplied data appears to be in the Office 2007+
XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call
a different part of POI to process this data (eg XSSF instead of HSSF)");
 			}
 			if ((signature & 0xFF8FFFFFFFFFFFFFL) == 0x0010000200040009L) {
@@ -129,22 +144,14 @@ public final class HeaderBlockReader {
 
 
 		// Figure out our block size
-		switch (blockStart[30]) {
+		switch (_data[30]) {
 			case 12:
 				bigBlockSize = POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS; break;
 			case  9:
 				bigBlockSize = POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS; break;
 			default:
 				throw new IOException("Unsupported blocksize  (2^"
-						+ blockStart[30] + "). Expected 2^9 or 2^12.");
-		}
-		_data = new byte[ bigBlockSize.getBigBlockSize() ];
-		System.arraycopy(blockStart, 0, _data, 0, blockStart.length);
-
-		// Now we can read the rest of our header
-		int byte_count = IOUtils.readFully(stream, _data, blockStart.length, _data.length - blockStart.length);
-		if (byte_count+bsCount != bigBlockSize.getBigBlockSize()) {
-			throw alertShortRead(byte_count, bigBlockSize.getBigBlockSize());
+						+ _data[30] + "). Expected 2^9 or 2^12.");
 		}
 
 		_bat_count      = getInt(_bat_count_offset, _data);
@@ -154,6 +161,17 @@ public final class HeaderBlockReader {
 		_xbat_start     = getInt(_xbat_start_offset, _data);
 		_xbat_count     = getInt(_xbat_count_offset, _data);
 	}
+	
+	private static byte[] readFirst512(InputStream stream) throws IOException {
+      // Grab the first 512 bytes
+      // (For 4096 sized blocks, the remaining 3584 bytes are zero)
+      byte[] data = new byte[512];
+      int bsCount = IOUtils.readFully(stream, data);
+      if(bsCount != 512) {
+         throw alertShortRead(bsCount, 512);
+      }
+      return data;
+	}
 
 	private static int getInt(int offset, byte[] data) {
 		return LittleEndian.getInt(data, offset);
@@ -216,7 +234,7 @@ public final class HeaderBlockReader {
 
 		for (int j = 0; j < _max_bats_in_header; j++) {
 			result[ j ] = LittleEndian.getInt(_data, offset);
-			offset      += LittleEndianConsts.INT_SIZE;
+			offset     += LittleEndianConsts.INT_SIZE;
 		}
 		return result;
 	}

Modified: poi/trunk/src/java/org/apache/poi/util/IOUtils.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/IOUtils.java?rev=1050607&r1=1050606&r2=1050607&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/IOUtils.java (original)
+++ poi/trunk/src/java/org/apache/poi/util/IOUtils.java Sat Dec 18 10:18:43 2010
@@ -21,6 +21,8 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
 
 public final class IOUtils {
 	private IOUtils() {
@@ -74,6 +76,29 @@ public final class IOUtils {
 			}
 		}
 	}
+	
+   /**
+    * Same as the normal <tt>channel.read(b)</tt>, but tries to ensure
+    * that the entire len number of bytes is read.
+    * <p>
+    * If the end of file is reached before any bytes are read, returns -1. If
+    * the end of the file is reached after some bytes are read, returns the
+    * number of bytes read. If the end of the file isn't reached before len
+    * bytes have been read, will return len bytes.
+    */
+	public static int readFully(ReadableByteChannel channel, ByteBuffer b) throws IOException
{
+      int total = 0;
+      while (true) {
+         int got = channel.read(b); 
+         if (got < 0) {
+            return (total == 0) ? -1 : total;
+         }
+         total += got;
+         if (total == b.capacity()) {
+            return total;
+         }
+      }
+	}
 
 	/**
 	 * Copies all the data from the given InputStream to the OutputStream. It

Added: poi/trunk/src/testcases/org/apache/poi/poifs/nio/TestDataSource.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/poifs/nio/TestDataSource.java?rev=1050607&view=auto
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/poifs/nio/TestDataSource.java (added)
+++ poi/trunk/src/testcases/org/apache/poi/poifs/nio/TestDataSource.java Sat Dec 18 10:18:43
2010
@@ -0,0 +1,38 @@
+
+/* ====================================================================
+   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.poi.poifs.nio;
+
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for the datasource implementations
+ */
+public class TestDataSource extends TestCase
+{
+   public void testFile() throws IOException {
+      // TODO
+   }
+   
+   public void testByteArray() throws IOException {
+      // TODO
+   }
+}



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


Mime
View raw message