Fix for bug introduced in r745976. EscherContainerRecord shouldn't hand out it's private 'child records' field.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@746018 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2009-02-19 22:02:14 +00:00
parent 3e6f2bbf80
commit 8a77c05b99
3 changed files with 103 additions and 68 deletions

View File

@ -34,8 +34,7 @@ import java.io.PrintWriter;
* *
* @author Glen Stampoultzis * @author Glen Stampoultzis
*/ */
public class EscherContainerRecord extends EscherRecord public final class EscherContainerRecord extends EscherRecord {
{
public static final short DGG_CONTAINER = (short)0xF000; public static final short DGG_CONTAINER = (short)0xF000;
public static final short BSTORE_CONTAINER = (short)0xF001; public static final short BSTORE_CONTAINER = (short)0xF001;
public static final short DG_CONTAINER = (short)0xF002; public static final short DG_CONTAINER = (short)0xF002;
@ -57,7 +56,7 @@ public class EscherContainerRecord extends EscherRecord
bytesWritten += childBytesWritten; bytesWritten += childBytesWritten;
offset += childBytesWritten; offset += childBytesWritten;
bytesRemaining -= childBytesWritten; bytesRemaining -= childBytesWritten;
getChildRecords().add( child ); addChildRecord(child);
if (offset >= data.length && bytesRemaining > 0) if (offset >= data.length && bytesRemaining > 0)
{ {
System.out.println("WARNING: " + bytesRemaining + " bytes remaining but no space left"); System.out.println("WARNING: " + bytesRemaining + " bytes remaining but no space left");
@ -73,16 +72,16 @@ public class EscherContainerRecord extends EscherRecord
LittleEndian.putShort(data, offset, getOptions()); LittleEndian.putShort(data, offset, getOptions());
LittleEndian.putShort(data, offset+2, getRecordId()); LittleEndian.putShort(data, offset+2, getRecordId());
int remainingBytes = 0; int remainingBytes = 0;
for ( Iterator iterator = getChildRecords().iterator(); iterator.hasNext(); ) Iterator<EscherRecord> iterator = _childRecords.iterator();
{ while (iterator.hasNext()) {
EscherRecord r = (EscherRecord) iterator.next(); EscherRecord r = iterator.next();
remainingBytes += r.getRecordSize(); remainingBytes += r.getRecordSize();
} }
LittleEndian.putInt(data, offset+4, remainingBytes); LittleEndian.putInt(data, offset+4, remainingBytes);
int pos = offset+8; int pos = offset+8;
for ( Iterator iterator = getChildRecords().iterator(); iterator.hasNext(); ) iterator = _childRecords.iterator();
{ while (iterator.hasNext()) {
EscherRecord r = (EscherRecord) iterator.next(); EscherRecord r = iterator.next();
pos += r.serialize(pos, data, listener ); pos += r.serialize(pos, data, listener );
} }
@ -90,12 +89,11 @@ public class EscherContainerRecord extends EscherRecord
return pos - offset; return pos - offset;
} }
public int getRecordSize() public int getRecordSize() {
{
int childRecordsSize = 0; int childRecordsSize = 0;
for ( Iterator iterator = getChildRecords().iterator(); iterator.hasNext(); ) Iterator<EscherRecord> iterator = _childRecords.iterator();
{ while (iterator.hasNext()) {
EscherRecord r = (EscherRecord) iterator.next(); EscherRecord r = iterator.next();
childRecordsSize += r.getRecordSize(); childRecordsSize += r.getRecordSize();
} }
return 8 + childRecordsSize; return 8 + childRecordsSize;
@ -106,46 +104,51 @@ public class EscherContainerRecord extends EscherRecord
* given recordId? * given recordId?
*/ */
public boolean hasChildOfType(short recordId) { public boolean hasChildOfType(short recordId) {
for ( Iterator iterator = getChildRecords().iterator(); iterator.hasNext(); ) Iterator<EscherRecord> iterator = _childRecords.iterator();
{ while (iterator.hasNext()) {
EscherRecord r = (EscherRecord) iterator.next(); EscherRecord r = iterator.next();
if(r.getRecordId() == recordId) { if(r.getRecordId() == recordId) {
return true; return true;
} }
} }
return false; return false;
} }
/** /**
* Returns a list of all the child (escher) records * @return a copy of the list of all the child records of the container.
* of the container.
*/ */
public List<EscherRecord> getChildRecords() { public List<EscherRecord> getChildRecords() {
return _childRecords; return new ArrayList<EscherRecord>(_childRecords);
} }
/**
* replaces the internal child list with the contents of the supplied <tt>childRecords</tt>
*/
public void setChildRecords(List<EscherRecord> childRecords) {
if (childRecords == _childRecords) {
throw new IllegalStateException("Child records private data member has escaped");
}
_childRecords.clear();
_childRecords.addAll(childRecords);
}
/** /**
* Returns all of our children which are also * Returns all of our children which are also
* EscherContainers (may be 0, 1, or vary rarely * EscherContainers (may be 0, 1, or vary rarely
* 2 or 3) * 2 or 3)
*/ */
public List getChildContainers() { public List<EscherContainerRecord> getChildContainers() {
List containers = new ArrayList(); List<EscherContainerRecord> containers = new ArrayList<EscherContainerRecord>();
for ( Iterator iterator = getChildRecords().iterator(); iterator.hasNext(); ) Iterator<EscherRecord> iterator = _childRecords.iterator();
{ while (iterator.hasNext()) {
EscherRecord r = (EscherRecord) iterator.next(); EscherRecord r = iterator.next();
if(r instanceof EscherContainerRecord) { if(r instanceof EscherContainerRecord) {
containers.add(r); containers.add((EscherContainerRecord) r);
} }
} }
return containers; return containers;
} }
public void setChildRecords(List<EscherRecord> childRecords) {
_childRecords.clear();
_childRecords.addAll(childRecords);
}
public String getRecordName() { public String getRecordName() {
switch (getRecordId()) { switch (getRecordId()) {
case DGG_CONTAINER: case DGG_CONTAINER:
@ -165,13 +168,12 @@ public class EscherContainerRecord extends EscherRecord
} }
} }
public void display( PrintWriter w, int indent ) public void display(PrintWriter w, int indent) {
{ super.display(w, indent);
super.display( w, indent ); for (Iterator<EscherRecord> iterator = _childRecords.iterator(); iterator.hasNext();)
for (Iterator iterator = _childRecords.iterator(); iterator.hasNext();)
{ {
EscherRecord escherRecord = (EscherRecord) iterator.next(); EscherRecord escherRecord = iterator.next();
escherRecord.display( w, indent + 1 ); escherRecord.display(w, indent + 1);
} }
} }
@ -188,16 +190,15 @@ public class EscherContainerRecord extends EscherRecord
String nl = System.getProperty( "line.separator" ); String nl = System.getProperty( "line.separator" );
StringBuffer children = new StringBuffer(); StringBuffer children = new StringBuffer();
if ( getChildRecords().size() > 0 ) if (_childRecords.size() > 0) {
{
children.append( " children: " + nl ); children.append( " children: " + nl );
int count = 0; int count = 0;
for ( Iterator iterator = getChildRecords().iterator(); iterator.hasNext(); ) for ( Iterator<EscherRecord> iterator = _childRecords.iterator(); iterator.hasNext(); )
{ {
String newIndent = indent + " "; String newIndent = indent + " ";
EscherRecord record = (EscherRecord) iterator.next(); EscherRecord record = iterator.next();
children.append(newIndent + "Child " + count + ":" + nl); children.append(newIndent + "Child " + count + ":" + nl);
if(record instanceof EscherContainerRecord) { if(record instanceof EscherContainerRecord) {
@ -215,18 +216,17 @@ public class EscherContainerRecord extends EscherRecord
indent + " isContainer: " + isContainerRecord() + nl + indent + " isContainer: " + isContainerRecord() + nl +
indent + " options: 0x" + HexDump.toHex( getOptions() ) + nl + indent + " options: 0x" + HexDump.toHex( getOptions() ) + nl +
indent + " recordId: 0x" + HexDump.toHex( getRecordId() ) + nl + indent + " recordId: 0x" + HexDump.toHex( getRecordId() ) + nl +
indent + " numchildren: " + getChildRecords().size() + nl + indent + " numchildren: " + _childRecords.size() + nl +
indent + children.toString(); indent + children.toString();
} }
public EscherSpRecord getChildById( short recordId ) public EscherSpRecord getChildById(short recordId) {
{ Iterator<EscherRecord> iterator = _childRecords.iterator();
for ( Iterator iterator = _childRecords.iterator(); iterator.hasNext(); ) while (iterator.hasNext()) {
{ EscherRecord r = iterator.next();
EscherRecord escherRecord = (EscherRecord) iterator.next(); if (r.getRecordId() == recordId)
if (escherRecord.getRecordId() == recordId) return (EscherSpRecord) r;
return (EscherSpRecord) escherRecord;
} }
return null; return null;
} }
@ -236,15 +236,15 @@ public class EscherContainerRecord extends EscherRecord
* *
* @param out - list to store found records * @param out - list to store found records
*/ */
public void getRecordsById(short recordId, List out){ public void getRecordsById(short recordId, List<EscherRecord> out){
for(Iterator it = _childRecords.iterator(); it.hasNext();) { Iterator<EscherRecord> iterator = _childRecords.iterator();
Object er = it.next(); while (iterator.hasNext()) {
EscherRecord r = (EscherRecord)er; EscherRecord r = iterator.next();
if(r instanceof EscherContainerRecord) { if(r instanceof EscherContainerRecord) {
EscherContainerRecord c = (EscherContainerRecord)r; EscherContainerRecord c = (EscherContainerRecord)r;
c.getRecordsById(recordId, out ); c.getRecordsById(recordId, out );
} else if (r.getRecordId() == recordId){ } else if (r.getRecordId() == recordId){
out.add(er); out.add(r);
} }
} }
} }

View File

@ -83,7 +83,7 @@ public final class MovieShape extends Picture {
EscherClientDataRecord cldata = new EscherClientDataRecord(); EscherClientDataRecord cldata = new EscherClientDataRecord();
cldata.setOptions((short)0xF); cldata.setOptions((short)0xF);
_escherContainer.getChildRecords().add(cldata); _escherContainer.addChildRecord(cldata);
OEShapeAtom oe = new OEShapeAtom(); OEShapeAtom oe = new OEShapeAtom();
InteractiveInfo info = new InteractiveInfo(); InteractiveInfo info = new InteractiveInfo();

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
@ -20,14 +19,17 @@ package org.apache.poi.ddf;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.util.List;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.util.HexRead; import org.apache.poi.util.HexRead;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
public class TestEscherContainerRecord extends TestCase /**
{ * Tests for {@link EscherContainerRecord}
*/
public final class TestEscherContainerRecord extends TestCase {
private String ESCHER_DATA_PATH; private String ESCHER_DATA_PATH;
protected void setUp() { protected void setUp() {
@ -129,17 +131,18 @@ public class TestEscherContainerRecord extends TestCase
" properties:" + nl; " properties:" + nl;
assertEquals( expected, r.toString() ); assertEquals( expected, r.toString() );
} }
private static final class DummyEscherRecord extends EscherRecord {
public DummyEscherRecord() { }
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) { return 0; }
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) { return 0; }
public int getRecordSize() { return 10; }
public String getRecordName() { return ""; }
}
public void testGetRecordSize() { public void testGetRecordSize() {
EscherContainerRecord r = new EscherContainerRecord(); EscherContainerRecord r = new EscherContainerRecord();
r.addChildRecord(new EscherRecord() r.addChildRecord(new DummyEscherRecord());
{
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) { return 0; }
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) { return 0; }
public int getRecordSize() { return 10; }
public String getRecordName() { return ""; }
} );
assertEquals(18, r.getRecordSize()); assertEquals(18, r.getRecordSize());
} }
@ -158,4 +161,36 @@ public class TestEscherContainerRecord extends TestCase
EscherContainerRecord record = new EscherContainerRecord(); EscherContainerRecord record = new EscherContainerRecord();
record.fillFields(data, 0, new DefaultEscherRecordFactory()); record.fillFields(data, 0, new DefaultEscherRecordFactory());
} }
/**
* Ensure {@link EscherContainerRecord} doesn't spill its guts everywhere
*/
public void testChildren() {
EscherContainerRecord ecr = new EscherContainerRecord();
List<EscherRecord> children0 = ecr.getChildRecords();
assertEquals(0, children0.size());
EscherRecord chA = new DummyEscherRecord();
EscherRecord chB = new DummyEscherRecord();
EscherRecord chC = new DummyEscherRecord();
ecr.addChildRecord(chA);
ecr.addChildRecord(chB);
children0.add(chC);
List<EscherRecord> children1 = ecr.getChildRecords();
assertTrue(children0 != children1);
assertEquals(2, children1.size());
assertEquals(chA, children1.get(0));
assertEquals(chB, children1.get(1));
assertEquals(1, children0.size()); // first copy unchanged
ecr.setChildRecords(children0);
ecr.addChildRecord(chA);
List<EscherRecord> children2 = ecr.getChildRecords();
assertEquals(2, children2.size());
assertEquals(chC, children2.get(0));
assertEquals(chA, children2.get(1));
}
} }