]> source.dussan.org Git - poi.git/commitdiff
Add NPOIFS high level Document implementation
authorNick Burch <nick@apache.org>
Tue, 28 Dec 2010 07:15:38 +0000 (07:15 +0000)
committerNick Burch <nick@apache.org>
Tue, 28 Dec 2010 07:15:38 +0000 (07:15 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1053273 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java
src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java [new file with mode: 0644]
src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java
src/java/org/apache/poi/poifs/storage/BATBlock.java

index 5b0cfb66075cb40c93dcaab738ba871dc42251b3..92261929ac0f34fa3fca627a03e6cd9173835316 100644 (file)
@@ -187,7 +187,6 @@ public class DirectoryNode
      *
      * @exception IOException
      */
-
     DocumentEntry createDocument(final POIFSDocument document)
         throws IOException
     {
@@ -195,12 +194,30 @@ public class DirectoryNode
         DocumentNode     rval     = new DocumentNode(property, this);
 
         (( DirectoryProperty ) getProperty()).addChild(property);
+        _ofilesystem.addDocument(document);
         
-        if(_ofilesystem != null) {
-           _ofilesystem.addDocument(document);
-        } else {
-           _nfilesystem.addDocument(document);
-        }
+        _entries.add(rval);
+        _byname.put(property.getName(), rval);
+        return rval;
+    }
+
+    /**
+     * create a new DocumentEntry
+     *
+     * @param document the new document
+     *
+     * @return the new DocumentEntry
+     *
+     * @exception IOException
+     */
+    DocumentEntry createDocument(final NPOIFSDocument document)
+        throws IOException
+    {
+        DocumentProperty property = document.getDocumentProperty();
+        DocumentNode     rval     = new DocumentNode(property, this);
+
+        (( DirectoryProperty ) getProperty()).addChild(property);
+        _nfilesystem.addDocument(document);
         
         _entries.add(rval);
         _byname.put(property.getName(), rval);
@@ -215,7 +232,6 @@ public class DirectoryNode
      *
      * @return true if the operation succeeded, else false
      */
-
     boolean changeName(final String oldName, final String newName)
     {
         boolean   rval  = false;
diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java
new file mode 100644 (file)
index 0000000..08c66b6
--- /dev/null
@@ -0,0 +1,185 @@
+/* ====================================================================
+   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.filesystem;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.apache.poi.poifs.common.POIFSConstants;
+import org.apache.poi.poifs.dev.POIFSViewable;
+import org.apache.poi.poifs.property.DocumentProperty;
+import org.apache.poi.util.HexDump;
+import org.apache.poi.util.IOUtils;
+
+/**
+ * This class manages a document in the NIO POIFS filesystem.
+ * This is the {@link NPOIFSFileSystem} version.
+ */
+public final class NPOIFSDocument implements POIFSViewable {
+   private DocumentProperty _property;
+
+   private NPOIFSFileSystem _filesystem;
+   private NPOIFSStream _stream;
+   private int _block_size;
+       
+   /**
+    * Constructor for an existing Document 
+    */
+   public NPOIFSDocument(DocumentProperty property, NPOIFSFileSystem filesystem) 
+      throws IOException
+   {
+      this._property = property;
+      this._filesystem = filesystem;
+
+      if(property.getSize() <= POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE) {
+         _stream = new NPOIFSStream(_filesystem.getMiniStore(), property.getStartBlock());
+         _block_size = _filesystem.getMiniStore().getBlockStoreBlockSize();
+      } else {
+         _stream = new NPOIFSStream(_filesystem, property.getStartBlock());
+         _block_size = _filesystem.getBlockStoreBlockSize();
+      }
+   }
+
+   /**
+    * Constructor for a new Document
+    *
+    * @param name the name of the POIFSDocument
+    * @param stream the InputStream we read data from
+    */
+   public NPOIFSDocument(String name, NPOIFSFileSystem filesystem, InputStream stream) 
+      throws IOException 
+   {
+      this._filesystem = filesystem;
+
+      // Buffer the contents into memory. This is a bit icky...
+      // TODO Replace with a buffer up to the mini stream size, then streaming write
+      byte[] contents;
+      if(stream instanceof ByteArrayInputStream) {
+         ByteArrayInputStream bais = (ByteArrayInputStream)stream;
+         contents = new byte[bais.available()];
+         bais.read(contents);
+      } else {
+         ByteArrayOutputStream baos = new ByteArrayOutputStream();
+         IOUtils.copy(stream, baos);
+         contents = baos.toByteArray();
+      }
+
+      // Do we need to store as a mini stream or a full one?
+      if(contents.length <= POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE) {
+         _stream = new NPOIFSStream(filesystem.getMiniStore());
+         _block_size = _filesystem.getMiniStore().getBlockStoreBlockSize();
+      } else {
+         _stream = new NPOIFSStream(filesystem);
+         _block_size = _filesystem.getBlockStoreBlockSize();
+      }
+
+      // Store it
+      _stream.updateContents(contents);
+
+      // And build the property for it
+      this._property = new DocumentProperty(name, contents.length);
+      _property.setStartBlock(_stream.getStartBlock());     
+   }
+
+   /**
+    * @return size of the document
+    */
+   public int getSize() {
+      return _property.getSize();
+   }
+
+   /**
+    * @return the instance's DocumentProperty
+    */
+   DocumentProperty getDocumentProperty() {
+      return _property;
+   }
+
+   /**
+    * Get an array of objects, some of which may implement POIFSViewable
+    *
+    * @return an array of Object; may not be null, but may be empty
+    */
+   public Object[] getViewableArray() {
+      Object[] results = new Object[1];
+      String result;
+
+      try {
+         if(getSize() > 0) {
+            // Get all the data into a single array
+            byte[] data = new byte[getSize()];
+            int offset = 0;
+            for(ByteBuffer buffer : _stream) {
+               int length = Math.min(_block_size, data.length-offset); 
+               buffer.get(data, offset, length);
+               offset += length;
+            }
+
+            ByteArrayOutputStream output = new ByteArrayOutputStream();
+            HexDump.dump(data, 0, output, 0);
+            result = output.toString();
+         } else {
+            result = "<NO DATA>";
+         }
+      } catch (IOException e) {
+         result = e.getMessage();
+      }
+      results[0] = result;
+      return results;
+   }
+
+   /**
+    * Get an Iterator of objects, some of which may implement POIFSViewable
+    *
+    * @return an Iterator; may not be null, but may have an empty back end
+    *           store
+    */
+   public Iterator getViewableIterator() {
+      return Collections.EMPTY_LIST.iterator();
+   }
+
+   /**
+    * Give viewers a hint as to whether to call getViewableArray or
+    * getViewableIterator
+    *
+    * @return <code>true</code> if a viewer should call getViewableArray,
+    *           <code>false</code> if a viewer should call getViewableIterator
+    */
+   public boolean preferArray() {
+      return true;
+   }
+
+   /**
+    * Provides a short description of the object, to be used when a
+    * POIFSViewable object has not provided its contents.
+    *
+    * @return short description
+    */
+   public String getShortDescription() {
+      StringBuffer buffer = new StringBuffer();
+
+      buffer.append("Document: \"").append(_property.getName()).append("\"");
+      buffer.append(" size = ").append(getSize());
+      return buffer.toString();
+   }
+}
index c292b0a92ad5e6fb20dae7d05a5c5f7b99551335..a397136c208e21d141898f60239fb990dbcd3a5a 100644 (file)
@@ -279,7 +279,7 @@ public class NPOIFSFileSystem extends BlockStore
           ByteBuffer fatData = getBlockAt(nextAt);
           xfat = BATBlock.createBATBlock(bigBlockSize, fatData);
           xfat.setOurBlockIndex(nextAt);
-          nextAt = xfat.getValueAt(bigBlockSize.getNextXBATChainOffset());
+          nextAt = xfat.getValueAt(bigBlockSize.getXBATEntriesPerBlock());
           
           _bat_blocks.add(xfat);
        }
@@ -464,7 +464,7 @@ public class NPOIFSFileSystem extends BlockStore
      *
      * @param document the POIFSDocument being added
      */
-    void addDocument(final POIFSDocument document)
+    void addDocument(final NPOIFSDocument document)
     {
         _property_table.addProperty(document.getDocumentProperty());
     }
index 6f85c84c7193f136688473288668bf2146a102e2..36da6dc38cc0746642b678c7aa6dd74e4ab713b4 100644 (file)
@@ -310,6 +310,12 @@ public final class BATBlock extends BigBlock {
     }
     
     public int getValueAt(int relativeOffset) {
+       if(relativeOffset >= _values.length) {
+          throw new ArrayIndexOutOfBoundsException(
+                "Unable to fetch offset " + relativeOffset + " as the " + 
+                "BAT only contains " + _values.length + " entries"
+          ); 
+       }
        return _values[relativeOffset];
     }
     public void setValueAt(int relativeOffset, int value) {