Headers should all be fixed as of revision 1310946.  I updated all the
headers which were non-conforming (pdmodel/common/XrefEntry.java
pdmodel/ConformingPDDocument.java cos/COSDictionaryLateBinding.java
cos/COSUnread.java).

If I missed any, let me know and I'll take care of it.

Thanks,
Adam

On 04/06/2012 08:45 AM, Andreas Lehmkuehler wrote:
> Hi,
> 
> I just realized that the headers of all new files aren't o.k., e.g. see [1]
> 
> @Adam
> Do you have the time to fix this. If not, do you give me the permission
> to change the headers in question?
> 
> BR
> Andreas Lehmkühler
> 
> [1]
> http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/ConformingPDDocument.java?view=markup&pathrev=1142109
> 
> 
> 
> Am 02.07.2011 00:28, schrieb a...@apache.org:
>> Author: adam
>> Date: Fri Jul  1 22:28:23 2011
>> New Revision: 1142109
>>
>> URL: http://svn.apache.org/viewvc?rev=1142109&view=rev
>> Log:
>> PDFBOX-1000: Conforming parser.  Initial commit to make it easier for
>> others to test&  contribute.
>>
>> Added:
>>     
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionaryLateBinding.java
>>
>>     
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSUnread.java
>>     
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/ConformingPDFParser.java
>>
>>     
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/ConformingPDDocument.java
>>
>>     
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/common/XrefEntry.java
>>
>>     
>> pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdfparser/ConformingPDFParserTest.java
>>
>>      pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdfparser/
>>     
>> pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdfparser/gdb-refcard.pdf
>>   
>> (with props)
>> Modified:
>>     
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionary.java
>>
>>     
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java
>>
>>     
>> pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/TestPDDocumentCatalog.java
>>
>>
>> Modified:
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionary.java
>>
>> URL:
>> http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionary.java?rev=1142109&r1=1142108&r2=1142109&view=diff
>>
>> ==============================================================================
>>
>> ---
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionary.java
>> (original)
>> +++
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionary.java
>> Fri Jul  1 22:28:23 2011
>> @@ -43,7 +43,7 @@ public class COSDictionary extends COSBa
>>        * The name-value pairs of this dictionary. The pairs are kept
>> in the
>>        * order they were added to the dictionary.
>>        */
>> -    private final Map<COSName, COSBase>  items =
>> +    protected final Map<COSName, COSBase>  items =
>>           new LinkedHashMap<COSName, COSBase>();
>>
>>       /**
>> @@ -1410,12 +1410,18 @@ public class COSDictionary extends COSBa
>>       /**
>>        * {@inheritDoc}
>>        */
>> -    public String toString()
>> -    {
>> +    @Override
>> +    public String toString() {
>>           StringBuilder retVal = new StringBuilder("COSDictionary{");
>> -        for( COSName key : items.keySet() )
>> -        {
>> -            retVal.append("(" + key + ":" +
>> getDictionaryObject(key).toString() + ") ");
>> +        for(COSName key : items.keySet()) {
>> +            retVal.append("(");
>> +            retVal.append(key);
>> +            retVal.append(":");
>> +            if(getDictionaryObject(key) != null)
>> +                retVal.append(getDictionaryObject(key).toString());
>> +            else
>> +                retVal.append("<null>");
>> +            retVal.append(") ");
>>           }
>>           retVal.append("}");
>>           return retVal.toString();
>>
>> Added:
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionaryLateBinding.java
>>
>> URL:
>> http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionaryLateBinding.java?rev=1142109&view=auto
>>
>> ==============================================================================
>>
>> ---
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionaryLateBinding.java
>> (added)
>> +++
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionaryLateBinding.java
>> Fri Jul  1 22:28:23 2011
>> @@ -0,0 +1,61 @@
>> +/*
>> + *  Copyright 2011 adam.
>> + *
>> + *  Licensed under the Apache License, Version 2.0 (the "License");
>> + *  you may not use this file except in compliance with the License.
>> + *  You may obtain a copy of the License at
>> + *
>> + *       http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + *  Unless required by applicable law or agreed to in writing, software
>> + *  distributed under the License is distributed on an "AS IS" BASIS,
>> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + *  See the License for the specific language governing permissions and
>> + *  limitations under the License.
>> + *  under the License.
>> + */
>> +
>> +package org.apache.pdfbox.cos;
>> +
>> +import org.apache.commons.logging.Log;
>> +import org.apache.commons.logging.LogFactory;
>> +import org.apache.pdfbox.pdfparser.ConformingPDFParser;
>> +
>> +/**
>> + *
>> + * @author adam
>> + */
>> +public class COSDictionaryLateBinding extends COSDictionary {
>> +    public static final Log log =
>> LogFactory.getLog(COSDictionaryLateBinding.class);
>> +    ConformingPDFParser parser;
>> +
>> +    public COSDictionaryLateBinding(ConformingPDFParser parser) {
>> +        super();
>> +        this.parser = parser;
>> +    }
>> +
>> +    /**
>> +     * This will get an object from this dictionary.  If the object
>> is a reference then it will
>> +     * dereference it and get it from the document.  If the object is
>> COSNull then
>> +     * null will be returned.
>> +     * @param key The key to the object that we are getting.
>> +     * @return The object that matches the key.
>> +     */
>> +    @Override
>> +    public COSBase getDictionaryObject(COSName key) {
>> +        COSBase retval = items.get(key);
>> +        if(retval instanceof COSObject) {
>> +            int objectNumber =
>> ((COSObject)retval).getObjectNumber().intValue();
>> +            int generation =
>> ((COSObject)retval).getGenerationNumber().intValue();
>> +            try {
>> +                retval = parser.getObject(objectNumber, generation);
>> +            } catch(Exception e) {
>> +                log.warn("Unable to read information for object " +
>> objectNumber);
>> +            }
>> +        }
>> +        if(retval instanceof COSNull) {
>> +            retval = null;
>> +        }
>> +        return retval;
>> +    }
>> +}
>>
>> Added:
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSUnread.java
>> URL:
>> http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSUnread.java?rev=1142109&view=auto
>>
>> ==============================================================================
>>
>> ---
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSUnread.java
>> (added)
>> +++
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSUnread.java
>> Fri Jul  1 22:28:23 2011
>> @@ -0,0 +1,100 @@
>> +/*
>> + *  Copyright 2011 adam.
>> + *
>> + *  Licensed under the Apache License, Version 2.0 (the "License");
>> + *  you may not use this file except in compliance with the License.
>> + *  You may obtain a copy of the License at
>> + *
>> + *       http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + *  Unless required by applicable law or agreed to in writing, software
>> + *  distributed under the License is distributed on an "AS IS" BASIS,
>> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + *  See the License for the specific language governing permissions and
>> + *  limitations under the License.
>> + *  under the License.
>> + */
>> +
>> +package org.apache.pdfbox.cos;
>> +
>> +import org.apache.pdfbox.exceptions.COSVisitorException;
>> +import org.apache.pdfbox.pdfparser.ConformingPDFParser;
>> +
>> +/**
>> + *
>> + * @author adam
>> + */
>> +public class COSUnread extends COSBase {
>> +    private long objectNumber;
>> +    private long generation;
>> +    private ConformingPDFParser parser;
>> +
>> +    public COSUnread() {
>> +        super();
>> +    }
>> +
>> +    public COSUnread(long objectNumber, long generation) {
>> +        this();
>> +        this.objectNumber = objectNumber;
>> +        this.generation = generation;
>> +    }
>> +
>> +    public COSUnread(long objectNumber, long generation,
>> ConformingPDFParser parser) {
>> +        this(objectNumber, generation);
>> +        this.parser = parser;
>> +    }
>> +
>> +    @Override
>> +    public Object accept(ICOSVisitor visitor) throws
>> COSVisitorException {
>> +        // TODO: read the object using the parser (if available) and
>> visit that object
>> +        throw new UnsupportedOperationException("COSUnread can not be
>> written/visited.");
>> +    }
>> +
>> +    @Override
>> +    public String toString() {
>> +        return "COSUnread{" + objectNumber + "," + generation + "}";
>> +    }
>> +
>> +    /**
>> +     * @return the objectNumber
>> +     */
>> +    public long getObjectNumber() {
>> +        return objectNumber;
>> +    }
>> +
>> +    /**
>> +     * @param objectNumber the objectNumber to set
>> +     */
>> +    public void setObjectNumber(long objectNumber) {
>> +        this.objectNumber = objectNumber;
>> +    }
>> +
>> +    /**
>> +     * @return the generation
>> +     */
>> +    public long getGeneration() {
>> +        return generation;
>> +    }
>> +
>> +    /**
>> +     * @param generation the generation to set
>> +     */
>> +    public void setGeneration(long generation) {
>> +        this.generation = generation;
>> +    }
>> +
>> +    /**
>> +     * @return the parser
>> +     */
>> +    public ConformingPDFParser getParser() {
>> +        return parser;
>> +    }
>> +
>> +    /**
>> +     * @param parser the parser to set
>> +     */
>> +    public void setParser(ConformingPDFParser parser) {
>> +        this.parser = parser;
>> +    }
>> +
>> +}
>>
>> Modified:
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java
>>
>> URL:
>> http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java?rev=1142109&r1=1142108&r2=1142109&view=diff
>>
>> ==============================================================================
>>
>> ---
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java
>> (original)
>> +++
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java
>> Fri Jul  1 22:28:23 2011
>> @@ -110,6 +110,10 @@ public abstract class BaseParser
>>        */
>>       protected final boolean forceParsing;
>>
>> +    public BaseParser() {
>> +        this.forceParsing = FORCE_PARSING;
>> +    }
>> +
>>       /**
>>        * Constructor.
>>        *
>> @@ -876,7 +880,7 @@ public abstract class BaseParser
>>               throw new IOException("expected='/' actual='" + (char)c
>> + "'-" + c + " " + pdfSource );
>>           }
>>           // costruisce il nome
>> -        StringBuffer buffer = new StringBuffer();
>> +        StringBuilder buffer = new StringBuilder();
>>           c = pdfSource.read();
>>           while( c != -1 )
>>           {
>> @@ -1063,7 +1067,7 @@ public abstract class BaseParser
>>           {
>>               if( Character.isDigit(c) || c == '-' || c == '+' || c ==
>> '.')
>>               {
>> -                StringBuffer buf = new StringBuffer();
>> +                StringBuilder buf = new StringBuilder();
>>                   int ic = pdfSource.read();
>>                   c = (char)ic;
>>                   while( Character.isDigit( c )||
>> @@ -1118,7 +1122,7 @@ public abstract class BaseParser
>>       protected String readString() throws IOException
>>       {
>>           skipSpaces();
>> -        StringBuffer buffer = new StringBuffer();
>> +        StringBuilder buffer = new StringBuilder();
>>           int c = pdfSource.read();
>>           while( !isEndOfName((char)c)&&  !isClosing(c)&&  c != -1 )
>>           {
>> @@ -1148,7 +1152,7 @@ public abstract class BaseParser
>>           {
>>               c = pdfSource.read();
>>           }
>> -        StringBuffer buffer = new StringBuffer( theString.length() );
>> +        StringBuilder buffer = new StringBuilder( theString.length() );
>>           int charsRead = 0;
>>           while( !isEOL(c)&&  c != -1&&  charsRead<  theString.length() )
>>           {
>> @@ -1194,7 +1198,7 @@ public abstract class BaseParser
>>
>>           //average string size is around 2 and the normal string
>> buffer size is
>>           //about 16 so lets save some space.
>> -        StringBuffer buffer = new StringBuffer(length);
>> +        StringBuilder buffer = new StringBuilder(length);
>>           while( !isWhitespace(c)&&  !isClosing(c)&&  c != -1&& 
>> buffer.length()<  length&&
>>                   c != '['&&
>>                   c != '<'&&
>> @@ -1250,7 +1254,7 @@ public abstract class BaseParser
>>               throw new IOException( "Error: End-of-File, expected
>> line");
>>           }
>>
>> -        StringBuffer buffer = new StringBuffer( 11 );
>> +        StringBuilder buffer = new StringBuilder( 11 );
>>
>>           int c;
>>           while ((c = pdfSource.read()) != -1)
>> @@ -1300,10 +1304,9 @@ public abstract class BaseParser
>>       }
>>
>>       /**
>> -     * This will tell if the next byte is whitespace or not.
>> -     *
>> +     * This will tell if the next byte is whitespace or not.  These
>> values are
>> +     * specified in table 1 (page 12) of ISO 32000-1:2008.
>>        * @param c The character to check against whitespace
>> -     *
>>        * @return true if the next byte in the stream is a whitespace
>> character.
>>        */
>>       protected boolean isWhitespace( int c )
>>
>> Added:
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/ConformingPDFParser.java
>>
>> URL:
>> http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/ConformingPDFParser.java?rev=1142109&view=auto
>>
>> ==============================================================================
>>
>> ---
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/ConformingPDFParser.java
>> (added)
>> +++
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/ConformingPDFParser.java
>> Fri Jul  1 22:28:23 2011
>> @@ -0,0 +1,696 @@
>> +/*
>> + *  Copyright 2010 adam.
>> + *
>> + *  Licensed under the Apache License, Version 2.0 (the "License");
>> + *  you may not use this file except in compliance with the License.
>> + *  You may obtain a copy of the License at
>> + *
>> + *       http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + *  Unless required by applicable law or agreed to in writing, software
>> + *  distributed under the License is distributed on an "AS IS" BASIS,
>> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + *  See the License for the specific language governing permissions and
>> + *  limitations under the License.
>> + *  under the License.
>> + */
>> +
>> +package org.apache.pdfbox.pdfparser;
>> +
>> +import java.io.File;
>> +import java.io.IOException;
>> +import java.util.ArrayList;
>> +import java.util.List;
>> +import java.util.Set;
>> +import org.apache.pdfbox.cos.COSArray;
>> +import org.apache.pdfbox.cos.COSBase;
>> +import org.apache.pdfbox.cos.COSDictionary;
>> +import org.apache.pdfbox.cos.COSDocument;
>> +import org.apache.pdfbox.cos.COSFloat;
>> +import org.apache.pdfbox.cos.COSInteger;
>> +import org.apache.pdfbox.cos.COSName;
>> +import org.apache.pdfbox.cos.COSNumber;
>> +import org.apache.pdfbox.cos.COSObject;
>> +import org.apache.pdfbox.cos.COSString;
>> +import org.apache.pdfbox.cos.COSUnread;
>> +import org.apache.pdfbox.io.RandomAccess;
>> +import org.apache.pdfbox.io.RandomAccessFile;
>> +import org.apache.pdfbox.pdmodel.ConformingPDDocument;
>> +import org.apache.pdfbox.pdmodel.PDDocument;
>> +import org.apache.pdfbox.pdmodel.common.XrefEntry;
>> +import org.apache.pdfbox.persistence.util.COSObjectKey;
>> +
>> +/**
>> + *
>> + * @author<a href="a...@apache.org">Adam Nichols</a>
>> + */
>> +public class ConformingPDFParser extends BaseParser {
>> +    protected RandomAccess inputFile;
>> +    List<XrefEntry>  xrefEntries;
>> +    private long currentOffset;
>> +    private ConformingPDDocument doc = null;
>> +    private boolean throwNonConformingException = true;
>> +    private boolean recursivlyRead = true;
>> +
>> +    /**
>> +     * Constructor.
>> +     *
>> +     * @param input The input stream that contains the PDF document.
>> +     *
>> +     * @throws IOException If there is an error initializing the stream.
>> +     */
>> +    public ConformingPDFParser(File inputFile) throws IOException {
>> +        this.inputFile = new RandomAccessFile(inputFile, "r");
>> +    }
>> +
>> +    /**
>> +     * This will parse the stream and populate the COSDocument
>> object.  This will close
>> +     * the stream when it is done parsing.
>> +     *
>> +     * @throws IOException If there is an error reading from the
>> stream or corrupt data
>> +     * is found.
>> +     */
>> +    public void parse() throws IOException {
>> +        document = new COSDocument();
>> +        doc = new ConformingPDDocument(document);
>> +        currentOffset = inputFile.length()-1;
>> +        long xRefTableLocation = parseTrailerInformation();
>> +        currentOffset = xRefTableLocation;
>> +        parseXrefTable();
>> +        // now that we read the xref table and put null references in
>> the doc,
>> +        // we can deference those objects now.
>> +        boolean oldValue = recursivlyRead;
>> +        recursivlyRead = false;
>> +        List<COSObjectKey>  keys = doc.getObjectKeysFromPool();
>> +        for(COSObjectKey key : keys) {
>> +            // getObject will put it into the document's object pool
>> for us
>> +            getObject(key.getNumber(), key.getGeneration());
>> +        }
>> +        recursivlyRead = oldValue;
>> +    }
>> +
>> +    /**
>> +     * This will get the document that was parsed.  parse() must be
>> called before this is called.
>> +     * When you are done with this document you must call close() on
>> it to release
>> +     * resources.
>> +     *
>> +     * @return The document that was parsed.
>> +     *
>> +     * @throws IOException If there is an error getting the document.
>> +     */
>> +    public COSDocument getDocument() throws IOException {
>> +        if( document == null ) {
>> +            throw new IOException( "You must call parse() before
>> calling getDocument()" );
>> +        }
>> +        return document;
>> +    }
>> +
>> +    /**
>> +     * This will get the PD document that was parsed.  When you are
>> done with
>> +     * this document you must call close() on it to release resources.
>> +     *
>> +     * @return The document at the PD layer.
>> +     *
>> +     * @throws IOException If there is an error getting the document.
>> +     */
>> +    public PDDocument getPDDocument() throws IOException {
>> +        return doc;
>> +    }
>> +
>> +    private boolean parseXrefTable() throws IOException {
>> +        String currentLine = readLine();
>> +        if(throwNonConformingException) {
>> +            if(!"xref".equals(currentLine))
>> +                throw new AssertionError("xref table not
>> found.\nExpected: xref\nFound: "+currentLine);
>> +        }
>> +
>> +        int objectNumber = readInt();
>> +        int entries = readInt();
>> +        xrefEntries = new ArrayList<XrefEntry>(entries);
>> +        for(int i=0; i<entries; i++)
>> +            xrefEntries.add(new XrefEntry(objectNumber++, readInt(),
>> readInt(), readLine()));
>> +
>> +        return true;
>> +    }
>> +
>> +    protected long parseTrailerInformation() throws IOException,
>> NumberFormatException {
>> +        long xrefLocation = -1;
>> +        consumeWhitespaceBackwards();
>> +        String currentLine = readLineBackwards();
>> +        if(throwNonConformingException) {
>> +            if(!"%%EOF".equals(currentLine))
>> +                throw new AssertionError("Invalid EOF
>> marker.\nExpected: %%EOF\nFound: "+currentLine);
>> +        }
>> +
>> +        xrefLocation = readLongBackwards();
>> +        currentLine = readLineBackwards();
>> +        if(throwNonConformingException) {
>> +            if(!"startxref".equals(currentLine))
>> +                throw new AssertionError("Invalid trailer.\nExpected:
>> startxref\nFound: "+currentLine);
>> +        }
>> +
>> +        document.setTrailer(readDictionaryBackwards());
>> +        consumeWhitespaceBackwards();
>> +        currentLine = readLineBackwards();
>> +        if(throwNonConformingException) {
>> +            if(!"trailer".equals(currentLine))
>> +                throw new AssertionError("Invalid trailer.\nExpected:
>> trailer\nFound: "+currentLine);
>> +        }
>> +
>> +        return xrefLocation;
>> +    }
>> +
>> +    protected byte readByteBackwards() throws IOException {
>> +        inputFile.seek(currentOffset);
>> +        byte singleByte = (byte)inputFile.read();
>> +        currentOffset--;
>> +        return singleByte;
>> +    }
>> +
>> +    protected byte readByte() throws IOException {
>> +        inputFile.seek(currentOffset);
>> +        byte singleByte = (byte)inputFile.read();
>> +        currentOffset++;
>> +        return singleByte;
>> +    }
>> +
>> +    protected String readBackwardUntilWhitespace() throws IOException {
>> +        StringBuilder sb = new StringBuilder();
>> +        byte singleByte = readByteBackwards();
>> +        while(!isWhitespace(singleByte)) {
>> +            sb.insert(0, (char)singleByte);
>> +            singleByte = readByteBackwards();
>> +        }
>> +        return sb.toString();
>> +    }
>> +
>> +    /**
>> +     * This will read all bytes (backwards) until a non-whitespace
>> character is
>> +     * found.  To save you an extra read, the non-whitespace
>> character is
>> +     * returned.  If the current character is not whitespace, this
>> method will
>> +     * just return the current char.
>> +     * @return the first non-whitespace character found
>> +     * @throws IOException if there is an error reading from the file
>> +     */
>> +    protected byte consumeWhitespaceBackwards() throws IOException {
>> +        inputFile.seek(currentOffset);
>> +        byte singleByte = (byte)inputFile.read();
>> +        if(!isWhitespace(singleByte))
>> +            return singleByte;
>> +
>> +        // we have some whitespace, let's consume it
>> +        while(isWhitespace(singleByte)) {
>> +            singleByte = readByteBackwards();
>> +        }
>> +        // readByteBackwards will decrement the currentOffset to
>> point the byte
>> +        // before the one just read, so we increment it back to the
>> current byte
>> +        currentOffset++;
>> +        return singleByte;
>> +    }
>> +
>> +    /**
>> +     * This will read all bytes until a non-whitespace character is
>> +     * found.  To save you an extra read, the non-whitespace
>> character is
>> +     * returned.  If the current character is not whitespace, this
>> method will
>> +     * just return the current char.
>> +     * @return the first non-whitespace character found
>> +     * @throws IOException if there is an error reading from the file
>> +     */
>> +    protected byte consumeWhitespace() throws IOException {
>> +        inputFile.seek(currentOffset);
>> +        byte singleByte = (byte)inputFile.read();
>> +        if(!isWhitespace(singleByte))
>> +            return singleByte;
>> +
>> +        // we have some whitespace, let's consume it
>> +        while(isWhitespace(singleByte)) {
>> +            singleByte = readByte();
>> +        }
>> +        // readByte() will increment the currentOffset to point the byte
>> +        // after the one just read, so we decrement it back to the
>> current byte
>> +        currentOffset--;
>> +        return singleByte;
>> +    }
>> +
>> +    /**
>> +     * This will consume any whitespace, read in bytes until
>> whitespace is found
>> +     * again and then parse the characters which have been read as a
>> long.  The
>> +     * current offset will then point at the first whitespace
>> character which
>> +     * preceeds the number.
>> +     * @return the parsed number
>> +     * @throws IOException if there is an error reading from the file
>> +     * @throws NumberFormatException if the bytes read can not be
>> converted to a number
>> +     */
>> +    protected long readLongBackwards() throws IOException,
>> NumberFormatException {
>> +        StringBuilder sb = new StringBuilder();
>> +        consumeWhitespaceBackwards();
>> +        byte singleByte = readByteBackwards();
>> +        while(!isWhitespace(singleByte)) {
>> +            sb.insert(0, (char)singleByte);
>> +            singleByte = readByteBackwards();
>> +        }
>> +        if(sb.length() == 0)
>> +            throw new AssertionError("Number not found.  Expected
>> number at offset: " + currentOffset);
>> +        return Long.parseLong(sb.toString());
>> +    }
>> +
>> +    @Override
>> +    protected int readInt() throws IOException {
>> +        StringBuilder sb = new StringBuilder();
>> +        consumeWhitespace();
>> +        byte singleByte = readByte();
>> +        while(!isWhitespace(singleByte)) {
>> +            sb.append((char)singleByte);
>> +            singleByte = readByte();
>> +        }
>> +        if(sb.length() == 0)
>> +            throw new AssertionError("Number not found.  Expected
>> number at offset: " + currentOffset);
>> +        return Integer.parseInt(sb.toString());
>> +    }
>> +
>> +    /**
>> +     * This will read in a number and return the COS version of the
>> number (be
>> +     * it a COSInteger or a COSFloat).
>> +     * @return the COSNumber which was read/parsed
>> +     * @throws IOException
>> +     */
>> +    protected COSNumber readNumber() throws IOException {
>> +        StringBuilder sb = new StringBuilder();
>> +        consumeWhitespace();
>> +        byte singleByte = readByte();
>> +        while(!isWhitespace(singleByte)) {
>> +            sb.append((char)singleByte);
>> +            singleByte = readByte();
>> +        }
>> +        if(sb.length() == 0)
>> +            throw new AssertionError("Number not found.  Expected
>> number at offset: " + currentOffset);
>> +        return parseNumber(sb.toString());
>> +    }
>> +
>> +    protected COSNumber parseNumber(String number) throws IOException {
>> +        if(number.matches("^[0-9]+$"))
>> +            return COSInteger.get(number);
>> +        return new COSFloat(Float.parseFloat(number));
>> +    }
>> +
>> +    protected COSBase processCosObject(String string) throws
>> IOException {
>> +        if(string != null&&  string.endsWith(">")) {
>> +            // string of hex codes
>> +            return
>> COSString.createFromHexString(string.replaceAll("^<",
>> "").replaceAll(">$", ""));
>> +        }
>> +        return null;
>> +    }
>> +
>> +    protected COSBase readObjectBackwards() throws IOException {
>> +        COSBase obj = null;
>> +        consumeWhitespaceBackwards();
>> +        String lastSection = readBackwardUntilWhitespace();
>> +        if("R".equals(lastSection)) {
>> +            // indirect reference
>> +            long gen = readLongBackwards();
>> +            long number = readLongBackwards();
>> +            // We just put a placeholder in the pool for now, we'll
>> read the data later
>> +            doc.putObjectInPool(new COSUnread(), number, gen);
>> +            obj = new COSUnread(number, gen, this);
>> +        } else if(">>".equals(lastSection)) {
>> +            // dictionary
>> +            throw new RuntimeException("Not yet implemented");
>> +        } else if(lastSection != null&&  lastSection.endsWith("]")) {
>> +            // array
>> +            COSArray array = new COSArray();
>> +            lastSection = lastSection.replaceAll("]$", "");
>> +            while(!lastSection.startsWith("[")) {
>> +                if(lastSection.matches("^\\s*<.*>\\s*$")) // it's a
>> hex string
>> +                   
>> array.add(COSString.createFromHexString(lastSection.replaceAll("^\\s*<",
>> "").replaceAll(">\\s*$", "")));
>> +                lastSection = readBackwardUntilWhitespace();
>> +            }
>> +            lastSection = lastSection.replaceAll("^\\[", "");
>> +            if(lastSection.matches("^\\s*<.*>\\s*$")) // it's a hex
>> string
>> +               
>> array.add(COSString.createFromHexString(lastSection.replaceAll("^\\s*<",
>> "").replaceAll(">\\s*$", "")));
>> +            obj = array;
>> +        } else if(lastSection != null&&  lastSection.endsWith(">")) {
>> +            // string of hex codes
>> +            obj = processCosObject(lastSection);
>> +        } else {
>> +            // try a number, otherwise fall back on a string
>> +            try {
>> +                Long.parseLong(lastSection);
>> +                obj = COSNumber.get(lastSection);
>> +            } catch(NumberFormatException e) {
>> +                throw new RuntimeException("Not yet implemented");
>> +            }
>> +        }
>> +
>> +        return obj;
>> +    }
>> +
>> +    protected COSName readNameBackwards() throws IOException {
>> +        String name = readBackwardUntilWhitespace();
>> +        name = name.replaceAll("^/", "");
>> +        return COSName.getPDFName(name);
>> +    }
>> +
>> +    public COSBase getObject(long objectNumber, long generation)
>> throws IOException {
>> +        // we could optionally, check to see if parse() have been
>> called&
>> +        // throw an exception here, but I don't think that's really
>> necessary
>> +        XrefEntry entry = xrefEntries.get((int)objectNumber);
>> +        currentOffset = entry.getByteOffset();
>> +        return readObject(objectNumber, generation);
>> +    }
>> +
>> +    /**
>> +     * This will read an object from the inputFile at whatever our
>> currentOffset
>> +     * is.  If the object and generation are not the expected values
>> and this
>> +     * object is set to throw an exception for non-conforming
>> documents, then an
>> +     * exception will be thrown.
>> +     * @param objectNumber the object number you expect to read
>> +     * @param generation the generation you expect this object to be
>> +     * @return
>> +     */
>> +    public COSBase readObject(long objectNumber, long generation)
>> throws IOException {
>> +        // when recursivly reading, we always pull the object from
>> the filesystem
>> +        if(document != null&&  recursivlyRead) {
>> +            // check to see if it is in the document cache before
>> hitting the filesystem
>> +            COSBase obj = doc.getObjectFromPool(objectNumber,
>> generation);
>> +            if(obj != null)
>> +                return obj;
>> +        }
>> +
>> +        int actualObjectNumber = readInt();
>> +        if(objectNumber != actualObjectNumber)
>> +            if(throwNonConformingException)
>> +                throw new AssertionError("Object numer expected was " +
>> +                        objectNumber + " but actual was " +
>> actualObjectNumber);
>> +        consumeWhitespace();
>> +
>> +        int actualGeneration = readInt();
>> +        if(generation != actualGeneration)
>> +            if(throwNonConformingException)
>> +                throw new AssertionError("Generation expected was " +
>> +                        generation + " but actual was " +
>> actualGeneration);
>> +        consumeWhitespace();
>> +
>> +        String obj = readWord();
>> +        if(!"obj".equals(obj))
>> +            if(throwNonConformingException)
>> +                throw new AssertionError("Expected keyword 'obj' but
>> found " + obj);
>> +
>> +        // put placeholder object in doc to prevent infinite recursion
>> +        // e.g. read Root ->  dereference object ->  read object
>> which has /Parent ->  GOTO read Root
>> +        doc.putObjectInPool(new COSObject(null), objectNumber,
>> generation);
>> +        COSBase object = readObject();
>> +        doc.putObjectInPool(object, objectNumber, generation);
>> +        return object;
>> +    }
>> +
>> +    /**
>> +     * This actually reads the object data.
>> +     * @return the object which is read
>> +     * @throws IOException
>> +     */
>> +    protected COSBase readObject() throws IOException {
>> +        consumeWhitespace();
>> +        String string = readWord();
>> +        if(string.startsWith("<<")) {
>> +            // this is a dictionary
>> +            COSDictionary dictionary = new COSDictionary();
>> +            boolean atEndOfDictionary = false;
>> +            // remove the marker for the beginning of the dictionary
>> +            string = string.replaceAll("^<<", "");
>> +
>> +            if("".equals(string) || string.matches("^\\w$"))
>> +                string = readWord().trim();
>> +            while(!atEndOfDictionary) {
>> +                COSName name = COSName.getPDFName(string);
>> +                COSBase object = readObject();
>> +                dictionary.setItem(name, object);
>> +
>> +                byte singleByte = consumeWhitespace();
>> +                if(singleByte == '>') {
>> +                    readByte(); // get rid of the second '>'
>> +                    atEndOfDictionary = true;
>> +                }
>> +                if(!atEndOfDictionary)
>> +                    string = readWord().trim();
>> +            }
>> +            return dictionary;
>> +        } else if(string.startsWith("/")) {
>> +            // it's a dictionary label. i.e. /Type or /Pages or
>> something similar
>> +            COSBase name = COSName.getPDFName(string);
>> +            return name;
>> +        } else if(string.startsWith("-")) {
>> +            // it's a negitive number
>> +            return parseNumber(string);
>> +        } else if(string.charAt(0)>= '0'&&  string.charAt(0)<= '9' ) {
>> +            // it's a COSInt or COSFloat, or a weak reference (i.e.
>> "3 0 R")
>> +            // we'll have to peek ahead a little to see if it's a
>> reference or not
>> +            long tempOffset = this.currentOffset;
>> +            consumeWhitespace();
>> +            String tempString = readWord();
>> +            if(tempString.matches("^[0-9]+$")) {
>> +                // it is an int, might be a weak reference...
>> +                tempString = readWord();
>> +                if(!"R".equals(tempString)) {
>> +                    // it's just a number, not a weak reference
>> +                    this.currentOffset = tempOffset;
>> +                    return parseNumber(string);
>> +                }
>> +            } else {
>> +                // it's just a number, not a weak reference
>> +                this.currentOffset = tempOffset;
>> +                return parseNumber(string);
>> +            }
>> +
>> +            // it wasn't a number, so we need to parse the
>> weak-reference
>> +            this.currentOffset = tempOffset;
>> +            int number = Integer.parseInt(string);
>> +            int gen = readInt();
>> +            String r = readWord();
>> +
>> +            if(!"R".equals(r))
>> +                if(throwNonConformingException)
>> +                    throw new AssertionError("Expected keyword 'R'
>> but found " + r);
>> +
>> +            if(recursivlyRead) {
>> +                // seek to the object, read it, seek back to current
>> location
>> +                long tempLocation = this.currentOffset;
>> +                this.currentOffset =
>> this.xrefEntries.get(number).getByteOffset();
>> +                COSBase returnValue = readObject(number, gen);
>> +                this.currentOffset = tempLocation;
>> +                return returnValue;
>> +            } else {
>> +                // Put a COSUnknown there as a placeholder
>> +                COSObject obj = new COSObject(new COSUnread());
>> +                obj.setObjectNumber(COSInteger.get(number));
>> +                obj.setGenerationNumber(COSInteger.get(gen));
>> +                return obj;
>> +            }
>> +        } else if(string.startsWith("]")) {
>> +            // end of an array, just return null
>> +            if("]".equals(string))
>> +                return null;
>> +            int oldLength = string.length();
>> +            this.currentOffset -= oldLength;
>> +            return null;
>> +        } else if(string.startsWith("[")) {
>> +            // array of values
>> +            // we'll just pay attention to the first part (this is in
>> case there
>> +            // is no whitespace between the "[" and the first element)
>> +            int oldLength = string.length();
>> +            string = "[";
>> +            this.currentOffset -= (oldLength - string.length() + 1);
>> +
>> +            COSArray array = new COSArray();
>> +            COSBase object = readObject();
>> +            while(object != null) {
>> +                array.add(object);
>> +                object = readObject();
>> +            }
>> +            return array;
>> +        } else if(string.startsWith("(")) {
>> +            // this is a string (not hex encoded), strip off the '('
>> and read until ')'
>> +            StringBuilder sb = new StringBuilder(string.substring(1));
>> +            byte singleByte = readByte();
>> +            while(singleByte != ')') {
>> +                sb.append((char)singleByte);
>> +                singleByte = readByte();
>> +            }
>> +            return new COSString(sb.toString());
>> +        } else {
>> +            throw new RuntimeException("Not yet implemented: " + string
>> +                    + " loation=" + this.currentOffset);
>> +        }
>> +    }
>> +
>> +    /**
>> +     * This will read the next string from the stream.
>> +     * @return The string that was read from the stream.
>> +     * @throws IOException If there is an error reading from the stream.
>> +     */
>> +    @Override
>> +    protected String readString() throws IOException {
>> +        consumeWhitespace();
>> +        StringBuilder buffer = new StringBuilder();
>> +        int c = pdfSource.read();
>> +        while(!isEndOfName((char)c)&&  !isClosing(c)&&  c != -1) {
>> +            buffer.append( (char)c );
>> +            c = pdfSource.read();
>> +        }
>> +        if (c != -1) {
>> +            pdfSource.unread(c);
>> +        }
>> +        return buffer.toString();
>> +    }
>> +
>> +    protected COSDictionary readDictionaryBackwards() throws
>> IOException {
>> +        COSDictionary dict = new COSDictionary();
>> +
>> +        // consume the last two '>' chars which signify the end of
>> the dictionary
>> +        consumeWhitespaceBackwards();
>> +        byte singleByte = readByteBackwards();
>> +        if(throwNonConformingException) {
>> +            if(singleByte != '>')
>> +                throw new AssertionError("");
>> +        }
>> +        singleByte = readByteBackwards();
>> +        if(throwNonConformingException) {
>> +            if(singleByte != '>')
>> +                throw new AssertionError("");
>> +        }
>> +
>> +        // check to see if we're at the end of the dictionary
>> +        boolean atEndOfDictionary = false;
>> +        singleByte = consumeWhitespaceBackwards();
>> +        if(singleByte == '<') {
>> +            inputFile.seek(currentOffset-1);
>> +            atEndOfDictionary =  ((byte)inputFile.read()) == '<';
>> +        }
>> +
>> +        COSDictionary backwardsDictionary = new COSDictionary();
>> +        // while we're not at the end of the dictionary, read in entries
>> +        while(!atEndOfDictionary) {
>> +            COSBase object = readObjectBackwards();
>> +            COSName name = readNameBackwards();
>> +            backwardsDictionary.setItem(name, object);
>> +
>> +            singleByte = consumeWhitespaceBackwards();
>> +            if(singleByte == '<') {
>> +                inputFile.seek(currentOffset-1);
>> +                atEndOfDictionary =  ((byte)inputFile.read()) == '<';
>> +            }
>> +        }
>> +
>> +        // the dictionaries preserve the order keys were added, as
>> such we shall
>> +        // add them in the proper order, not the reverse order
>> +        Set<COSName>  backwardsKeys = backwardsDictionary.keySet();
>> +        for(int i = backwardsKeys.size()-1; i>=0; i--)
>> +            dict.setItem((COSName)backwardsKeys.toArray()[i],
>> backwardsDictionary.getItem((COSName)backwardsKeys.toArray()[i]));
>> +
>> +        // consume the last two '<' chars
>> +        readByteBackwards();
>> +        readByteBackwards();
>> +
>> +        return dict;
>> +    }
>> +
>> +    /**
>> +     * This will read a line starting with the byte at offset and going
>> +     * backwards until it finds a newline.  This should only be used
>> if we are
>> +     * certain that the data will only be text, and not binary data.
>> +     *
>> +     * @param offset the location of the file where we should start
>> reading
>> +     * @return the string which was read
>> +     * @throws IOException if there was an error reading data from
>> the file
>> +     */
>> +    protected String readLineBackwards() throws IOException {
>> +        StringBuilder sb = new StringBuilder();
>> +        boolean endOfObject = false;
>> +
>> +        do {
>> +            // first we read the %%EOF marker
>> +            byte singleByte = readByteBackwards();
>> +            if(singleByte == '\n') {
>> +                // if ther's a preceeding \r, we'll eat that as well
>> +                inputFile.seek(currentOffset);
>> +                if((byte)inputFile.read() == '\r')
>> +                    currentOffset--;
>> +                endOfObject = true;
>> +            } else if(singleByte == '\r') {
>> +                endOfObject = true;
>> +            } else {
>> +                sb.insert(0, (char)singleByte);
>> +            }
>> +        } while(!endOfObject);
>> +
>> +        return sb.toString();
>> +    }
>> +
>> +    /**
>> +     * This will read a line starting with the byte at offset and going
>> +     * forward until it finds a newline.  This should only be used if
>> we are
>> +     * certain that the data will only be text, and not binary data.
>> +     * @param offset the location of the file where we should start
>> reading
>> +     * @return the string which was read
>> +     * @throws IOException if there was an error reading data from
>> the file
>> +     */
>> +    @Override
>> +    protected String readLine() throws IOException {
>> +        StringBuilder sb = new StringBuilder();
>> +        boolean endOfLine = false;
>> +
>> +        do {
>> +            // first we read the %%EOF marker
>> +            byte singleByte = readByte();
>> +            if(singleByte == '\n') {
>> +                // if ther's a preceeding \r, we'll eat that as well
>> +                inputFile.seek(currentOffset);
>> +                if((byte)inputFile.read() == '\r')
>> +                    currentOffset++;
>> +                endOfLine = true;
>> +            } else if(singleByte == '\r') {
>> +                endOfLine = true;
>> +            } else {
>> +                sb.append((char)singleByte);
>> +            }
>> +        } while(!endOfLine);
>> +
>> +        return sb.toString();
>> +    }
>> +
>> +    protected String readWord() throws IOException {
>> +        StringBuilder sb = new StringBuilder();
>> +        boolean stop = true;
>> +        do {
>> +            byte singleByte = readByte();
>> +            stop = this.isWhitespace(singleByte);
>> +
>> +            // there are some additional characters which indicate
>> the next element/word has begun
>> +            // ignore the first char we read, b/c the first char is
>> the beginnging of this object, not the next one
>> +            if(!stop&&  sb.length()>  0) {
>> +                stop = singleByte == '/' || singleByte == '['
>> +                        || singleByte == ']'
>> +                        || (singleByte == '>'&& 
>> !">".equals(sb.toString()));
>> +                if(stop) // we're stopping on a non-whitespace char,
>> decrement the
>> +                    this.currentOffset--; // counter so we don't miss
>> this character
>> +            }
>> +            if(!stop)
>> +                sb.append((char)singleByte);
>> +        } while(!stop);
>> +
>> +        return sb.toString();
>> +    }
>> +
>> +    /**
>> +     * @return the recursivlyRead
>> +     */
>> +    public boolean isRecursivlyRead() {
>> +        return recursivlyRead;
>> +    }
>> +
>> +    /**
>> +     * @param recursivlyRead the recursivlyRead to set
>> +     */
>> +    public void setRecursivlyRead(boolean recursivlyRead) {
>> +        this.recursivlyRead = recursivlyRead;
>> +    }
>> +}
>>
>> Added:
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/ConformingPDDocument.java
>>
>> URL:
>> http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/ConformingPDDocument.java?rev=1142109&view=auto
>>
>> ==============================================================================
>>
>> ---
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/ConformingPDDocument.java
>> (added)
>> +++
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/ConformingPDDocument.java
>> Fri Jul  1 22:28:23 2011
>> @@ -0,0 +1,115 @@
>> +/*
>> + *  Copyright 2011 adam.
>> + *
>> + *  Licensed under the Apache License, Version 2.0 (the "License");
>> + *  you may not use this file except in compliance with the License.
>> + *  You may obtain a copy of the License at
>> + *
>> + *       http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + *  Unless required by applicable law or agreed to in writing, software
>> + *  distributed under the License is distributed on an "AS IS" BASIS,
>> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + *  See the License for the specific language governing permissions and
>> + *  limitations under the License.
>> + *  under the License.
>> + */
>> +
>> +package org.apache.pdfbox.pdmodel;
>> +
>> +import java.io.File;
>> +import java.io.IOException;
>> +import java.util.ArrayList;
>> +import java.util.HashMap;
>> +import java.util.List;
>> +import java.util.Map;
>> +import org.apache.pdfbox.cos.COSBase;
>> +import org.apache.pdfbox.cos.COSDocument;
>> +import org.apache.pdfbox.pdfparser.ConformingPDFParser;
>> +import org.apache.pdfbox.persistence.util.COSObjectKey;
>> +
>> +/**
>> + *
>> + * @author adam
>> + */
>> +public class ConformingPDDocument extends PDDocument {
>> +    /**
>> +     * Maps ObjectKeys to a COSObject. Note that references to these
>> objects
>> +     * are also stored in COSDictionary objects that map a name to a
>> specific object.
>> +     */
>> +    private final Map<COSObjectKey, COSBase>  objectPool =
>> +        new HashMap<COSObjectKey, COSBase>();
>> +    private ConformingPDFParser parser = null;
>> +
>> +    public ConformingPDDocument() throws IOException {
>> +        super();
>> +    }
>> +
>> +    public ConformingPDDocument(COSDocument doc) throws IOException {
>> +        super(doc);
>> +    }
>> +
>> +    /**
>> +     * This will load a document from an input stream.
>> +     * @param input The File which contains the document.
>> +     * @return The document that was loaded.
>> +     * @throws IOException If there is an error reading from the stream.
>> +     */
>> +    public static PDDocument load(File input) throws IOException {
>> +        ConformingPDFParser parser = new ConformingPDFParser(input);
>> +        parser.parse();
>> +        return parser.getPDDocument();
>> +    }
>> +
>> +    /**
>> +     * This will get an object from the pool.
>> +     * @param key The object key.
>> +     * @return The object in the pool or a new one if it has not been
>> parsed yet.
>> +     * @throws IOException If there is an error getting the proxy
>> object.
>> +     */
>> +    public COSBase getObjectFromPool(COSObjectKey key) throws
>> IOException {
>> +        return objectPool.get(key);
>> +    }
>> +
>> +    /**
>> +     * This will get an object from the pool.
>> +     * @param key The object key.
>> +     * @return The object in the pool or a new one if it has not been
>> parsed yet.
>> +     * @throws IOException If there is an error getting the proxy
>> object.
>> +     */
>> +    public List<COSObjectKey>  getObjectKeysFromPool() throws
>> IOException {
>> +        List<COSObjectKey>  keys = new ArrayList<COSObjectKey>();
>> +        for(COSObjectKey key : objectPool.keySet())
>> +            keys.add(key);
>> +        return keys;
>> +    }
>> +
>> +    /**
>> +     * This will get an object from the pool.
>> +     * @param number the object number
>> +     * @param generation the generation of this object you wish to load
>> +     * @return The object in the pool
>> +     * @throws IOException If there is an error getting the proxy
>> object.
>> +     */
>> +    public COSBase getObjectFromPool(long number, long generation)
>> throws IOException {
>> +        return objectPool.get(new COSObjectKey(number, generation));
>> +    }
>> +
>> +    public void putObjectInPool(COSBase object, long number, long
>> generation) {
>> +        objectPool.put(new COSObjectKey(number, generation), object);
>> +    }
>> +
>> +    /**
>> +     * @return the parser
>> +     */
>> +    public ConformingPDFParser getParser() {
>> +        return parser;
>> +    }
>> +
>> +    /**
>> +     * @param parser the parser to set
>> +     */
>> +    public void setParser(ConformingPDFParser parser) {
>> +        this.parser = parser;
>> +    }
>> +}
>>
>> Added:
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/common/XrefEntry.java
>>
>> URL:
>> http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/common/XrefEntry.java?rev=1142109&view=auto
>>
>> ==============================================================================
>>
>> ---
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/common/XrefEntry.java
>> (added)
>> +++
>> pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/common/XrefEntry.java
>> Fri Jul  1 22:28:23 2011
>> @@ -0,0 +1,43 @@
>> +/*
>> + *  Copyright 2011 adam.
>> + *
>> + *  Licensed under the Apache License, Version 2.0 (the "License");
>> + *  you may not use this file except in compliance with the License.
>> + *  You may obtain a copy of the License at
>> + *
>> + *       http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + *  Unless required by applicable law or agreed to in writing, software
>> + *  distributed under the License is distributed on an "AS IS" BASIS,
>> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + *  See the License for the specific language governing permissions and
>> + *  limitations under the License.
>> + *  under the License.
>> + */
>> +
>> +package org.apache.pdfbox.pdmodel.common;
>> +
>> +/**
>> + *
>> + * @author adam
>> + */
>> +public class XrefEntry {
>> +    private int objectNumber = 0;
>> +    private int byteOffset = 0;
>> +    private int generation = 0;
>> +    private boolean inUse = true;
>> +
>> +    public XrefEntry() {
>> +    }
>> +
>> +    public XrefEntry(int objectNumber, int byteOffset, int
>> generation, String inUse) {
>> +        this.objectNumber = objectNumber;
>> +        this.byteOffset = byteOffset;
>> +        this.generation = generation;
>> +        this.inUse = "n".equals(inUse);
>> +    }
>> +
>> +    public int getByteOffset() {
>> +        return byteOffset;
>> +    }
>> +}
>>
>> Added:
>> pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdfparser/ConformingPDFParserTest.java
>>
>> URL:
>> http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdfparser/ConformingPDFParserTest.java?rev=1142109&view=auto
>>
>> ==============================================================================
>>
>> ---
>> pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdfparser/ConformingPDFParserTest.java
>> (added)
>> +++
>> pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdfparser/ConformingPDFParserTest.java
>> Fri Jul  1 22:28:23 2011
>> @@ -0,0 +1,73 @@
>> +/*
>> + *  Copyright 2010 adam.
>> + *
>> + *  Licensed under the Apache License, Version 2.0 (the "License");
>> + *  you may not use this file except in compliance with the License.
>> + *  You may obtain a copy of the License at
>> + *
>> + *       http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + *  Unless required by applicable law or agreed to in writing, software
>> + *  distributed under the License is distributed on an "AS IS" BASIS,
>> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + *  See the License for the specific language governing permissions and
>> + *  limitations under the License.
>> + *  under the License.
>> + */
>> +
>> +package org.apache.pdfbox.pdfparser;
>> +
>> +import java.io.File;
>> +import java.net.URL;
>> +import org.apache.pdfbox.cos.COSDictionary;
>> +import org.junit.After;
>> +import org.junit.AfterClass;
>> +import org.junit.Before;
>> +import org.junit.BeforeClass;
>> +import org.junit.Test;
>> +import static org.junit.Assert.*;
>> +
>> +/**
>> + *
>> + * @author adam
>> + */
>> +public class ConformingPDFParserTest {
>> +
>> +    public ConformingPDFParserTest() {
>> +    }
>> +
>> +    @BeforeClass
>> +    public static void setUpClass() throws Exception {
>> +    }
>> +
>> +    @AfterClass
>> +    public static void tearDownClass() throws Exception {
>> +    }
>> +
>> +    @Before
>> +    public void setUp() {
>> +    }
>> +
>> +    @After
>> +    public void tearDown() {
>> +    }
>> +
>> +    /**
>> +     * Test of parse method, of class ConformingPDFParser.
>> +     */
>> +    @Test
>> +    public void testParse() throws Exception {
>> +        URL inputUrl =
>> ConformingPDFParser.class.getResource("gdb-refcard.pdf");
>> +        File inputFile = new File(inputUrl.toURI());
>> +        ConformingPDFParser instance = new
>> ConformingPDFParser(inputFile);
>> +        instance.parse();
>> +
>> +        COSDictionary trailer = instance.getDocument().getTrailer();
>> +        assertNotNull(trailer);
>> +        System.out.println("Trailer: " +
>> instance.getDocument().getTrailer().toString());
>> +        assertEquals(3, trailer.size());
>> +        assertNotNull(trailer.getDictionaryObject("Root"));
>> +        assertNotNull(trailer.getDictionaryObject("Info"));
>> +        assertNotNull(trailer.getDictionaryObject("Size"));
>> +    }
>> +}
>> \ No newline at end of file
>>
>> Modified:
>> pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/TestPDDocumentCatalog.java
>>
>> URL:
>> http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/TestPDDocumentCatalog.java?rev=1142109&r1=1142108&r2=1142109&view=diff
>>
>> ==============================================================================
>>
>> ---
>> pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/TestPDDocumentCatalog.java
>> (original)
>> +++
>> pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/TestPDDocumentCatalog.java
>> Fri Jul  1 22:28:23 2011
>> @@ -16,7 +16,6 @@
>>    */
>>   package org.apache.pdfbox.pdmodel;
>>
>> -import java.io.File;
>>   import junit.framework.TestCase;
>>
>>   public class TestPDDocumentCatalog extends TestCase {
>> @@ -62,13 +61,29 @@ public class TestPDDocumentCatalog exten
>>               doc =
>> PDDocument.load(TestPDDocumentCatalog.class.getResourceAsStream("page_label.pdf"));
>>
>>               PDDocumentCatalog cat = doc.getDocumentCatalog();
>>               // getLabelsByPageIndices() should not throw an exception
>> -            String[] labels =
>> cat.getPageLabels().getLabelsByPageIndices();
>> +            cat.getPageLabels().getLabelsByPageIndices();
>>           } catch(Exception e) {
>> -            e.printStackTrace();
>>               fail("Threw exception!");
>>           } finally {
>>               if(doc != null)
>>                   doc.close();
>>           }
>>       }
>> +
>> +    /**
>> +     * Test case for
>> +     *<a href="https://issues.apache.org/jira/browse/PDFBOX-911";
>> +     *>PDFBOX-911</a>  - Method PDDocument.getNumberOfPages() returns
>> wrong
>> +     * number of pages
>> +     */
>> +    public void testGetNumberOfPages() throws Exception {
>> +        PDDocument doc = null;
>> +        try {
>> +            doc =
>> PDDocument.load(TestPDDocumentCatalog.class.getResource("test.unc.pdf"));
>> +            assertEquals(4, doc.getNumberOfPages());
>> +        } finally {
>> +            if(doc != null)
>> +                doc.close();
>> +        }
>> +    }
>>   }
>>
>> Added:
>> pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdfparser/gdb-refcard.pdf
>>
>> URL:
>> http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdfparser/gdb-refcard.pdf?rev=1142109&view=auto
>>
>> ==============================================================================
>>
>> Binary file - no diff available.
>>
>> Propchange:
>> pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdfparser/gdb-refcard.pdf
>>
>> ------------------------------------------------------------------------------
>>
>>      svn:mime-type = application/octet-stream
>>
>>
> 

Reply via email to