View Javadoc
1   /*
2   Copyright (c) 2013 James Ahlborn
3   
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7   
8       http://www.apache.org/licenses/LICENSE-2.0
9   
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15  */
16  
17  package com.healthmarketscience.jackcess.util;
18  
19  import java.io.File;
20  import java.io.FileNotFoundException;
21  import java.io.FileOutputStream;
22  import java.util.Arrays;
23  
24  import com.healthmarketscience.jackcess.ColumnBuilder;
25  import com.healthmarketscience.jackcess.DataType;
26  import com.healthmarketscience.jackcess.Database;
27  import com.healthmarketscience.jackcess.Database.FileFormat;
28  import com.healthmarketscience.jackcess.Row;
29  import com.healthmarketscience.jackcess.Table;
30  import com.healthmarketscience.jackcess.TableBuilder;
31  import com.healthmarketscience.jackcess.complex.Attachment;
32  import com.healthmarketscience.jackcess.impl.ByteUtil;
33  import com.healthmarketscience.jackcess.impl.CompoundOleUtil;
34  import junit.framework.TestCase;
35  import org.apache.poi.poifs.filesystem.DocumentEntry;
36  import org.apache.poi.poifs.filesystem.DocumentInputStream;
37  import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
38  import static com.healthmarketscience.jackcess.TestUtil.*;
39  import static com.healthmarketscience.jackcess.impl.JetFormatTest.*;
40  
41  /**
42   *
43   * @author James Ahlborn
44   */
45  public class OleBlobTest extends TestCase 
46  {
47  
48    public OleBlobTest(String name) {
49      super(name);
50    }
51  
52    public void testCreateBlob() throws Exception
53    {
54      File sampleFile = new File("src/test/data/sample-input.tab");
55      String sampleFilePath = sampleFile.getAbsolutePath();
56      String sampleFileName = sampleFile.getName();
57      byte[] sampleFileBytes = toByteArray(sampleFile);
58  
59      for(FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
60        Database db = create(fileFormat);
61  
62        Table t = new TableBuilder("TestOle")
63          .addColumn(new ColumnBuilder("id", DataType.LONG))
64          .addColumn(new ColumnBuilder("ole", DataType.OLE))
65          .toTable(db);
66  
67        OleBlob blob = null;
68        try {
69          blob = new OleBlob.Builder()
70            .setSimplePackage(sampleFile)
71            .toBlob();
72          t.addRow(1, blob);
73        } finally {
74          ByteUtil.closeQuietly(blob);
75        }
76        
77        try {
78          blob = new OleBlob.Builder()
79            .setLink(sampleFile)
80            .toBlob();
81          t.addRow(2, blob);
82        } finally {
83          ByteUtil.closeQuietly(blob);
84        }
85        
86        try {
87          blob = new OleBlob.Builder()
88            .setPackagePrettyName("Text File")
89            .setPackageClassName("Text.File")
90            .setPackageTypeName("TextFile")
91            .setOtherBytes(sampleFileBytes)
92            .toBlob();
93          t.addRow(3, blob);
94        } finally {
95          ByteUtil.closeQuietly(blob);
96        }
97  
98        for(Row row : t) {
99          try {
100           blob = row.getBlob("ole");
101           OleBlob.Content content = blob.getContent();
102           assertSame(blob, content.getBlob());
103           assertSame(content, blob.getContent());
104 
105           switch(row.getInt("id")) {
106           case 1:
107             assertEquals(OleBlob.ContentType.SIMPLE_PACKAGE, content.getType());
108             OleBlob.SimplePackageContent spc = (OleBlob.SimplePackageContent)content;
109             assertEquals(sampleFilePath, spc.getFilePath());
110             assertEquals(sampleFilePath, spc.getLocalFilePath());
111             assertEquals(sampleFileName, spc.getFileName());
112             assertEquals(OleBlob.Builder.PACKAGE_PRETTY_NAME, 
113                          spc.getPrettyName());
114             assertEquals(OleBlob.Builder.PACKAGE_TYPE_NAME, 
115                          spc.getTypeName());
116             assertEquals(OleBlob.Builder.PACKAGE_TYPE_NAME, 
117                          spc.getClassName());
118             assertEquals(sampleFileBytes.length, spc.length());
119             assertTrue(Arrays.equals(sampleFileBytes, 
120                                      toByteArray(spc.getStream(), spc.length())));
121             break;
122 
123           case 2:
124             OleBlob.LinkContent lc = (OleBlob.LinkContent)content;
125             assertEquals(OleBlob.ContentType.LINK, lc.getType());
126             assertEquals(sampleFilePath, lc.getLinkPath());
127             assertEquals(sampleFilePath, lc.getFilePath());
128             assertEquals(sampleFileName, lc.getFileName());
129             assertEquals(OleBlob.Builder.PACKAGE_PRETTY_NAME, lc.getPrettyName());
130             assertEquals(OleBlob.Builder.PACKAGE_TYPE_NAME, lc.getTypeName());
131             assertEquals(OleBlob.Builder.PACKAGE_TYPE_NAME, lc.getClassName());
132             break;
133             
134           case 3:
135             OleBlob.OtherContent oc = (OleBlob.OtherContent)content;
136             assertEquals(OleBlob.ContentType.OTHER, oc.getType());
137             assertEquals("Text File", oc.getPrettyName());
138             assertEquals("Text.File", oc.getClassName());
139             assertEquals("TextFile", oc.getTypeName());
140             assertEquals(sampleFileBytes.length, oc.length());
141             assertTrue(Arrays.equals(sampleFileBytes, 
142                                      toByteArray(oc.getStream(), oc.length())));
143             break;
144           default:
145             throw new RuntimeException("unexpected id " + row);
146           }
147         } finally {
148           ByteUtil.closeQuietly(blob);
149         }
150       }
151 
152       db.close();      
153     }    
154   }
155 
156   public void testReadBlob() throws Exception
157   {
158     for(TestDB testDb : TestDB.getSupportedForBasename(Basename.BLOB, true)) {
159       Database db = open(testDb);
160 
161       Table t = db.getTable("Table1");
162 
163       for(Row row : t) {
164 
165         OleBlob oleBlob = null;
166         try {
167 
168           String name = row.getString("name");
169           oleBlob = row.getBlob("ole_data");
170           OleBlob.Content content = oleBlob.getContent();
171           Attachment attach = null;
172           if(content.getType() != OleBlob.ContentType.LINK) {
173             attach = row.getForeignKey("attach_data").getAttachments().get(0);
174           }
175 
176           switch(content.getType()) {
177           case LINK:
178             OleBlob.LinkContent lc = (OleBlob.LinkContent)content;
179             if("test_link".equals(name)) {
180               assertEquals("Z:\\jackcess_test\\ole\\test_data.txt", lc.getLinkPath());
181             } else {
182               assertEquals("Z:\\jackcess_test\\ole\\test_datau2.txt", lc.getLinkPath());
183             }
184             break;
185 
186           case SIMPLE_PACKAGE:
187             OleBlob.SimplePackageContent spc = (OleBlob.SimplePackageContent)content;
188             byte[] packageBytes = toByteArray(spc.getStream(), spc.length());
189             assertTrue(Arrays.equals(attach.getFileData(), packageBytes));
190             break;
191 
192           case COMPOUND_STORAGE:
193             OleBlob.CompoundContent cc = (OleBlob.CompoundContent)content;
194             if(cc.hasContentsEntry()) {
195               OleBlob.CompoundContent.Entry entry = cc.getContentsEntry();
196               byte[] entryBytes = toByteArray(entry.getStream(), entry.length());
197               assertTrue(Arrays.equals(attach.getFileData(), entryBytes));
198             } else {
199 
200               if("test_word.doc".equals(name)) {
201                 checkCompoundEntries(cc, 
202                                      "/%02OlePres000", 466,
203                                      "/WordDocument", 4096,
204                                      "/%05SummaryInformation", 4096,
205                                      "/%05DocumentSummaryInformation", 4096,
206                                      "/%03AccessObjSiteData", 56,
207                                      "/%02OlePres001", 1620,
208                                      "/1Table", 6380,
209                                      "/%01CompObj", 114,
210                                      "/%01Ole", 20);
211                 checkCompoundStorage(cc, attach);
212               } else if("test_excel.xls".equals(name)) {
213                 checkCompoundEntries(cc, 
214                                      "/%02OlePres000", 1326,
215                                      "/%03AccessObjSiteData", 56,
216                                      "/%05SummaryInformation", 200,
217                                      "/%05DocumentSummaryInformation", 264,
218                                      "/%02OlePres001", 4208,
219                                      "/%01CompObj", 107,
220                                      "/Workbook", 13040,
221                                      "/%01Ole", 20);
222                 // the excel data seems to be modified when embedded as ole,
223                 // so we can't reallly test it against the attachment data
224               } else {
225                 throw new RuntimeException("unexpected compound entry " + name);
226               }
227             }
228             break;
229 
230           case OTHER:
231             OleBlob.OtherContent oc = (OleBlob.OtherContent)content;
232             byte[] otherBytes = toByteArray(oc.getStream(), oc.length());
233             assertTrue(Arrays.equals(attach.getFileData(), otherBytes));
234             break;
235 
236           default:
237             throw new RuntimeException("unexpected type " + content.getType());
238           }
239 
240         } finally {
241           ByteUtil.closeQuietly(oleBlob);
242         }
243       }
244 
245       db.close();
246     } 
247   }
248 
249   private static void checkCompoundEntries(OleBlob.CompoundContent cc, 
250                                            Object... entryInfo)
251     throws Exception
252   {
253     int idx = 0;
254     for(OleBlob.CompoundContent.Entry e : cc) {
255       String entryName = (String)entryInfo[idx];
256       int entryLen = (Integer)entryInfo[idx + 1];
257 
258       assertEquals(entryName, e.getName());
259       assertEquals(entryLen, e.length());
260 
261       idx += 2;
262     }
263   }
264 
265   private static void checkCompoundStorage(OleBlob.CompoundContent cc, 
266                                            Attachment attach)
267     throws Exception
268   {
269     File tmpData = File.createTempFile("attach_", ".dat");
270 
271     try {
272       FileOutputStream fout = new FileOutputStream(tmpData);
273       fout.write(attach.getFileData());
274       fout.close();
275 
276       NPOIFSFileSystem attachFs = new NPOIFSFileSystem(tmpData, true);
277 
278       for(OleBlob.CompoundContent.Entry e : cc) {
279         DocumentEntry attachE = null;
280         try {
281           attachE = CompoundOleUtil.getDocumentEntry(e.getName(), attachFs.getRoot());
282         } catch(FileNotFoundException fnfe) {
283           // ignored, the ole data has extra entries
284           continue;
285         }
286 
287         byte[] attachEBytes = toByteArray(new DocumentInputStream(attachE), 
288                                           attachE.getSize());
289         byte[] entryBytes = toByteArray(e.getStream(), e.length());
290 
291         assertTrue(Arrays.equals(attachEBytes, entryBytes));
292       }
293 
294       ByteUtil.closeQuietly(attachFs);
295       
296     } finally {
297       tmpData.delete();
298     }    
299   }
300 }