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:
parent
490bdc3fe6
commit
e518cdfbbc
@ -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,11 +195,36 @@ 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
|
||||||
|
// 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");
|
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)
|
||||||
{
|
{
|
||||||
userCode = req.processRecord(rec);
|
userCode = req.processRecord(rec);
|
||||||
|
BIN
src/testcases/org/apache/poi/hssf/data/ContinueRecordProblem.xls
Normal file
BIN
src/testcases/org/apache/poi/hssf/data/ContinueRecordProblem.xls
Normal file
Binary file not shown.
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user