Fix for bug #42844 - Include some of the crazy continue record handling that we have in RecordFactory into HSSFEventFactory, so that we can handle when records aren't immediately followed by their continue

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@569101 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2007-08-23 18:20:39 +00:00
parent 490bdc3fe6
commit e518cdfbbc
3 changed files with 123 additions and 5 deletions

View File

@ -27,6 +27,10 @@ import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.RecordFactory; import org.apache.poi.hssf.record.RecordFactory;
import org.apache.poi.hssf.record.ContinueRecord; import org.apache.poi.hssf.record.ContinueRecord;
import org.apache.poi.hssf.record.DrawingRecord;
import org.apache.poi.hssf.record.DrawingGroupRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem;
/** /**
@ -140,11 +144,12 @@ public class HSSFEventFactory
{ {
Record rec = null; Record rec = null;
Record lastRec = null;
DrawingRecord lastDrawingRecord = new DrawingRecord();
while (in.hasNextRecord()) while (in.hasNextRecord())
{ {
in.nextRecord(); in.nextRecord();
sid = in.getSid();; sid = in.getSid();;
// //
@ -190,9 +195,34 @@ public class HSSFEventFactory
// if there is only one // if there is only one
// records, it will go here too. // records, it will go here too.
} }
else else {
{ // Normally, ContinueRecords are handled internally
throw new RecordFormatException("Records should handle ContinueRecord internally. Should not see this exception"); // However, in a few cases, there is a gap between a record at
// its Continue, so we have to handle them specially
// This logic is much like in RecordFactory.createRecords()
Record[] recs = RecordFactory.createRecord(in);
ContinueRecord crec = (ContinueRecord)recs[0];
if((lastRec instanceof ObjRecord) || (lastRec instanceof TextObjectRecord)) {
// You can have Obj records between a DrawingRecord
// and its continue!
lastDrawingRecord.processContinueRecord( crec.getData() );
// Trigger them on the drawing record, now it's complete
rec = lastDrawingRecord;
}
else if((lastRec instanceof DrawingGroupRecord)) {
((DrawingGroupRecord)lastRec).processContinueRecord(crec.getData());
// Trigger them on the drawing record, now it's complete
rec = lastRec;
}
else {
throw new RecordFormatException("Records should handle ContinueRecord internally. Should not see this exception");
}
}
// Update our tracking of the last record
lastRec = rec;
if(rec instanceof DrawingRecord) {
lastDrawingRecord = (DrawingRecord)rec;
} }
} }
if (rec != null) if (rec != null)

View File

@ -0,0 +1,88 @@
/* ====================================================================
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.hssf.eventusermodel;
import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
import org.apache.poi.hssf.eventusermodel.HSSFListener;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.ContinueRecord;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import junit.framework.TestCase;
public class TestHSSFEventFactory extends TestCase {
private String dirname;
public TestHSSFEventFactory() {
dirname = System.getProperty("HSSF.testdata.path");
}
public void testWithMissingRecords() throws Exception {
File f = new File(dirname + "/SimpleWithSkip.xls");
HSSFRequest req = new HSSFRequest();
MockHSSFListener mockListen = new MockHSSFListener();
req.addListenerForAllRecords(mockListen);
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(f));
HSSFEventFactory factory = new HSSFEventFactory();
factory.processWorkbookEvents(req, fs);
// Check we got the records
assertTrue( mockListen.records.size() > 100 );
}
public void testWithCrazyContinueRecords() throws Exception {
// Some files have crazy ordering of their continue records
// Check that we don't break on them (bug #42844)
File f = new File(dirname + "/ContinueRecordProblem.xls");
HSSFRequest req = new HSSFRequest();
MockHSSFListener mockListen = new MockHSSFListener();
req.addListenerForAllRecords(mockListen);
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(f));
HSSFEventFactory factory = new HSSFEventFactory();
factory.processWorkbookEvents(req, fs);
// Check we got the records
assertTrue( mockListen.records.size() > 100 );
// And none of them are continue ones
Record[] r = (Record[])mockListen.records.toArray(
new Record[mockListen.records.size()] );
for(int i=0; i<r.length; i++) {
assertFalse( r[i] instanceof ContinueRecord );
}
}
private static class MockHSSFListener implements HSSFListener {
private MockHSSFListener() {}
private ArrayList records = new ArrayList();
public void processRecord(Record record) {
records.add(record);
}
}
}