Bugzilla 46776 - Added clone() method to MulBlankRecord to fix crash in Sheet.cloneSheet()

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@782177 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2009-06-06 00:46:41 +00:00
parent 3f7db41945
commit 190684164a
3 changed files with 127 additions and 109 deletions

View File

@ -35,6 +35,7 @@
<release version="3.5-beta7" date="2009-??-??"> <release version="3.5-beta7" date="2009-??-??">
</release> </release>
<release version="3.5-beta6" date="2009-06-11"> <release version="3.5-beta6" date="2009-06-11">
<action dev="POI-DEVELOPERS" type="fix">46776 - Added clone() method to MulBlankRecord to fix crash in Sheet.cloneSheet()</action>
<action dev="POI-DEVELOPERS" type="fix">47244 - Fixed HSSFSheet to handle missing header / footer records</action> <action dev="POI-DEVELOPERS" type="fix">47244 - Fixed HSSFSheet to handle missing header / footer records</action>
<action dev="POI-DEVELOPERS" type="fix">47312 - Fixed formula parser to properly reject cell references with a '0' row component</action> <action dev="POI-DEVELOPERS" type="fix">47312 - Fixed formula parser to properly reject cell references with a '0' row component</action>
<action dev="POI-DEVELOPERS" type="fix">47199 - Fixed PageSettingsBlock/Sheet to tolerate margin records after other non-PSB records</action> <action dev="POI-DEVELOPERS" type="fix">47199 - Fixed PageSettingsBlock/Sheet to tolerate margin records after other non-PSB records</action>

View File

@ -22,8 +22,7 @@ import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: Multiple Blank cell record(0x00BE) <P/> * Title: Multiple Blank cell record(0x00BE) <P/>
* Description: Represents a set of columns in a row with no value but with styling. * Description: Represents a set of columns in a row with no value but with styling.
* In this release we have read-only support for this record type. * <p/>
* The RecordFactory converts this to a set of BlankRecord objects.<P/>
* REFERENCE: PG 329 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P/> * REFERENCE: PG 329 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P/>
* @author Andrew C. Oliver (acoliver at apache dot org) * @author Andrew C. Oliver (acoliver at apache dot org)
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
@ -32,53 +31,38 @@ import org.apache.poi.util.LittleEndianOutput;
public final class MulBlankRecord extends StandardRecord { public final class MulBlankRecord extends StandardRecord {
public final static short sid = 0x00BE; public final static short sid = 0x00BE;
private int field_1_row; private final int _row;
private short field_2_first_col; private final int _firstCol;
private short[] field_3_xfs; private final short[] _xfs;
private short field_4_last_col; private final int _lastCol;
public MulBlankRecord(int row, int firstCol, short[] xfs) { public MulBlankRecord(int row, int firstCol, short[] xfs) {
field_1_row = row; _row = row;
field_2_first_col = (short)firstCol; _firstCol = firstCol;
field_3_xfs = xfs; _xfs = xfs;
field_4_last_col = (short) (firstCol + xfs.length - 1); _lastCol = firstCol + xfs.length - 1;
} }
/** /**
* get the row number of the cells this represents * @return the row number of the cells this represents
*
* @return row number
*/ */
public int getRow() public int getRow() {
{ return _row;
return field_1_row;
} }
/** /**
* starting column (first cell this holds in the row) * @return starting column (first cell this holds in the row). Zero based
* @return first column number
*/ */
public short getFirstColumn() public int getFirstColumn() {
{ return _firstCol;
return field_2_first_col;
}
/**
* ending column (last cell this holds in the row)
* @return first column number
*/
public short getLastColumn()
{
return field_4_last_col;
} }
/** /**
* get the number of columns this contains (last-first +1) * get the number of columns this contains (last-first +1)
* @return number of columns (last - first +1) * @return number of columns (last - first +1)
*/ */
public int getNumColumns() public int getNumColumns() {
{ return _lastCol - _firstCol + 1;
return field_4_last_col - field_2_first_col + 1;
} }
/** /**
@ -86,27 +70,24 @@ public final class MulBlankRecord extends StandardRecord {
* @param coffset the column (coffset = column - field_2_first_col) * @param coffset the column (coffset = column - field_2_first_col)
* @return the XF index for the column * @return the XF index for the column
*/ */
public short getXFAt(int coffset) public short getXFAt(int coffset) {
{ return _xfs[coffset];
return field_3_xfs[ coffset ];
} }
/** /**
* @param in the RecordInputstream to read the record from * @param in the RecordInputstream to read the record from
*/ */
public MulBlankRecord(RecordInputStream in) { public MulBlankRecord(RecordInputStream in) {
field_1_row = in.readUShort(); _row = in.readUShort();
field_2_first_col = in.readShort(); _firstCol = in.readShort();
field_3_xfs = parseXFs(in); _xfs = parseXFs(in);
field_4_last_col = in.readShort(); _lastCol = in.readShort();
} }
private static short [] parseXFs(RecordInputStream in) private static short [] parseXFs(RecordInputStream in) {
{
short[] retval = new short[(in.remaining() - 2) / 2]; short[] retval = new short[(in.remaining() - 2) / 2];
for (int idx = 0; idx < retval.length;idx++) for (int idx = 0; idx < retval.length;idx++) {
{
retval[idx] = in.readShort(); retval[idx] = in.readShort();
} }
return retval; return retval;
@ -118,7 +99,7 @@ public final class MulBlankRecord extends StandardRecord {
buffer.append("[MULBLANK]\n"); buffer.append("[MULBLANK]\n");
buffer.append("row = ").append(Integer.toHexString(getRow())).append("\n"); buffer.append("row = ").append(Integer.toHexString(getRow())).append("\n");
buffer.append("firstcol = ").append(Integer.toHexString(getFirstColumn())).append("\n"); buffer.append("firstcol = ").append(Integer.toHexString(getFirstColumn())).append("\n");
buffer.append(" lastcol = ").append(Integer.toHexString(getLastColumn())).append("\n"); buffer.append(" lastcol = ").append(Integer.toHexString(_lastCol)).append("\n");
for (int k = 0; k < getNumColumns(); k++) { for (int k = 0; k < getNumColumns(); k++) {
buffer.append("xf").append(k).append(" = ").append( buffer.append("xf").append(k).append(" = ").append(
Integer.toHexString(getXFAt(k))).append("\n"); Integer.toHexString(getXFAt(k))).append("\n");
@ -127,23 +108,28 @@ public final class MulBlankRecord extends StandardRecord {
return buffer.toString(); return buffer.toString();
} }
public short getSid() public short getSid() {
{
return sid; return sid;
} }
public void serialize(LittleEndianOutput out) { public void serialize(LittleEndianOutput out) {
out.writeShort(field_1_row); out.writeShort(_row);
out.writeShort(field_2_first_col); out.writeShort(_firstCol);
int nItems = field_3_xfs.length; int nItems = _xfs.length;
for (int i = 0; i < nItems; i++) { for (int i = 0; i < nItems; i++) {
out.writeShort(field_3_xfs[i]); out.writeShort(_xfs[i]);
} }
out.writeShort(field_4_last_col); out.writeShort(_lastCol);
} }
protected int getDataSize() { protected int getDataSize() {
// 3 short fields + array of shorts // 3 short fields + array of shorts
return 6 + field_3_xfs.length * 2; return 6 + _xfs.length * 2;
}
@Override
public Object clone() {
// immutable - so OK to return this
return this;
} }
} }

View File

@ -18,6 +18,7 @@
package org.apache.poi.hssf.model; package org.apache.poi.hssf.model;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;
@ -34,6 +35,7 @@ import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.GutsRecord; import org.apache.poi.hssf.record.GutsRecord;
import org.apache.poi.hssf.record.IndexRecord; import org.apache.poi.hssf.record.IndexRecord;
import org.apache.poi.hssf.record.MergeCellsRecord; import org.apache.poi.hssf.record.MergeCellsRecord;
import org.apache.poi.hssf.record.MulBlankRecord;
import org.apache.poi.hssf.record.NumberRecord; import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordBase; import org.apache.poi.hssf.record.RecordBase;
@ -671,4 +673,33 @@ public final class TestSheet extends TestCase {
} }
assertNotNull(cft); assertNotNull(cft);
} }
public void testCloneMulBlank_bug46776() {
Record[] recs = {
Sheet.createBOF(),
new DimensionsRecord(),
new RowRecord(1),
new MulBlankRecord(1, 3, new short[] { 0x0F, 0x0F, 0x0F, } ),
new RowRecord(2),
createWindow2Record(),
EOFRecord.instance,
};
Sheet sheet = createSheet(Arrays.asList(recs));
Sheet sheet2;
try {
sheet2 = sheet.cloneSheet();
} catch (RuntimeException e) {
if (e.getMessage().equals("The class org.apache.poi.hssf.record.MulBlankRecord needs to define a clone method")) {
throw new AssertionFailedError("Identified bug 46776");
}
throw e;
}
RecordCollector rc = new RecordCollector();
sheet2.visitContainedRecords(rc, 0);
Record[] clonedRecs = rc.getRecords();
assertEquals(recs.length+2, clonedRecs.length); // +2 for INDEX and DBCELL
}
} }