Various changes. SST refactoring which I'm not sure is worth it because I'm pretty sure SST recordsize calculation is all wrong. Added some logging stuff and also merged some stuff from 1.5 branch
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@352701 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
502509ea2d
commit
511dbc0cea
@ -11,7 +11,15 @@
|
||||
<person id="NKB" name="Nicola Ken Barozzi" email="barozzi@nicolaken.com"/>
|
||||
<person id="POI-DEVELOPERS" name="Poi Developers" email="poi-dev@jakarta.apache.org"/>
|
||||
</devs>
|
||||
<release version="1.5" date="Coming Soon">
|
||||
<release version="1.6-dev" date="Unrelease">
|
||||
<action dev="NKB" type="update">Removed runtime dependency on commonds logging.</action>
|
||||
<action dev="POI-DEVELOPERS" type="update">Formula support</action>
|
||||
</release>
|
||||
<release version="1.5.1" date="16 June 2002">
|
||||
<action dev="GJS" type="update">Removed depedency on commons logging. Now define poi.logging system property to enable logging to standard out.</action>
|
||||
<action dev="GJS" type="fix">Fixed SST string handling so that spreadsheets with rich text or extended text will be read correctly.</action>
|
||||
</release>
|
||||
<release version="1.5" date="06 May 2002">
|
||||
<action dev="NKB" type="update">New project build.</action>
|
||||
<action dev="NKB" type="update">New project documentation system based on Cocoon.</action>
|
||||
<action dev="POI-DEVELOPERS" type="update">Package rename</action>
|
||||
|
@ -13,7 +13,7 @@
|
||||
<section title="How to use the HSSF prototype API">
|
||||
|
||||
<section title="Capabilities">
|
||||
<p>This release of the how-to outlines functionality for the 1.5 release.
|
||||
<p>This release of the how-to outlines functionality for the CVS HEAD.
|
||||
Those looking for information on previous releases should
|
||||
look in the documentation distributed with that release.</p>
|
||||
<p>
|
||||
@ -398,55 +398,32 @@ export CLASSPATH=$CLASSPATH:$HSSFDIR/hssf.jar:$HSSFDIR/poi-poifs.jar:$HSSFDIR/po
|
||||
<ul>
|
||||
<li>Type:
|
||||
<code>java org.apache.poi.hssf.dev.HSSF ~/input.xls output.xls</code>
|
||||
<p>
|
||||
<br/>
|
||||
<br/>
|
||||
This is the read/write/modify test. It reads in the spreadsheet, modifies a cell, and writes it back out.
|
||||
Failing this test is not necessarily a bad thing. If HSSF tries to modify a non-existant sheet then this will
|
||||
most likely fail. No big deal. </p></li>
|
||||
most likely fail. No big deal. </li>
|
||||
</ul>
|
||||
</section>
|
||||
<section title="HSSF Logging facility">
|
||||
<p>HSSF now has a logging facility (using
|
||||
<link href="http://jakarta.apache.org/commons/logging.html">commons logging</link>)
|
||||
that will record massive amounts of debugging information. Its mostly
|
||||
useful to us hssf-developing geeks, but might be useful in tracking
|
||||
down problems.
|
||||
</p>
|
||||
<p>So Why use commons logging rather than log4j? Well the following discussion from
|
||||
the jakarta-general mailing list sums it up pretty well. (Thanks Morgan)
|
||||
</p>
|
||||
<p><em>Here's the problem, as I see it.</em>
|
||||
</p>
|
||||
<p><em>Suppose Commons component A decides to adopt Log4J, Commons component B
|
||||
decides to adopt LogKit, and Commons component C adopts JDK1.4 logging.
|
||||
They will all minimally function with the right jars in the classpath.
|
||||
However you (the end-user) are left with maintaining configuration for 3
|
||||
different logging APIs, which is tedious at best. When you take into
|
||||
account cool features like variable log levels, Log4J appenders and the
|
||||
like, you're pretty much guaranteed to swallow up useful configuration
|
||||
options because sophisticated configurations are too difficult to maintain
|
||||
over mutiple logging implementations.</em>
|
||||
</p>
|
||||
<p>
|
||||
<em>Contrarily, if all three Commons components use a logging facade, you can
|
||||
focus all your configuration efforts on one logging implementation. Sure,
|
||||
there is a trade-off; you don't have access to all the features, and the
|
||||
interface between the facade and the implementation must be maintained. But
|
||||
the benefits are not just political; they potentially make the end-users
|
||||
configuration much easier.</em>
|
||||
</p>
|
||||
<p><em>Even if all Commons components used the same logging implementation (Log4J
|
||||
for example), other projects in Jakarta-land may choose otherwise. If you
|
||||
add enough Jakarta projects to your environment, you eventually end up with
|
||||
the scenario described above. It's a worthwhile effort to attempt a logging
|
||||
solution that plays well with the Jakarta community at large. I think in
|
||||
many cases the Commons Logging component can fill that role.</em>
|
||||
</p>
|
||||
<p>
|
||||
Refer to the commons logging package level javadoc for more information concerning how to
|
||||
<link href="http://jakarta.apache.org/commons/logging/api/index.html">configure commons logging.</link>
|
||||
</p>
|
||||
<section title="Logging facility">
|
||||
<p>Poi can dynamically select it's logging implementation. Poi trys to
|
||||
create a logger using the System property named "org.apache.poi.util.POILogger".
|
||||
Out of the box this can be set to one of three values:
|
||||
</p>
|
||||
<ul>
|
||||
<li>org.apache.poi.util.CommonsLogger</li>
|
||||
<li>org.apache.poi.util.NullLogger</li>
|
||||
<li>org.apache.poi.util.SystemOutLogger</li>
|
||||
</ul>
|
||||
<p>
|
||||
If the property is not defined or points to an invalid classthen the NullLogger is used.
|
||||
</p>
|
||||
<p>
|
||||
Refer to the commons logging package level javadoc for more information concerning how to
|
||||
<link href="http://jakarta.apache.org/commons/logging/api/index.html">configure commons logging.</link>
|
||||
</p>
|
||||
</section>
|
||||
<section title="HSSF Developer's tools">
|
||||
<section title="HSSF Developer's Tools">
|
||||
|
||||
<p>HSSF has a number of tools useful for developers to debug/develop
|
||||
stuff using HSSF (and more generally XLS files). We've already
|
||||
|
@ -158,45 +158,3 @@ class RecordProcessor
|
||||
}
|
||||
}
|
||||
|
||||
class SSTRecordHeader
|
||||
{
|
||||
int numStrings;
|
||||
int numUniqueStrings;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public SSTRecordHeader( int numStrings, int numUniqueStrings )
|
||||
{
|
||||
this.numStrings = numStrings;
|
||||
this.numUniqueStrings = numUniqueStrings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes out the SST record. This consists of the sid, the record size, the number of
|
||||
* strings and the number of unique strings.
|
||||
*
|
||||
* @param data The data buffer to write the header to.
|
||||
* @param bufferIndex The index into the data buffer where the header should be written.
|
||||
* @param recSize The number of records written.
|
||||
*
|
||||
* @return The bufer of bytes modified.
|
||||
*/
|
||||
public int writeSSTHeader( byte[] data, int bufferIndex, int recSize )
|
||||
{
|
||||
int offset = bufferIndex;
|
||||
|
||||
LittleEndian.putShort( data, offset, SSTRecord.sid );
|
||||
offset += LittleEndianConsts.SHORT_SIZE;
|
||||
LittleEndian.putShort( data, offset, (short) ( recSize ) );
|
||||
offset += LittleEndianConsts.SHORT_SIZE;
|
||||
// LittleEndian.putInt( data, offset, getNumStrings() );
|
||||
LittleEndian.putInt( data, offset, numStrings );
|
||||
offset += LittleEndianConsts.INT_SIZE;
|
||||
// LittleEndian.putInt( data, offset, getNumUniqueStrings() );
|
||||
LittleEndian.putInt( data, offset, numUniqueStrings );
|
||||
offset += LittleEndianConsts.INT_SIZE;
|
||||
return offset - bufferIndex;
|
||||
}
|
||||
|
||||
}
|
103
src/java/org/apache/poi/hssf/record/SSTRecordHeader.java
Normal file
103
src/java/org/apache/poi/hssf/record/SSTRecordHeader.java
Normal file
@ -0,0 +1,103 @@
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache POI" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache POI", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*/
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
|
||||
/**
|
||||
* Write out an SST header record.
|
||||
*
|
||||
* @author Glen Stampoultzis (glens at apache.org)
|
||||
*/
|
||||
class SSTRecordHeader
|
||||
{
|
||||
int numStrings;
|
||||
int numUniqueStrings;
|
||||
|
||||
public SSTRecordHeader( int numStrings, int numUniqueStrings )
|
||||
{
|
||||
this.numStrings = numStrings;
|
||||
this.numUniqueStrings = numUniqueStrings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes out the SST record. This consists of the sid, the record size, the number of
|
||||
* strings and the number of unique strings.
|
||||
*
|
||||
* @param data The data buffer to write the header to.
|
||||
* @param bufferIndex The index into the data buffer where the header should be written.
|
||||
* @param recSize The number of records written.
|
||||
*
|
||||
* @return The bufer of bytes modified.
|
||||
*/
|
||||
public int writeSSTHeader( byte[] data, int bufferIndex, int recSize )
|
||||
{
|
||||
int offset = bufferIndex;
|
||||
|
||||
LittleEndian.putShort( data, offset, SSTRecord.sid );
|
||||
offset += LittleEndianConsts.SHORT_SIZE;
|
||||
LittleEndian.putShort( data, offset, (short) ( recSize ) );
|
||||
offset += LittleEndianConsts.SHORT_SIZE;
|
||||
// LittleEndian.putInt( data, offset, getNumStrings() );
|
||||
LittleEndian.putInt( data, offset, numStrings );
|
||||
offset += LittleEndianConsts.INT_SIZE;
|
||||
// LittleEndian.putInt( data, offset, getNumUniqueStrings() );
|
||||
LittleEndian.putInt( data, offset, numUniqueStrings );
|
||||
offset += LittleEndianConsts.INT_SIZE;
|
||||
return offset - bufferIndex;
|
||||
}
|
||||
|
||||
}
|
259
src/java/org/apache/poi/hssf/record/SSTRecordSizeCalculator.java
Normal file
259
src/java/org/apache/poi/hssf/record/SSTRecordSizeCalculator.java
Normal file
@ -0,0 +1,259 @@
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache POI" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache POI", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*/
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Used to calculate the record sizes for a particular record.
|
||||
*
|
||||
* @author Glen Stampoultzis (glens at apache.org)
|
||||
*/
|
||||
class SSTRecordSizeCalculator
|
||||
{
|
||||
private SSTSerializer serializer;
|
||||
|
||||
private UnicodeString unistr = null;
|
||||
private int stringReminant = 0;
|
||||
private int unipos = 0;
|
||||
/** Is there any more string to be written? */
|
||||
private boolean isRemainingString = false;
|
||||
private int totalBytesWritten = 0;
|
||||
private boolean finished = false;
|
||||
private boolean firstRecord = true;
|
||||
private int totalWritten = 0;
|
||||
private int recordSize = 0;
|
||||
private int pos = 0;
|
||||
|
||||
public SSTRecordSizeCalculator(SSTSerializer serializer)
|
||||
{
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the size in bytes of the SST record. This will include continue
|
||||
* records.
|
||||
*
|
||||
* @return the size of the SST record.
|
||||
*/
|
||||
public int getRecordSize()
|
||||
{
|
||||
initVars();
|
||||
|
||||
serializer.recordLengths = new ArrayList();
|
||||
int retval = 0;
|
||||
int totalStringSpaceRequired = serializer.calculateUnicodeSize();
|
||||
|
||||
if ( totalStringSpaceRequired > SSTRecord.MAX_DATA_SPACE )
|
||||
{
|
||||
retval = sizeOverContinuation( totalStringSpaceRequired );
|
||||
}
|
||||
else
|
||||
{
|
||||
// short data: write one simple SST record
|
||||
retval = SSTRecord.SST_RECORD_OVERHEAD + totalStringSpaceRequired;
|
||||
serializer.recordLengths.add( new Integer( totalStringSpaceRequired ) );
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
private int sizeOverContinuation( int totalStringSpaceRequired )
|
||||
{
|
||||
int retval;
|
||||
|
||||
while ( !finished )
|
||||
{
|
||||
recordSize = 0;
|
||||
pos = 0;
|
||||
|
||||
if ( firstRecord )
|
||||
{
|
||||
addMaxLengthRecordSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// writing continue record
|
||||
pos = 0;
|
||||
int toBeWritten = ( totalStringSpaceRequired - totalBytesWritten ) + ( isRemainingString ? 1 : 0 );
|
||||
int size = Math.min( SSTRecord.MAX_RECORD_SIZE - SSTRecord.STD_RECORD_OVERHEAD, toBeWritten );
|
||||
|
||||
if ( size == toBeWritten )
|
||||
{
|
||||
finished = true;
|
||||
}
|
||||
recordSize = size + SSTRecord.STD_RECORD_OVERHEAD;
|
||||
serializer.recordLengths.add( new Integer( size ) );
|
||||
pos = 4;
|
||||
}
|
||||
if ( isRemainingString )
|
||||
{
|
||||
calcReminant();
|
||||
}
|
||||
calcRemainingStrings();
|
||||
totalWritten += recordSize;
|
||||
}
|
||||
retval = totalWritten;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
private void addMaxLengthRecordSize()
|
||||
{
|
||||
// writing SST record
|
||||
recordSize = SSTRecord.MAX_RECORD_SIZE;
|
||||
pos = 12;
|
||||
firstRecord = false;
|
||||
serializer.recordLengths.add( new Integer( recordSize - SSTRecord.STD_RECORD_OVERHEAD ) );
|
||||
}
|
||||
|
||||
private void calcRemainingStrings()
|
||||
{
|
||||
for ( ; unipos < serializer.strings.size(); unipos++ )
|
||||
{
|
||||
int available = SSTRecord.MAX_RECORD_SIZE - pos;
|
||||
Integer intunipos = new Integer( unipos );
|
||||
|
||||
unistr = ( (UnicodeString) serializer.strings.get( intunipos ) );
|
||||
if ( unistr.getRecordSize() <= available )
|
||||
{
|
||||
totalBytesWritten += unistr.getRecordSize();
|
||||
pos += unistr.getRecordSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( available >= SSTRecord.STRING_MINIMAL_OVERHEAD )
|
||||
{
|
||||
int toBeWritten =
|
||||
unistr.maxBrokenLength( available );
|
||||
|
||||
totalBytesWritten += toBeWritten;
|
||||
stringReminant =
|
||||
( unistr.getRecordSize() - toBeWritten )
|
||||
+ LittleEndianConsts.BYTE_SIZE;
|
||||
if ( available != toBeWritten )
|
||||
{
|
||||
int shortrecord = recordSize
|
||||
- ( available - toBeWritten );
|
||||
|
||||
serializer.recordLengths.set(
|
||||
serializer.recordLengths.size() - 1,
|
||||
new Integer(
|
||||
shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) );
|
||||
recordSize = shortrecord;
|
||||
}
|
||||
isRemainingString = true;
|
||||
unipos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int shortrecord = recordSize - available;
|
||||
|
||||
serializer.recordLengths.set( serializer.recordLengths.size() - 1,
|
||||
new Integer( shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) );
|
||||
recordSize = shortrecord;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void calcReminant()
|
||||
{
|
||||
int available = SSTRecord.MAX_RECORD_SIZE - pos;
|
||||
|
||||
if ( stringReminant <= available )
|
||||
{
|
||||
|
||||
// write reminant
|
||||
totalBytesWritten += stringReminant - 1;
|
||||
pos += stringReminant;
|
||||
isRemainingString = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// write as much of the remnant as possible
|
||||
int toBeWritten = unistr.maxBrokenLength( available );
|
||||
|
||||
if ( available != toBeWritten )
|
||||
{
|
||||
int shortrecord = recordSize - ( available - toBeWritten );
|
||||
serializer.recordLengths.set( serializer.recordLengths.size() - 1,
|
||||
new Integer( shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) );
|
||||
recordSize = shortrecord;
|
||||
}
|
||||
totalBytesWritten += toBeWritten - 1;
|
||||
pos += toBeWritten;
|
||||
stringReminant -= toBeWritten - 1;
|
||||
isRemainingString = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void initVars()
|
||||
{
|
||||
unistr = null;
|
||||
stringReminant = 0;
|
||||
unipos = 0;
|
||||
isRemainingString = false;
|
||||
totalBytesWritten = 0;
|
||||
finished = false;
|
||||
firstRecord = true;
|
||||
totalWritten = 0;
|
||||
}
|
||||
|
||||
}
|
@ -55,10 +55,8 @@
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.util.BinaryTree;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This class handles serialization of SST records. It utilizes the record processor
|
||||
@ -69,8 +67,10 @@ import java.util.ArrayList;
|
||||
class SSTSerializer
|
||||
{
|
||||
|
||||
private List recordLengths;
|
||||
private BinaryTree strings;
|
||||
// todo: make private again
|
||||
List recordLengths;
|
||||
BinaryTree strings;
|
||||
|
||||
private int numStrings;
|
||||
private int numUniqueStrings;
|
||||
private SSTRecordHeader sstRecordHeader;
|
||||
@ -81,7 +81,7 @@ class SSTSerializer
|
||||
this.strings = strings;
|
||||
this.numStrings = numStrings;
|
||||
this.numUniqueStrings = numUniqueStrings;
|
||||
this.sstRecordHeader = new SSTRecordHeader(numStrings, numUniqueStrings);
|
||||
this.sstRecordHeader = new SSTRecordHeader( numStrings, numUniqueStrings );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,166 +107,25 @@ class SSTSerializer
|
||||
return record_size;
|
||||
}
|
||||
|
||||
private int calculateUnicodeSize()
|
||||
|
||||
|
||||
// todo: make private again
|
||||
/**
|
||||
* Calculates the total unicode size for all the strings.
|
||||
*
|
||||
* @return the total size.
|
||||
*/
|
||||
int calculateUnicodeSize()
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
for ( int k = 0; k < strings.size(); k++ )
|
||||
{
|
||||
retval += getUnicodeString(k).getRecordSize();
|
||||
retval += getUnicodeString( k ).getRecordSize();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
// we can probably simplify this later...this calculates the size
|
||||
// w/o serializing but still is a bit slow
|
||||
public int getRecordSize()
|
||||
{
|
||||
recordLengths = new ArrayList();
|
||||
int retval = 0;
|
||||
int unicodesize = calculateUnicodeSize();
|
||||
|
||||
if ( unicodesize > SSTRecord.MAX_DATA_SPACE )
|
||||
{
|
||||
retval = calcRecordSizesForLongStrings( unicodesize );
|
||||
}
|
||||
else
|
||||
{
|
||||
// short data: write one simple SST record
|
||||
retval = SSTRecord.SST_RECORD_OVERHEAD + unicodesize;
|
||||
recordLengths.add( new Integer( unicodesize ) );
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
private int calcRecordSizesForLongStrings( int unicodesize )
|
||||
{
|
||||
int retval;
|
||||
UnicodeString unistr = null;
|
||||
int stringreminant = 0;
|
||||
int unipos = 0;
|
||||
boolean lastneedcontinue = false;
|
||||
int stringbyteswritten = 0;
|
||||
boolean finished = false;
|
||||
boolean first_record = true;
|
||||
int totalWritten = 0;
|
||||
|
||||
while ( !finished )
|
||||
{
|
||||
int record = 0;
|
||||
int pos = 0;
|
||||
|
||||
if ( first_record )
|
||||
{
|
||||
|
||||
// writing SST record
|
||||
record = SSTRecord.MAX_RECORD_SIZE;
|
||||
pos = 12;
|
||||
first_record = false;
|
||||
recordLengths.add( new Integer( record - SSTRecord.STD_RECORD_OVERHEAD ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// writing continue record
|
||||
pos = 0;
|
||||
int to_be_written = ( unicodesize - stringbyteswritten ) + ( lastneedcontinue ? 1 : 0 );
|
||||
int size = Math.min( SSTRecord.MAX_RECORD_SIZE - SSTRecord.STD_RECORD_OVERHEAD, to_be_written );
|
||||
|
||||
if ( size == to_be_written )
|
||||
{
|
||||
finished = true;
|
||||
}
|
||||
record = size + SSTRecord.STD_RECORD_OVERHEAD;
|
||||
recordLengths.add( new Integer( size ) );
|
||||
pos = 4;
|
||||
}
|
||||
if ( lastneedcontinue )
|
||||
{
|
||||
int available = SSTRecord.MAX_RECORD_SIZE - pos;
|
||||
|
||||
if ( stringreminant <= available )
|
||||
{
|
||||
|
||||
// write reminant
|
||||
stringbyteswritten += stringreminant - 1;
|
||||
pos += stringreminant;
|
||||
lastneedcontinue = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// write as much of the remnant as possible
|
||||
int toBeWritten = unistr.maxBrokenLength( available );
|
||||
|
||||
if ( available != toBeWritten )
|
||||
{
|
||||
int shortrecord = record - ( available - toBeWritten );
|
||||
recordLengths.set( recordLengths.size() - 1,
|
||||
new Integer( shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) );
|
||||
record = shortrecord;
|
||||
}
|
||||
stringbyteswritten += toBeWritten - 1;
|
||||
pos += toBeWritten;
|
||||
stringreminant -= toBeWritten - 1;
|
||||
lastneedcontinue = true;
|
||||
}
|
||||
}
|
||||
for ( ; unipos < strings.size(); unipos++ )
|
||||
{
|
||||
int available = SSTRecord.MAX_RECORD_SIZE - pos;
|
||||
Integer intunipos = new Integer( unipos );
|
||||
|
||||
unistr = ( (UnicodeString) strings.get( intunipos ) );
|
||||
if ( unistr.getRecordSize() <= available )
|
||||
{
|
||||
stringbyteswritten += unistr.getRecordSize();
|
||||
pos += unistr.getRecordSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( available >= SSTRecord.STRING_MINIMAL_OVERHEAD )
|
||||
{
|
||||
int toBeWritten =
|
||||
unistr.maxBrokenLength( available );
|
||||
|
||||
stringbyteswritten += toBeWritten;
|
||||
stringreminant =
|
||||
( unistr.getRecordSize() - toBeWritten )
|
||||
+ LittleEndianConsts.BYTE_SIZE;
|
||||
if ( available != toBeWritten )
|
||||
{
|
||||
int shortrecord = record
|
||||
- ( available - toBeWritten );
|
||||
|
||||
recordLengths.set(
|
||||
recordLengths.size() - 1,
|
||||
new Integer(
|
||||
shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) );
|
||||
record = shortrecord;
|
||||
}
|
||||
lastneedcontinue = true;
|
||||
unipos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int shortrecord = record - available;
|
||||
|
||||
recordLengths.set( recordLengths.size() - 1,
|
||||
new Integer( shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) );
|
||||
record = shortrecord;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
totalWritten += record;
|
||||
}
|
||||
retval = totalWritten;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
private void serializeSingleSSTRecord( byte[] data, int offset, int record_length_index )
|
||||
{
|
||||
// short data: write one simple SST record
|
||||
@ -279,8 +138,8 @@ class SSTSerializer
|
||||
for ( int k = 0; k < strings.size(); k++ )
|
||||
{
|
||||
// UnicodeString unistr = ( (UnicodeString) strings.get( new Integer( k ) ) );
|
||||
System.arraycopy( getUnicodeString(k).serialize(), 0, data, pos + offset, getUnicodeString(k).getRecordSize() );
|
||||
pos += getUnicodeString(k).getRecordSize();
|
||||
System.arraycopy( getUnicodeString( k ).serialize(), 0, data, pos + offset, getUnicodeString( k ).getRecordSize() );
|
||||
pos += getUnicodeString( k ).getRecordSize();
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,4 +212,9 @@ class SSTSerializer
|
||||
return ( (UnicodeString) strings.get( intunipos ) );
|
||||
}
|
||||
|
||||
public int getRecordSize()
|
||||
{
|
||||
return new SSTRecordSizeCalculator(this).getRecordSize();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
@ -55,11 +54,9 @@
|
||||
|
||||
package org.apache.poi.util;
|
||||
|
||||
import org.apache.log4j.Category;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import junit.framework.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Marc Johnson (mjohnson at apache dot org)
|
||||
@ -68,7 +65,7 @@ import java.io.*;
|
||||
*/
|
||||
|
||||
public class TestPOILogFactory
|
||||
extends TestCase
|
||||
extends TestCase
|
||||
{
|
||||
/**
|
||||
* Creates new TestPOILogFactory
|
||||
@ -76,9 +73,9 @@ public class TestPOILogFactory
|
||||
* @param name
|
||||
*/
|
||||
|
||||
public TestPOILogFactory(String name)
|
||||
public TestPOILogFactory( String name )
|
||||
{
|
||||
super(name);
|
||||
super( name );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,26 +85,26 @@ public class TestPOILogFactory
|
||||
*/
|
||||
|
||||
public void testLog()
|
||||
throws IOException
|
||||
throws IOException
|
||||
{
|
||||
//NKB Testing only that logging classes use gives no exception
|
||||
// Since logging can be disabled, no checking of logging
|
||||
// output is done.
|
||||
|
||||
POILogger l1 = POILogFactory.getLogger("org.apache.poi.hssf.test");
|
||||
POILogger l2 = POILogFactory.getLogger("org.apache.poi.hdf.test");
|
||||
|
||||
l1.log(POILogger.FATAL, "testing cat org.apache.poi.hssf.*:FATAL");
|
||||
l1.log(POILogger.ERROR, "testing cat org.apache.poi.hssf.*:ERROR");
|
||||
l1.log(POILogger.WARN, "testing cat org.apache.poi.hssf.*:WARN");
|
||||
l1.log(POILogger.INFO, "testing cat org.apache.poi.hssf.*:INFO");
|
||||
l1.log(POILogger.DEBUG, "testing cat org.apache.poi.hssf.*:DEBUG");
|
||||
POILogger l1 = POILogFactory.getLogger( "org.apache.poi.hssf.test" );
|
||||
POILogger l2 = POILogFactory.getLogger( "org.apache.poi.hdf.test" );
|
||||
|
||||
l2.log(POILogger.FATAL, "testing cat org.apache.poi.hdf.*:FATAL");
|
||||
l2.log(POILogger.ERROR, "testing cat org.apache.poi.hdf.*:ERROR");
|
||||
l2.log(POILogger.WARN, "testing cat org.apache.poi.hdf.*:WARN");
|
||||
l2.log(POILogger.INFO, "testing cat org.apache.poi.hdf.*:INFO");
|
||||
l2.log(POILogger.DEBUG, "testing cat org.apache.poi.hdf.*:DEBUG");
|
||||
l1.log( POILogger.FATAL, "testing cat org.apache.poi.hssf.*:FATAL" );
|
||||
l1.log( POILogger.ERROR, "testing cat org.apache.poi.hssf.*:ERROR" );
|
||||
l1.log( POILogger.WARN, "testing cat org.apache.poi.hssf.*:WARN" );
|
||||
l1.log( POILogger.INFO, "testing cat org.apache.poi.hssf.*:INFO" );
|
||||
l1.log( POILogger.DEBUG, "testing cat org.apache.poi.hssf.*:DEBUG" );
|
||||
|
||||
l2.log( POILogger.FATAL, "testing cat org.apache.poi.hdf.*:FATAL" );
|
||||
l2.log( POILogger.ERROR, "testing cat org.apache.poi.hdf.*:ERROR" );
|
||||
l2.log( POILogger.WARN, "testing cat org.apache.poi.hdf.*:WARN" );
|
||||
l2.log( POILogger.INFO, "testing cat org.apache.poi.hdf.*:INFO" );
|
||||
l2.log( POILogger.DEBUG, "testing cat org.apache.poi.hdf.*:DEBUG" );
|
||||
|
||||
}
|
||||
|
||||
@ -117,9 +114,9 @@ public class TestPOILogFactory
|
||||
* @param ignored_args
|
||||
*/
|
||||
|
||||
public static void main(String [] ignored_args)
|
||||
public static void main( String[] ignored_args )
|
||||
{
|
||||
System.out.println("Testing basic util.POILogFactory functionality");
|
||||
junit.textui.TestRunner.run(TestPOILogFactory.class);
|
||||
System.out.println( "Testing basic util.POILogFactory functionality" );
|
||||
junit.textui.TestRunner.run( TestPOILogFactory.class );
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
@ -57,19 +56,16 @@ package org.apache.poi.util;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
/**
|
||||
* Tests the log class.
|
||||
*
|
||||
* @author Glen Stampoultzis (glens at apache.org)
|
||||
* @author Marc Johnson (mjohnson at apache dot org)
|
||||
* @author Nicola Ken Barozzi (nicolaken at apache.org)
|
||||
* @author Nicola Ken Barozzi (nicolaken at apache.org)
|
||||
*/
|
||||
|
||||
public class TestPOILogger
|
||||
extends TestCase
|
||||
extends TestCase
|
||||
{
|
||||
/**
|
||||
* Constructor TestPOILogger
|
||||
@ -79,23 +75,9 @@ public class TestPOILogger
|
||||
*
|
||||
*/
|
||||
|
||||
public TestPOILogger(String s)
|
||||
public TestPOILogger( String s )
|
||||
{
|
||||
super(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method setUp
|
||||
*
|
||||
*
|
||||
* @exception Exception
|
||||
*
|
||||
*/
|
||||
|
||||
protected void setUp()
|
||||
throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
super( s );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,29 +85,20 @@ public class TestPOILogger
|
||||
*
|
||||
* @exception Exception
|
||||
*/
|
||||
|
||||
public void testVariousLogTypes()
|
||||
throws Exception
|
||||
throws Exception
|
||||
{
|
||||
//NKB Testing only that logging classes use gives no exception
|
||||
// Since logging can be disabled, no checking of logging
|
||||
// output is done.
|
||||
|
||||
POILogger log = POILogFactory.getLogger("foo");
|
||||
|
||||
log.log(POILogger.WARN, "Test = ", new Integer(1));
|
||||
log.logFormatted(POILogger.ERROR, "Test param 1 = %, param 2 = %",
|
||||
"2", new Integer(3));
|
||||
log.logFormatted(POILogger.ERROR, "Test param 1 = %, param 2 = %",
|
||||
new int[]
|
||||
{
|
||||
4, 5
|
||||
});
|
||||
log.logFormatted(POILogger.ERROR,
|
||||
"Test param 1 = %1.1, param 2 = %0.1", new double[]
|
||||
{
|
||||
4, 5.23
|
||||
});
|
||||
POILogger log = POILogFactory.getLogger( "foo" );
|
||||
|
||||
log.log( POILogger.WARN, "Test = ", new Integer( 1 ) );
|
||||
log.logFormatted( POILogger.ERROR, "Test param 1 = %, param 2 = %", "2", new Integer( 3 ) );
|
||||
log.logFormatted( POILogger.ERROR, "Test param 1 = %, param 2 = %", new int[]{4, 5} );
|
||||
log.logFormatted( POILogger.ERROR,
|
||||
"Test param 1 = %1.1, param 2 = %0.1", new double[]{4, 5.23} );
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user