SonarCube fixes - visibility of member attributes

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1771583 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2016-11-27 13:12:00 +00:00
parent 12009f09d6
commit 8968b6d6b6
21 changed files with 319 additions and 215 deletions

View File

@ -17,6 +17,8 @@
package org.apache.poi.hpsf; package org.apache.poi.hpsf;
import java.util.Arrays;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
@ -40,12 +42,15 @@ public class ClassID
public static final ClassID POWERPOINT95 = new ClassID("{EA7BAE70-FB3B-11CD-A903-00AA00510EA3}"); public static final ClassID POWERPOINT95 = new ClassID("{EA7BAE70-FB3B-11CD-A903-00AA00510EA3}");
public static final ClassID EQUATION30 = new ClassID("{0002CE02-0000-0000-C000-000000000046}"); public static final ClassID EQUATION30 = new ClassID("{0002CE02-0000-0000-C000-000000000046}");
/** <p>The number of bytes occupied by this object in the byte
* stream.</p> */
public static final int LENGTH = 16;
/** /**
* <p>The bytes making out the class ID in correct order, * <p>The bytes making out the class ID in correct order,
* i.e. big-endian.</p> * i.e. big-endian.</p>
*/ */
protected byte[] bytes; private final byte[] bytes = new byte[LENGTH];
@ -56,8 +61,7 @@ public class ClassID
* @param src The byte array to read from. * @param src The byte array to read from.
* @param offset The offset of the first byte to read. * @param offset The offset of the first byte to read.
*/ */
public ClassID(final byte[] src, final int offset) public ClassID(final byte[] src, final int offset) {
{
read(src, offset); read(src, offset);
} }
@ -66,11 +70,8 @@ public class ClassID
* <p>Creates a {@link ClassID} and initializes its value with * <p>Creates a {@link ClassID} and initializes its value with
* 0x00 bytes.</p> * 0x00 bytes.</p>
*/ */
public ClassID() public ClassID() {
{ Arrays.fill(bytes, (byte)0);
bytes = new byte[LENGTH];
for (int i = 0; i < LENGTH; i++)
bytes[i] = 0x00;
} }
@ -81,7 +82,6 @@ public class ClassID
* @param externalForm representation of the Class ID represented by this object. * @param externalForm representation of the Class ID represented by this object.
*/ */
public ClassID(String externalForm) { public ClassID(String externalForm) {
bytes = new byte[LENGTH];
String clsStr = externalForm.replaceAll("[{}-]", ""); String clsStr = externalForm.replaceAll("[{}-]", "");
for (int i=0; i<clsStr.length(); i+=2) { for (int i=0; i<clsStr.length(); i+=2) {
bytes[i/2] = (byte)Integer.parseInt(clsStr.substring(i, i+2), 16); bytes[i/2] = (byte)Integer.parseInt(clsStr.substring(i, i+2), 16);
@ -89,16 +89,11 @@ public class ClassID
} }
/** <p>The number of bytes occupied by this object in the byte
* stream.</p> */
public static final int LENGTH = 16;
/** /**
* @return The number of bytes occupied by this object in the byte * @return The number of bytes occupied by this object in the byte
* stream. * stream.
*/ */
public int length() public int length() {
{
return LENGTH; return LENGTH;
} }
@ -110,8 +105,7 @@ public class ClassID
* *
* @return the bytes making out the class ID. * @return the bytes making out the class ID.
*/ */
public byte[] getBytes() public byte[] getBytes() {
{
return bytes; return bytes;
} }
@ -123,10 +117,8 @@ public class ClassID
* @param bytes The bytes making out the class ID in big-endian format. They * @param bytes The bytes making out the class ID in big-endian format. They
* are copied without their order being changed. * are copied without their order being changed.
*/ */
public void setBytes(final byte[] bytes) public void setBytes(final byte[] bytes) {
{ System.arraycopy(bytes, 0, this.bytes, 0, LENGTH);
for (int i = 0; i < this.bytes.length; i++)
this.bytes[i] = bytes[i];
} }
@ -141,10 +133,7 @@ public class ClassID
* *
* @return A byte array containing the class ID. * @return A byte array containing the class ID.
*/ */
public byte[] read(final byte[] src, final int offset) public byte[] read(final byte[] src, final int offset) {
{
bytes = new byte[16];
/* Read double word. */ /* Read double word. */
bytes[0] = src[3 + offset]; bytes[0] = src[3 + offset];
bytes[1] = src[2 + offset]; bytes[1] = src[2 + offset];
@ -160,8 +149,7 @@ public class ClassID
bytes[7] = src[6 + offset]; bytes[7] = src[6 + offset];
/* Read 8 bytes. */ /* Read 8 bytes. */
for (int i = 8; i < 16; i++) System.arraycopy(src, 8 + offset, bytes, 8, 8);
bytes[i] = src[i + offset];
return bytes; return bytes;
} }
@ -180,13 +168,14 @@ public class ClassID
* ID 16 bytes in the byte array after the <var>offset</var> position. * ID 16 bytes in the byte array after the <var>offset</var> position.
*/ */
public void write(final byte[] dst, final int offset) public void write(final byte[] dst, final int offset)
throws ArrayStoreException throws ArrayStoreException {
{
/* Check array size: */ /* Check array size: */
if (dst.length < 16) if (dst.length < LENGTH) {
throw new ArrayStoreException throw new ArrayStoreException
("Destination byte[] must have room for at least 16 bytes, " + ("Destination byte[] must have room for at least 16 bytes, " +
"but has a length of only " + dst.length + "."); "but has a length of only " + dst.length + ".");
}
/* Write double word. */ /* Write double word. */
dst[0 + offset] = bytes[3]; dst[0 + offset] = bytes[3];
dst[1 + offset] = bytes[2]; dst[1 + offset] = bytes[2];
@ -202,8 +191,7 @@ public class ClassID
dst[7 + offset] = bytes[6]; dst[7 + offset] = bytes[6];
/* Write 8 bytes. */ /* Write 8 bytes. */
for (int i = 8; i < 16; i++) System.arraycopy(bytes, 8, dst, 8 + offset, 8);
dst[i + offset] = bytes[i];
} }
@ -217,16 +205,19 @@ public class ClassID
* <code>false</code>. * <code>false</code>.
*/ */
@Override @Override
public boolean equals(final Object o) public boolean equals(final Object o) {
{ if (o == null || !(o instanceof ClassID)) {
if (o == null || !(o instanceof ClassID))
return false; return false;
}
final ClassID cid = (ClassID) o; final ClassID cid = (ClassID) o;
if (bytes.length != cid.bytes.length) if (bytes.length != cid.bytes.length) {
return false; return false;
for (int i = 0; i < bytes.length; i++) }
if (bytes[i] != cid.bytes[i]) for (int i = 0; i < bytes.length; i++) {
if (bytes[i] != cid.bytes[i]) {
return false; return false;
}
}
return true; return true;
} }
@ -236,8 +227,7 @@ public class ClassID
* @see Object#hashCode() * @see Object#hashCode()
*/ */
@Override @Override
public int hashCode() public int hashCode() {
{
return new String(bytes, StringUtil.UTF8).hashCode(); return new String(bytes, StringUtil.UTF8).hashCode();
} }
@ -248,18 +238,16 @@ public class ClassID
* @return String representation of the Class ID represented by this object. * @return String representation of the Class ID represented by this object.
*/ */
@Override @Override
public String toString() public String toString() {
{ StringBuilder sbClassId = new StringBuilder(38);
StringBuffer sbClassId = new StringBuffer(38);
sbClassId.append('{'); sbClassId.append('{');
for (int i = 0; i < 16; i++) for (int i = 0; i < LENGTH; i++) {
{
sbClassId.append(HexDump.toHex(bytes[i])); sbClassId.append(HexDump.toHex(bytes[i]));
if (i == 3 || i == 5 || i == 7 || i == 9) if (i == 3 || i == 5 || i == 7 || i == 9) {
sbClassId.append('-'); sbClassId.append('-');
}
} }
sbClassId.append('}'); sbClassId.append('}');
return sbClassId.toString(); return sbClassId.toString();
} }
} }

View File

@ -30,35 +30,35 @@ import java.io.OutputStream;
* TODO Fix this, as it starts to go wrong on * TODO Fix this, as it starts to go wrong on
* large streams * large streams
*/ */
final class HDGFLZWCompressor { /* package */ final class HDGFLZWCompressor {
// We use 12 bit codes: // We use 12 bit codes:
// * 0-255 are real bytes // * 0-255 are real bytes
// * 256-4095 are the substring codes // * 256-4095 are the substring codes
// Java handily initialises our buffer / dictionary // Java handily initialises our buffer / dictionary
// to all zeros // to all zeros
byte[] dict = new byte[4096]; private byte[] dict = new byte[4096];
// The next block of data to be written out, minus // The next block of data to be written out, minus
// its mask byte // its mask byte
byte[] buffer = new byte[16]; private byte[] buffer = new byte[16];
// And how long it is // And how long it is
// (Un-compressed codes are 1 byte each, compressed codes // (Un-compressed codes are 1 byte each, compressed codes
// are two) // are two)
int bufferLen = 0; private int bufferLen = 0;
// The raw length of a code is limited to 4 bits + 2 // The raw length of a code is limited to 4 bits + 2
byte[] rawCode = new byte[18]; private byte[] rawCode = new byte[18];
// And how much we're using // And how much we're using
int rawCodeLen = 0; private int rawCodeLen = 0;
// How far through the input and output streams we are // How far through the input and output streams we are
int posInp = 0; private int posInp = 0;
int posOut = 0; private int posOut = 0;
// What the next mask byte to output will be // What the next mask byte to output will be
int nextMask = 0; private int nextMask = 0;
// And how many bits we've already set // And how many bits we've already set
int maskBitsSet = 0; private int maskBitsSet = 0;
public HDGFLZWCompressor() {} public HDGFLZWCompressor() {}

View File

@ -95,7 +95,7 @@ public final class Chunk {
public int getOnDiskSize() { public int getOnDiskSize() {
int size = header.getSizeInBytes() + contents.length; int size = header.getSizeInBytes() + contents.length;
if(trailer != null) { if(trailer != null) {
size += trailer.trailerData.length; size += trailer.getTrailerData().length;
} }
if(separator != null) { if(separator != null) {
size += separator.separatorData.length; size += separator.separatorData.length;

View File

@ -130,7 +130,7 @@ public final class ChunkFactory {
ChunkHeader header = ChunkHeader header =
ChunkHeader.createChunkHeader(version, data, offset); ChunkHeader.createChunkHeader(version, data, offset);
// Sanity check // Sanity check
if(header.length < 0) { if(header.getLength() < 0) {
throw new IllegalArgumentException("Found a chunk with a negative length, which isn't allowed"); throw new IllegalArgumentException("Found a chunk with a negative length, which isn't allowed");
} }
@ -144,14 +144,14 @@ public final class ChunkFactory {
"Header called for " + header.getLength() +" bytes, but that would take us past the end of the data!"); "Header called for " + header.getLength() +" bytes, but that would take us past the end of the data!");
endOfDataPos = data.length; endOfDataPos = data.length;
header.length = data.length - offset - header.getSizeInBytes(); header.setLength(data.length - offset - header.getSizeInBytes());
if(header.hasTrailer()) { if(header.hasTrailer()) {
header.length -= 8; header.setLength(header.getLength() - 8);
endOfDataPos -= 8; endOfDataPos -= 8;
} }
if(header.hasSeparator()) { if(header.hasSeparator()) {
header.length -= 4; header.setLength(header.getLength() - 4);
endOfDataPos -= 4; endOfDataPos -= 4;
} }
} }

View File

@ -25,10 +25,10 @@ import java.nio.charset.Charset;
* A chunk header * A chunk header
*/ */
public abstract class ChunkHeader { public abstract class ChunkHeader {
protected int type; private int type;
protected int id; private int id;
protected int length; private int length;
protected int unknown1; private int unknown1;
/** /**
* Creates the appropriate ChunkHeader for the Chunk Header at * Creates the appropriate ChunkHeader for the Chunk Header at
@ -42,23 +42,23 @@ public abstract class ChunkHeader {
} else { } else {
ch = new ChunkHeaderV6(); ch = new ChunkHeaderV6();
} }
ch.type = (int)LittleEndian.getUInt(data, offset + 0); ch.setType((int)LittleEndian.getUInt(data, offset + 0));
ch.id = (int)LittleEndian.getUInt(data, offset + 4); ch.setId((int)LittleEndian.getUInt(data, offset + 4));
ch.unknown1 = (int)LittleEndian.getUInt(data, offset + 8); ch.setUnknown1((int)LittleEndian.getUInt(data, offset + 8));
ch.length = (int)LittleEndian.getUInt(data, offset + 12); ch.setLength((int)LittleEndian.getUInt(data, offset + 12));
ch.unknown2 = LittleEndian.getShort(data, offset + 16); ch.setUnknown2(LittleEndian.getShort(data, offset + 16));
ch.unknown3 = LittleEndian.getUByte(data, offset + 18); ch.setUnknown3(LittleEndian.getUByte(data, offset + 18));
return ch; return ch;
} else if(documentVersion == 5 || documentVersion == 4) { } else if(documentVersion == 5 || documentVersion == 4) {
ChunkHeaderV4V5 ch = new ChunkHeaderV4V5(); ChunkHeaderV4V5 ch = new ChunkHeaderV4V5();
ch.type = LittleEndian.getShort(data, offset + 0); ch.setType(LittleEndian.getShort(data, offset + 0));
ch.id = LittleEndian.getShort(data, offset + 2); ch.setId(LittleEndian.getShort(data, offset + 2));
ch.unknown2 = LittleEndian.getUByte(data, offset + 4); ch.setUnknown2(LittleEndian.getUByte(data, offset + 4));
ch.unknown3 = LittleEndian.getUByte(data, offset + 5); ch.setUnknown3(LittleEndian.getUByte(data, offset + 5));
ch.unknown1 = LittleEndian.getShort(data, offset + 6); ch.setUnknown1(LittleEndian.getShort(data, offset + 6));
ch.length = (int)LittleEndian.getUInt(data, offset + 8); ch.setLength((int)LittleEndian.getUInt(data, offset + 8));
return ch; return ch;
} else { } else {
@ -90,6 +90,7 @@ public abstract class ChunkHeader {
public int getId() { public int getId() {
return id; return id;
} }
/** /**
* Returns the length of the trunk, excluding the length * Returns the length of the trunk, excluding the length
* of the header, trailer or separator. * of the header, trailer or separator.
@ -97,6 +98,7 @@ public abstract class ChunkHeader {
public int getLength() { public int getLength() {
return length; return length;
} }
/** /**
* Returns the type of the chunk, which affects the * Returns the type of the chunk, which affects the
* mandatory information * mandatory information
@ -104,7 +106,24 @@ public abstract class ChunkHeader {
public int getType() { public int getType() {
return type; return type;
} }
public int getUnknown1() { public int getUnknown1() {
return unknown1; return unknown1;
} }
void setType(int type) {
this.type = type;
}
void setId(int id) {
this.id = id;
}
void setLength(int length) {
this.length = length;
}
void setUnknown1(int unknown1) {
this.unknown1 = unknown1;
}
} }

View File

@ -23,30 +23,45 @@ import java.nio.charset.Charset;
* A chunk header from v11+ * A chunk header from v11+
*/ */
public final class ChunkHeaderV11 extends ChunkHeaderV6 { public final class ChunkHeaderV11 extends ChunkHeaderV6 {
/** /**
* Does the chunk have a separator? * Does the chunk have a separator?
*/ */
public boolean hasSeparator() { public boolean hasSeparator() {
// For some reason, there are two types that don't have a short unknown2 = getUnknown2();
// separator despite the flags that indicate they do short unknown3 = getUnknown3();
if(type == 0x1f || type == 0xc9) { return false; }
// If there's a trailer, there's a separator switch (getType()) {
if(hasTrailer()) { return true; } case 0x1f: case 0xc9:
// For some reason, there are two types that don't have a
// separator despite the flags that indicate they do
return false;
if(unknown2 == 2 && unknown3 == 0x55) { return true; } case 0x69:
if(unknown2 == 2 && unknown3 == 0x54 && type == 0xa9) { return true; } return true;
if(unknown2 == 2 && unknown3 == 0x54 && type == 0xaa) { return true; }
if(unknown2 == 2 && unknown3 == 0x54 && type == 0xb4) { return true; }
if(unknown2 == 2 && unknown3 == 0x54 && type == 0xb6) { return true; }
if(unknown2 == 3 && unknown3 != 0x50) { return true; }
if(type == 0x69) { return true; }
return false; case 0xa9: case 0xaa: case 0xb4: case 0xb6:
} if (unknown2 == 2 && unknown3 == 0x54) {
return true;
}
break;
@Override default:
public Charset getChunkCharset() { break;
return Charset.forName("UTF-16LE"); }
}
if (
(unknown2 == 2 && unknown3 == 0x55) ||
(unknown2 == 3 && unknown3 != 0x50)
) {
return true;
}
// If there's a trailer, there's a separator
return hasTrailer();
}
@Override
public Charset getChunkCharset() {
return Charset.forName("UTF-16LE");
}
} }

View File

@ -23,8 +23,8 @@ import java.nio.charset.Charset;
* A chunk header from v4 or v5 * A chunk header from v4 or v5
*/ */
public final class ChunkHeaderV4V5 extends ChunkHeader { public final class ChunkHeaderV4V5 extends ChunkHeader {
protected short unknown2; private short unknown2;
protected short unknown3; private short unknown3;
public short getUnknown2() { public short getUnknown2() {
return unknown2; return unknown2;
@ -61,4 +61,12 @@ public final class ChunkHeaderV4V5 extends ChunkHeader {
public Charset getChunkCharset() { public Charset getChunkCharset() {
return Charset.forName("ASCII"); return Charset.forName("ASCII");
} }
void setUnknown2(short unknown2) {
this.unknown2 = unknown2;
}
void setUnknown3(short unknown3) {
this.unknown3 = unknown3;
}
} }

View File

@ -23,8 +23,8 @@ import java.nio.charset.Charset;
* A chunk header from v6 * A chunk header from v6
*/ */
public class ChunkHeaderV6 extends ChunkHeader { public class ChunkHeaderV6 extends ChunkHeader {
protected short unknown2; private short unknown2;
protected short unknown3; private short unknown3;
public short getUnknown2() { public short getUnknown2() {
return unknown2; return unknown2;
@ -45,15 +45,15 @@ public class ChunkHeaderV6 extends ChunkHeader {
* Does the chunk have a trailer? * Does the chunk have a trailer?
*/ */
public boolean hasTrailer() { public boolean hasTrailer() {
if(unknown1 != 0 || type == 0x71 || type == 0x70) { switch (getType()) {
return true; case 0x2c: case 0x65: case 0x66: case 0x69:
} case 0x6a: case 0x6b: case 0x70: case 0x71:
if(type == 0x6b || type == 0x6a || type == 0x69 || type == 0x66 return true;
|| type == 0x65 || type == 0x2c) { default:
return true; return (getUnknown1() != 0);
} }
return false;
} }
/** /**
* Does the chunk have a separator? * Does the chunk have a separator?
*/ */
@ -66,4 +66,12 @@ public class ChunkHeaderV6 extends ChunkHeader {
public Charset getChunkCharset() { public Charset getChunkCharset() {
return Charset.forName("ASCII"); return Charset.forName("ASCII");
} }
void setUnknown2(short unknown2) {
this.unknown2 = unknown2;
}
void setUnknown3(short unknown3) {
this.unknown3 = unknown3;
}
} }

View File

@ -21,7 +21,7 @@ package org.apache.poi.hdgf.chunks;
* A trailer that follows a chunk * A trailer that follows a chunk
*/ */
public final class ChunkTrailer { public final class ChunkTrailer {
protected byte[] trailerData; private byte[] trailerData;
public ChunkTrailer(byte[] data, int offset) { public ChunkTrailer(byte[] data, int offset) {
trailerData = new byte[8]; trailerData = new byte[8];
@ -31,4 +31,8 @@ public final class ChunkTrailer {
public String toString() { public String toString() {
return "<ChunkTrailer of length " + trailerData.length + ">"; return "<ChunkTrailer of length " + trailerData.length + ">";
} }
byte[] getTrailerData() {
return trailerData;
}
} }

View File

@ -37,8 +37,8 @@ import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
public final class VSDDumper { public final class VSDDumper {
final static String tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; final static String tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
final PrintStream ps; private final PrintStream ps;
final HDGFDiagram hdgf; private final HDGFDiagram hdgf;
VSDDumper(PrintStream ps, HDGFDiagram hdgf) { VSDDumper(PrintStream ps, HDGFDiagram hdgf) {
this.ps = ps; this.ps = ps;
this.hdgf = hdgf; this.hdgf = hdgf;

View File

@ -22,11 +22,11 @@ package org.apache.poi.hdgf.pointers;
* blocks elsewhere in the file * blocks elsewhere in the file
*/ */
public abstract class Pointer { public abstract class Pointer {
protected int type; private int type;
protected int address; private int address;
protected int offset; private int offset;
protected int length; private int length;
protected short format; private short format;
public int getAddress() { public int getAddress() {
return address; return address;
@ -53,4 +53,25 @@ public abstract class Pointer {
public abstract boolean destinationHasPointers(); public abstract boolean destinationHasPointers();
public abstract boolean destinationHasChunks(); public abstract boolean destinationHasChunks();
public abstract boolean destinationCompressed(); public abstract boolean destinationCompressed();
protected void setType(int type) {
this.type = type;
}
protected void setAddress(int address) {
this.address = address;
}
protected void setOffset(int offset) {
this.offset = offset;
}
protected void setLength(int length) {
this.length = length;
}
protected void setFormat(short format) {
this.format = format;
}
protected boolean isFormatBetween(int min, int max) {
return (min <= format && format < max);
}
} }

View File

@ -38,20 +38,20 @@ public final class PointerFactory {
Pointer p; Pointer p;
if(version >= 6) { if(version >= 6) {
p = new PointerV6(); p = new PointerV6();
p.type = LittleEndian.getInt(data, offset+0); p.setType(LittleEndian.getInt(data, offset+0));
p.address = (int)LittleEndian.getUInt(data, offset+4); p.setAddress((int)LittleEndian.getUInt(data, offset+4));
p.offset = (int)LittleEndian.getUInt(data, offset+8); p.setOffset((int)LittleEndian.getUInt(data, offset+8));
p.length = (int)LittleEndian.getUInt(data, offset+12); p.setLength((int)LittleEndian.getUInt(data, offset+12));
p.format = LittleEndian.getShort(data, offset+16); p.setFormat(LittleEndian.getShort(data, offset+16));
return p; return p;
} else if(version == 5) { } else if(version == 5) {
p = new PointerV5(); p = new PointerV5();
p.type = LittleEndian.getShort(data, offset+0); p.setType(LittleEndian.getShort(data, offset+0));
p.format = LittleEndian.getShort(data, offset+2); p.setFormat(LittleEndian.getShort(data, offset+2));
p.address = (int)LittleEndian.getUInt(data, offset+4); p.setAddress((int)LittleEndian.getUInt(data, offset+4));
p.offset = (int)LittleEndian.getUInt(data, offset+8); p.setOffset((int)LittleEndian.getUInt(data, offset+8));
p.length = (int)LittleEndian.getUInt(data, offset+12); p.setLength((int)LittleEndian.getUInt(data, offset+12));
return p; return p;
} else { } else {

View File

@ -25,33 +25,34 @@ import org.apache.poi.util.LittleEndian;
public final class PointerV5 extends Pointer { public final class PointerV5 extends Pointer {
// TODO Are these getters correct? // TODO Are these getters correct?
public boolean destinationHasStrings() { public boolean destinationHasStrings() {
return (0x40 <= format && format < 0x50); return isFormatBetween(0x40, 0x50);
} }
public boolean destinationHasPointers() { public boolean destinationHasPointers() {
if(type == 20) { switch (getType()) {
return true; case 20:
return true;
case 22:
return false;
default:
return isFormatBetween(0x1d, 0x1f) || isFormatBetween(0x50, 0x60);
} }
if(type == 22) {
return false;
}
if(format == 0x1d || format == 0x1e) {
return true;
}
return (0x50 <= format && format < 0x60);
} }
public boolean destinationHasChunks() { public boolean destinationHasChunks() {
if (type == 21) { switch (getType()) {
return true; case 21:
return true;
case 24:
return true;
default:
return isFormatBetween(0xd0, 0xdf);
} }
if (type == 24) {
return true;
}
return (0xd0 <= format && format < 0xdf);
} }
public boolean destinationCompressed() { public boolean destinationCompressed() {
// Apparently, it's the second least significant bit // Apparently, it's the second least significant bit
return (format & 2) > 0; return (getFormat() & 2) > 0;
} }
/** /**
@ -63,7 +64,7 @@ public final class PointerV5 extends Pointer {
* Depends on the type only, not stored * Depends on the type only, not stored
*/ */
public int getNumPointersOffset(byte[] data) { public int getNumPointersOffset(byte[] data) {
switch (type) { switch (getType()) {
case 0x1d: case 0x1d:
case 0x4e: case 0x4e:
return 30; return 30;

View File

@ -24,20 +24,19 @@ import org.apache.poi.util.LittleEndian;
*/ */
public final class PointerV6 extends Pointer { public final class PointerV6 extends Pointer {
public boolean destinationHasStrings() { public boolean destinationHasStrings() {
return (0x40 <= format && format < 0x50); return isFormatBetween(0x40, 0x50);
} }
public boolean destinationHasPointers() { public boolean destinationHasPointers() {
if(type == 20) return true; return (getType() == 20) || isFormatBetween(0x1d, 0x1f) || isFormatBetween(0x50, 0x60);
if(format == 0x1d || format == 0x1e) return true;
return (0x50 <= format && format < 0x60);
} }
public boolean destinationHasChunks() { public boolean destinationHasChunks() {
return (0xd0 <= format && format < 0xdf); return isFormatBetween(0xd0, 0xdf);
} }
public boolean destinationCompressed() { public boolean destinationCompressed() {
// Apparently, it's the second least significant bit // Apparently, it's the second least significant bit
return (format & 2) > 0; return (getFormat() & 2) > 0;
} }
/** /**

View File

@ -42,6 +42,7 @@ public abstract class EscherPart extends HPBFPart {
new DefaultEscherRecordFactory(); new DefaultEscherRecordFactory();
ArrayList<EscherRecord> ec = new ArrayList<EscherRecord>(); ArrayList<EscherRecord> ec = new ArrayList<EscherRecord>();
byte data[] = getData();
int left = data.length; int left = data.length;
while(left > 0) { while(left > 0) {
EscherRecord er = erf.createRecord(data, 0); EscherRecord er = erf.createRecord(data, 0);
@ -68,12 +69,14 @@ public abstract class EscherPart extends HPBFPart {
size += records[i].getRecordSize(); size += records[i].getRecordSize();
} }
data = new byte[size]; byte data[] = new byte[size];
size = 0; size = 0;
for(int i=0; i<records.length; i++) { for(int i=0; i<records.length; i++) {
int thisSize = int thisSize =
records[i].serialize(size, data); records[i].serialize(size, data);
size += thisSize; size += thisSize;
} }
setData(data);
} }
} }

View File

@ -31,7 +31,7 @@ import org.apache.poi.util.IOUtils;
* for all of them. * for all of them.
*/ */
public abstract class HPBFPart { public abstract class HPBFPart {
protected byte[] data; private byte[] data;
/** /**
* @param path the path to the part, eg Contents or Quill, QuillSub, CONTENTS * @param path the path to the part, eg Contents or Quill, QuillSub, CONTENTS
*/ */
@ -94,7 +94,11 @@ public abstract class HPBFPart {
* Returns the raw data that makes up * Returns the raw data that makes up
* this document part. * this document part.
*/ */
public byte[] getData() { return data; } public final byte[] getData() { return data; }
protected final void setData(byte data[]) {
this.data = data.clone();
}
/** /**
* Returns * Returns

View File

@ -39,6 +39,7 @@ public final class QuillContents extends HPBFPart {
// Now parse the first 512 bytes, and produce // Now parse the first 512 bytes, and produce
// all our bits // all our bits
byte data[] = getData();
// Check first 8 bytes // Check first 8 bytes
String f8 = new String(data, 0, 8, LocaleUtil.CHARSET_1252); String f8 = new String(data, 0, 8, LocaleUtil.CHARSET_1252);

View File

@ -21,15 +21,15 @@ package org.apache.poi.hpbf.model.qcbits;
* Parent of all Quill CONTENTS bits * Parent of all Quill CONTENTS bits
*/ */
public abstract class QCBit { public abstract class QCBit {
protected String thingType; private String thingType;
protected String bitType; private String bitType;
protected byte[] data; private byte[] data;
protected int optA; private int optA;
protected int optB; private int optB;
protected int optC; private int optC;
protected int dataOffset; private int dataOffset;
public QCBit(String thingType, String bitType, byte[] data) { public QCBit(String thingType, String bitType, byte[] data) {
this.thingType = thingType; this.thingType = thingType;
@ -47,7 +47,10 @@ public abstract class QCBit {
* or PLC * or PLC
*/ */
public String getBitType() { return bitType; } public String getBitType() { return bitType; }
public byte[] getData() { return data; } public final byte[] getData() { return data; }
protected final void setData(byte data[]) {
this.data = data.clone();
}
public int getOptA() { public int getOptA() {
return optA; return optA;

View File

@ -26,18 +26,18 @@ import org.apache.poi.util.StringUtil;
* format is determined by the type of the PLCs. * format is determined by the type of the PLCs.
*/ */
public abstract class QCPLCBit extends QCBit { public abstract class QCPLCBit extends QCBit {
protected int numberOfPLCs; private int numberOfPLCs;
protected int typeOfPLCS; private int typeOfPLCS;
/** /**
* The data which goes before the main PLC entries. * The data which goes before the main PLC entries.
* This is apparently always made up of 2 byte * This is apparently always made up of 2 byte
* un-signed ints.. * un-signed ints..
*/ */
protected int[] preData; private int[] preData;
/** The first value of each PLC, normally 4 bytes */ /** The first value of each PLC, normally 4 bytes */
protected long[] plcValA; private long[] plcValA;
/** The second value of each PLC, normally 4 bytes */ /** The second value of each PLC, normally 4 bytes */
protected long[] plcValB; private long[] plcValB;
private QCPLCBit(String thingType, String bitType, byte[] data) { private QCPLCBit(String thingType, String bitType, byte[] data) {
@ -74,6 +74,18 @@ public abstract class QCPLCBit extends QCBit {
return plcValB; return plcValB;
} }
final void setPreData(int preData[]) {
this.preData = preData.clone();
}
final void setPlcValA(long[] plcValA) {
this.plcValA = plcValA.clone();
}
final void setPlcValB(long[] plcValB) {
this.plcValB = plcValB.clone();
}
public static QCPLCBit createQCPLCBit(String thingType, String bitType, byte[] data) { public static QCPLCBit createQCPLCBit(String thingType, String bitType, byte[] data) {
@ -103,17 +115,23 @@ public abstract class QCPLCBit extends QCBit {
super(thingType, bitType, data); super(thingType, bitType, data);
// Grab our 4x pre-data // Grab our 4x pre-data
preData = new int[4]; int preData[] = {
preData[0] = LittleEndian.getUShort(data, 8+0); LittleEndian.getUShort(data, 8+0),
preData[1] = LittleEndian.getUShort(data, 8+2); LittleEndian.getUShort(data, 8+2),
preData[2] = LittleEndian.getUShort(data, 8+4); LittleEndian.getUShort(data, 8+4),
preData[3] = LittleEndian.getUShort(data, 8+6); LittleEndian.getUShort(data, 8+6)
};
setPreData(preData);
// And grab the 2 byte values // And grab the 2 byte values
for(int i=0; i<numberOfPLCs; i++) { int cntPlcs = getNumberOfPLCs();
long plcValA[] = new long[cntPlcs], plcValB[] = new long[cntPlcs];
for(int i=0; i<cntPlcs; i++) {
plcValA[i] = LittleEndian.getUShort(data, 16+(4*i)); plcValA[i] = LittleEndian.getUShort(data, 16+(4*i));
plcValB[i] = LittleEndian.getUShort(data, 16+(4*i)+2); plcValB[i] = LittleEndian.getUShort(data, 16+(4*i)+2);
} }
setPlcValA(plcValA);
setPlcValB(plcValB);
} }
} }
@ -126,17 +144,23 @@ public abstract class QCPLCBit extends QCBit {
super(thingType, bitType, data); super(thingType, bitType, data);
// Grab our 4x pre-data // Grab our 4x pre-data
preData = new int[4]; int preData[] = {
preData[0] = LittleEndian.getUShort(data, 8+0); LittleEndian.getUShort(data, 8+0),
preData[1] = LittleEndian.getUShort(data, 8+2); LittleEndian.getUShort(data, 8+2),
preData[2] = LittleEndian.getUShort(data, 8+4); LittleEndian.getUShort(data, 8+4),
preData[3] = LittleEndian.getUShort(data, 8+6); LittleEndian.getUShort(data, 8+6)
};
setPreData(preData);
// And grab the 4 byte values // And grab the 4 byte values
for(int i=0; i<numberOfPLCs; i++) { int cntPlcs = getNumberOfPLCs();
long plcValA[] = new long[cntPlcs], plcValB[] = new long[cntPlcs];
for(int i=0; i<cntPlcs; i++) {
plcValA[i] = LittleEndian.getUInt(data, 16+(8*i)); plcValA[i] = LittleEndian.getUInt(data, 16+(8*i));
plcValB[i] = LittleEndian.getUInt(data, 16+(8*i)+4); plcValB[i] = LittleEndian.getUInt(data, 16+(8*i)+4);
} }
setPlcValA(plcValA);
setPlcValB(plcValB);
} }
} }
@ -149,20 +173,26 @@ public abstract class QCPLCBit extends QCBit {
super(thingType, bitType, data); super(thingType, bitType, data);
// Grab our 7x pre-data // Grab our 7x pre-data
preData = new int[7]; int preData[] = {
preData[0] = LittleEndian.getUShort(data, 8+0); LittleEndian.getUShort(data, 8+0),
preData[1] = LittleEndian.getUShort(data, 8+2); LittleEndian.getUShort(data, 8+2),
preData[2] = LittleEndian.getUShort(data, 8+4); LittleEndian.getUShort(data, 8+4),
preData[3] = LittleEndian.getUShort(data, 8+6); LittleEndian.getUShort(data, 8+6),
preData[4] = LittleEndian.getUShort(data, 8+8); LittleEndian.getUShort(data, 8+8),
preData[5] = LittleEndian.getUShort(data, 8+10); LittleEndian.getUShort(data, 8+10),
preData[6] = LittleEndian.getUShort(data, 8+12); LittleEndian.getUShort(data, 8+12)
};
setPreData(preData);
// And grab the 4 byte values // And grab the 4 byte values
for(int i=0; i<numberOfPLCs; i++) { int cntPlcs = getNumberOfPLCs();
long plcValA[] = new long[cntPlcs], plcValB[] = new long[cntPlcs];
for(int i=0; i<cntPlcs; i++) {
plcValA[i] = LittleEndian.getUInt(data, 22+(8*i)); plcValA[i] = LittleEndian.getUInt(data, 22+(8*i));
plcValB[i] = LittleEndian.getUInt(data, 22+(8*i)+4); plcValB[i] = LittleEndian.getUInt(data, 22+(8*i)+4);
} }
setPlcValA(plcValA);
setPlcValB(plcValB);
} }
} }
@ -183,37 +213,38 @@ public abstract class QCPLCBit extends QCBit {
private Type12(String thingType, String bitType, byte[] data) { private Type12(String thingType, String bitType, byte[] data) {
super(thingType, bitType, data); super(thingType, bitType, data);
int cntPlcs = getNumberOfPLCs();
// How many hyperlinks do we really have? // How many hyperlinks do we really have?
// (zero hyperlinks gets numberOfPLCs=1) // (zero hyperlinks gets numberOfPLCs=1)
if(data.length == 0x34) { hyperlinks = new String[data.length == 0x34 ? 0 : cntPlcs];
hyperlinks = new String[0];
} else {
hyperlinks = new String[numberOfPLCs];
}
// We have 4 bytes, then the start point of each // We have 4 bytes, then the start point of each
// hyperlink, then the end point of the text. // hyperlink, then the end point of the text.
preData = new int[1+numberOfPLCs+1]; int preData[] = new int[1+cntPlcs+1];
for(int i=0; i<preData.length; i++) { for(int i=0; i<preData.length; i++) {
preData[i] = (int)LittleEndian.getUInt(data, 8+(i*4)); preData[i] = (int)LittleEndian.getUInt(data, 8+(i*4));
} }
setPreData(preData);
// Then we have a whole bunch of stuff, which grows // Then we have a whole bunch of stuff, which grows
// with the number of hyperlinks // with the number of hyperlinks
// For now, we think these are shorts // For now, we think these are shorts
int at = 8+4+(numberOfPLCs*4)+4; int at = 8+4+(cntPlcs*4)+4;
int until = 0x34; int until = 0x34;
if(numberOfPLCs == 1 && hyperlinks.length == 1) { if(cntPlcs == 1 && hyperlinks.length == 1) {
until = oneStartsAt; until = oneStartsAt;
} else if(numberOfPLCs >= 2) { } else if(cntPlcs >= 2) {
until = twoStartsAt + (numberOfPLCs-2)*threePlusIncrement; until = twoStartsAt + (cntPlcs-2)*threePlusIncrement;
} }
plcValA = new long[(until-at)/2]; long plcValA[] = new long[(until-at)/2];
plcValB = new long[0]; long plcValB[] = new long[0];
for(int i=0; i<plcValA.length; i++) { for(int i=0; i<plcValA.length; i++) {
plcValA[i] = LittleEndian.getUShort(data, at+(i*2)); plcValA[i] = LittleEndian.getUShort(data, at+(i*2));
} }
setPlcValA(plcValA);
setPlcValB(plcValB);
// Finally, we have a series of lengths + hyperlinks // Finally, we have a series of lengths + hyperlinks
at = until; at = until;
@ -259,7 +290,7 @@ public abstract class QCPLCBit extends QCBit {
* @param number The hyperlink number, zero based * @param number The hyperlink number, zero based
*/ */
public int getTextStartAt(int number) { public int getTextStartAt(int number) {
return preData[1+number]; return getPreData()[1+number];
} }
/** /**
* Returns where in the text that this block * Returns where in the text that this block
@ -269,7 +300,7 @@ public abstract class QCPLCBit extends QCBit {
* PLCBit applies to. * PLCBit applies to.
*/ */
public int getAllTextEndAt() { public int getAllTextEndAt() {
return preData[numberOfPLCs+1]; return getPreData()[getNumberOfPLCs()+1];
} }
} }
} }

View File

@ -32,13 +32,12 @@ public final class QCTextBit extends QCBit {
* are \r and not \n * are \r and not \n
*/ */
public String getText() { public String getText() {
return StringUtil.getFromUnicodeLE( return StringUtil.getFromUnicodeLE(getData());
data, 0, data.length/2
);
} }
public void setText(String text) { public void setText(String text) {
data = new byte[text.length()*2]; byte data[] = new byte[text.length()*2];
StringUtil.putUnicodeLE(text, data, 0); StringUtil.putUnicodeLE(text, data, 0);
setData(data);
} }
} }

View File

@ -28,10 +28,10 @@ public abstract class StreamTest extends TestCase {
protected boolean hasPointers = false; protected boolean hasPointers = false;
public TestPointer(boolean compressed, int offset, int length, int type, short format) { public TestPointer(boolean compressed, int offset, int length, int type, short format) {
this.compressed = compressed; this.compressed = compressed;
this.offset = offset; setOffset(offset);
this.length = length; setLength(length);
this.type = type; setType(type);
this.format = format; setFormat(format);
} }
@Override @Override