aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/pdfbox/cos
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/pdfbox/cos')
-rw-r--r--src/main/java/org/pdfbox/cos/COSArray.java492
-rw-r--r--src/main/java/org/pdfbox/cos/COSBase.java86
-rw-r--r--src/main/java/org/pdfbox/cos/COSBoolean.java161
-rw-r--r--src/main/java/org/pdfbox/cos/COSDictionary.java1167
-rw-r--r--src/main/java/org/pdfbox/cos/COSDocument.java518
-rw-r--r--src/main/java/org/pdfbox/cos/COSFloat.java173
-rw-r--r--src/main/java/org/pdfbox/cos/COSInteger.java190
-rw-r--r--src/main/java/org/pdfbox/cos/COSName.java572
-rw-r--r--src/main/java/org/pdfbox/cos/COSNull.java88
-rw-r--r--src/main/java/org/pdfbox/cos/COSNumber.java115
-rw-r--r--src/main/java/org/pdfbox/cos/COSObject.java226
-rw-r--r--src/main/java/org/pdfbox/cos/COSStream.java495
-rw-r--r--src/main/java/org/pdfbox/cos/COSString.java403
-rw-r--r--src/main/java/org/pdfbox/cos/ICOSVisitor.java132
-rw-r--r--src/main/java/org/pdfbox/cos/package.html12
15 files changed, 4830 insertions, 0 deletions
diff --git a/src/main/java/org/pdfbox/cos/COSArray.java b/src/main/java/org/pdfbox/cos/COSArray.java
new file mode 100644
index 0000000..cb7d278
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSArray.java
@@ -0,0 +1,492 @@
+/**
+ * Copyright (c) 2003-2005, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+
+
+import org.pdfbox.exceptions.COSVisitorException;
+import org.pdfbox.pdmodel.common.COSObjectable;
+
+/**
+ * An array of PDFBase objects as part of the PDF document.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.22 $
+ */
+public class COSArray extends COSBase
+{
+ private List objects = new ArrayList();
+
+ /**
+ * Constructor.
+ */
+ public COSArray()
+ {
+ //default constructor
+ }
+
+ /**
+ * This will add an object to the array.
+ *
+ * @param object The object to add to the array.
+ */
+ public void add( COSBase object )
+ {
+ objects.add( object );
+ }
+
+ /**
+ * This will add an object to the array.
+ *
+ * @param object The object to add to the array.
+ */
+ public void add( COSObjectable object )
+ {
+ objects.add( object.getCOSObject() );
+ }
+
+ /**
+ * Add the specified object at the ith location and push the rest to the
+ * right.
+ *
+ * @param i The index to add at.
+ * @param object The object to add at that index.
+ */
+ public void add( int i, COSBase object)
+ {
+ objects.add( i, object );
+ }
+
+ /**
+ * This will remove all of the objects in the collection.
+ */
+ public void clear()
+ {
+ objects.clear();
+ }
+
+ /**
+ * This will remove all of the objects in the collection.
+ *
+ * @param objectsList The list of objects to remove from the collection.
+ */
+ public void removeAll( Collection objectsList )
+ {
+ objects.removeAll( objectsList );
+ }
+
+ /**
+ * This will retain all of the objects in the collection.
+ *
+ * @param objectsList The list of objects to retain from the collection.
+ */
+ public void retainAll( Collection objectsList )
+ {
+ objects.retainAll( objectsList );
+ }
+
+ /**
+ * This will add an object to the array.
+ *
+ * @param objectsList The object to add to the array.
+ */
+ public void addAll( Collection objectsList )
+ {
+ objects.addAll( objectsList );
+ }
+
+ /**
+ * This will add all objects to this array.
+ *
+ * @param objectList The objects to add.
+ */
+ public void addAll( COSArray objectList )
+ {
+ objects.addAll( objectList.objects );
+ }
+
+ /**
+ * Add the specified object at the ith location and push the rest to the
+ * right.
+ *
+ * @param i The index to add at.
+ * @param objectList The object to add at that index.
+ */
+ public void addAll( int i, Collection objectList )
+ {
+ objects.addAll( i, objectList );
+ }
+
+ /**
+ * This will set an object at a specific index.
+ *
+ * @param index zero based index into array.
+ * @param object The object to set.
+ */
+ public void set( int index, COSBase object )
+ {
+ objects.set( index, object );
+ }
+
+ /**
+ * This will set an object at a specific index.
+ *
+ * @param index zero based index into array.
+ * @param intVal The object to set.
+ */
+ public void set( int index, int intVal )
+ {
+ objects.set( index, new COSInteger( intVal ) );
+ }
+
+ /**
+ * This will set an object at a specific index.
+ *
+ * @param index zero based index into array.
+ * @param object The object to set.
+ */
+ public void set( int index, COSObjectable object )
+ {
+ COSBase base = null;
+ if( object != null )
+ {
+ base = object.getCOSObject();
+ }
+ objects.set( index, base );
+ }
+
+ /**
+ * This will get an object from the array. This will dereference the object.
+ * If the object is COSNull then null will be returned.
+ *
+ * @param index The index into the array to get the object.
+ *
+ * @return The object at the requested index.
+ */
+ public COSBase getObject( int index )
+ {
+ Object obj = objects.get( index );
+ if( obj instanceof COSObject )
+ {
+ obj = ((COSObject)obj).getObject();
+ }
+ if( obj instanceof COSNull )
+ {
+ obj = null;
+ }
+ return (COSBase)obj;
+ }
+
+ /**
+ * This will get an object from the array. This will NOT derefernce
+ * the COS object.
+ *
+ * @param index The index into the array to get the object.
+ *
+ * @return The object at the requested index.
+ */
+ public COSBase get( int index )
+ {
+ return (COSBase)objects.get( index );
+ }
+
+ /**
+ * Get the value of the array as an integer.
+ *
+ * @param index The index into the list.
+ *
+ * @return The value at that index or -1 if it is null.
+ */
+ public int getInt( int index )
+ {
+ return getInt( index, -1 );
+ }
+
+ /**
+ * Get the value of the array as an integer, return the default if it does
+ * not exist.
+ *
+ * @param index The value of the array.
+ * @param defaultValue The value to return if the value is null.
+ * @return The value at the index or the defaultValue.
+ */
+ public int getInt( int index, int defaultValue )
+ {
+ int retval = defaultValue;
+ if( defaultValue < size() )
+ {
+ COSNumber number = (COSNumber)get( index );
+ if( number != null )
+ {
+ retval = number.intValue();
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * Set the value in the array as an integer.
+ *
+ * @param index The index into the array.
+ * @param value The value to set.
+ */
+ public void setInt( int index, int value )
+ {
+ set( index, new COSInteger( value ) );
+ }
+
+ /**
+ * Set the value in the array as a name.
+ * @param index The index into the array.
+ * @param name The name to set in the array.
+ */
+ public void setName( int index, String name )
+ {
+ set( index, COSName.getPDFName( name ) );
+ }
+
+ /**
+ * Get the value of the array as a string.
+ *
+ * @param index The index into the array.
+ * @return The name converted to a string or null if it does not exist.
+ */
+ public String getName( int index )
+ {
+ return getName( index, null );
+ }
+
+ /**
+ * Get an entry in the array that is expected to be a COSName.
+ * @param index The index into the array.
+ * @param defaultValue The value to return if it is null.
+ * @return The value at the index or defaultValue if none is found.
+ */
+ public String getName( int index, String defaultValue )
+ {
+ String retval = defaultValue;
+ if( index < size() )
+ {
+ COSName name = (COSName)get( index );
+ if( name != null )
+ {
+ retval = name.getName();
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * Set the value in the array as a string.
+ * @param index The index into the array.
+ * @param string The string to set in the array.
+ */
+ public void setString( int index, String string )
+ {
+ set( index, new COSString( string ) );
+ }
+
+ /**
+ * Get the value of the array as a string.
+ *
+ * @param index The index into the array.
+ * @return The string or null if it does not exist.
+ */
+ public String getString( int index )
+ {
+ return getString( index, null );
+ }
+
+ /**
+ * Get an entry in the array that is expected to be a COSName.
+ * @param index The index into the array.
+ * @param defaultValue The value to return if it is null.
+ * @return The value at the index or defaultValue if none is found.
+ */
+ public String getString( int index, String defaultValue )
+ {
+ String retval = defaultValue;
+ if( index < size() )
+ {
+ COSString string = (COSString)get( index );
+ if( string != null )
+ {
+ retval = string.getString();
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * This will get the size of this array.
+ *
+ * @return The number of elements in the array.
+ */
+ public int size()
+ {
+ return objects.size();
+ }
+
+ /**
+ * This will remove an element from the array.
+ *
+ * @param i The index of the object to remove.
+ *
+ * @return The object that was removed.
+ */
+ public COSBase remove( int i )
+ {
+ return (COSBase)objects.remove( i );
+ }
+
+ /**
+ * This will remove an element from the array.
+ *
+ * @param o The object to remove.
+ *
+ * @return The object that was removed.
+ */
+ public boolean remove( COSBase o )
+ {
+ return objects.remove( o );
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ public String toString()
+ {
+ return "COSArray{" + objects + "}";
+ }
+
+ /**
+ * Get access to the list.
+ *
+ * @return an iterator over the array elements
+ */
+ public Iterator iterator()
+ {
+ return objects.iterator();
+ }
+
+ /**
+ * This will return the index of the entry or -1 if it is not found.
+ *
+ * @param object The object to search for.
+ * @return The index of the object or -1.
+ */
+ public int indexOf( COSBase object )
+ {
+ int retval = -1;
+ for( int i=0; retval < 0 && i<size(); i++ )
+ {
+ if( get( i ).equals( object ) )
+ {
+ retval = i;
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * This will add null values until the size of the array is at least
+ * as large as the parameter. If the array is already larger than the
+ * parameter then nothing is done.
+ *
+ * @param size The desired size of the array.
+ */
+ public void growToSize( int size )
+ {
+ growToSize( size, null );
+ }
+
+ /**
+ * This will add the object until the size of the array is at least
+ * as large as the parameter. If the array is already larger than the
+ * parameter then nothing is done.
+ *
+ * @param size The desired size of the array.
+ * @param object The object to fill the array with.
+ */
+ public void growToSize( int size, COSBase object )
+ {
+ while( size() < size )
+ {
+ add( object );
+ }
+ }
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return any object, depending on the visitor implementation, or null
+ * @throws COSVisitorException If an error occurs while visiting this object.
+ */
+ public Object accept(ICOSVisitor visitor) throws COSVisitorException
+ {
+ return visitor.visitFromArray(this);
+ }
+
+ /**
+ * This will take an COSArray of numbers and convert it to a float[].
+ *
+ * @return This COSArray as an array of float numbers.
+ */
+ public float[] toFloatArray()
+ {
+ float[] retval = new float[size()];
+ for( int i=0; i<size(); i++ )
+ {
+ retval[i] = ((COSNumber)getObject( i )).floatValue();
+ }
+ return retval;
+ }
+
+ /**
+ * Clear the current contents of the COSArray and set it with the float[].
+ *
+ * @param value The new value of the float array.
+ */
+ public void setFloatArray( float[] value )
+ {
+ this.clear();
+ for( int i=0; i<value.length; i++ )
+ {
+ add( new COSFloat( value[i] ) );
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/COSBase.java b/src/main/java/org/pdfbox/cos/COSBase.java
new file mode 100644
index 0000000..85e0c45
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSBase.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2003-2005, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import org.pdfbox.filter.FilterManager;
+import org.pdfbox.pdmodel.common.COSObjectable;
+
+import org.pdfbox.exceptions.COSVisitorException;
+
+/**
+ * The base object that all objects in the PDF document will extend.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.13 $
+ */
+public abstract class COSBase implements COSObjectable
+{
+ /**
+ * Constructor.
+ */
+ public COSBase()
+ {
+ }
+
+ /**
+ * This will get the filter manager to use to filter streams.
+ *
+ * @return The filter manager.
+ */
+ public FilterManager getFilterManager()
+ {
+ /**
+ * @todo move this to PDFdocument or something better
+ */
+ return new FilterManager();
+ }
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getCOSObject()
+ {
+ return this;
+ }
+
+
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return any object, depending on the visitor implementation, or null
+ * @throws COSVisitorException If an error occurs while visiting this object.
+ */
+ public abstract Object accept(ICOSVisitor visitor) throws COSVisitorException;
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/COSBoolean.java b/src/main/java/org/pdfbox/cos/COSBoolean.java
new file mode 100644
index 0000000..0fe2d6f
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSBoolean.java
@@ -0,0 +1,161 @@
+/**
+ * Copyright (c) 2003, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.pdfbox.exceptions.COSVisitorException;
+
+/**
+ * This class represents a boolean value in the PDF document.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.13 $
+ */
+public class COSBoolean extends COSBase
+{
+ /**
+ * The true boolean token.
+ */
+ public static final byte[] TRUE_BYTES = new byte[]{ 116, 114, 117, 101 }; //"true".getBytes( "ISO-8859-1" );
+ /**
+ * The false boolean token.
+ */
+ public static final byte[] FALSE_BYTES = new byte[]{ 102, 97, 108, 115, 101 }; //"false".getBytes( "ISO-8859-1" );
+
+ /**
+ * The PDF true value.
+ */
+ public static final COSBoolean TRUE = new COSBoolean( true );
+
+ /**
+ * The PDF false value.
+ */
+ public static final COSBoolean FALSE = new COSBoolean( false );
+
+ private boolean value;
+
+ /**
+ * Constructor.
+ *
+ * @param aValue The boolean value.
+ */
+ private COSBoolean(boolean aValue )
+ {
+ value = aValue;
+ }
+
+ /**
+ * This will get the value that this object wraps.
+ *
+ * @return The boolean value of this object.
+ */
+ public boolean getValue()
+ {
+ return value;
+ }
+
+ /**
+ * This will get the value that this object wraps.
+ *
+ * @return The boolean value of this object.
+ */
+ public Boolean getValueAsObject()
+ {
+ return (value?Boolean.TRUE:Boolean.FALSE);
+ }
+
+ /**
+ * This will get the boolean value.
+ *
+ * @param value Parameter telling which boolean value to get.
+ *
+ * @return The single boolean instance that matches the parameter.
+ */
+ public static COSBoolean getBoolean( boolean value )
+ {
+ return (value?TRUE:FALSE);
+ }
+
+ /**
+ * This will get the boolean value.
+ *
+ * @param value Parameter telling which boolean value to get.
+ *
+ * @return The single boolean instance that matches the parameter.
+ */
+ public static COSBoolean getBoolean( Boolean value )
+ {
+ return getBoolean( value.booleanValue() );
+ }
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return any object, depending on the visitor implementation, or null
+ * @throws COSVisitorException If an error occurs while visiting this object.
+ */
+ public Object accept(ICOSVisitor visitor) throws COSVisitorException
+ {
+ return visitor.visitFromBoolean(this);
+ }
+
+ /**
+ * Return a string representation of this object.
+ *
+ * @return The string value of this object.
+ */
+ public String toString()
+ {
+ return String.valueOf( value );
+ }
+
+ /**
+ * This will write this object out to a PDF stream.
+ *
+ * @param output The stream to write this object out to.
+ *
+ * @throws IOException If an error occurs while writing out this object.
+ */
+ public void writePDF( OutputStream output ) throws IOException
+ {
+ if( value )
+ {
+ output.write( TRUE_BYTES );
+ }
+ else
+ {
+ output.write( FALSE_BYTES );
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/COSDictionary.java b/src/main/java/org/pdfbox/cos/COSDictionary.java
new file mode 100644
index 0000000..eb92433
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSDictionary.java
@@ -0,0 +1,1167 @@
+/**
+ * Copyright (c) 2003-2005, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import java.util.Iterator;
+
+import org.pdfbox.exceptions.COSVisitorException;
+
+import org.pdfbox.pdmodel.common.COSObjectable;
+import org.pdfbox.util.DateConverter;
+
+/**
+ * This class represents a dictionary where name/value pairs reside.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.29 $
+ */
+public class COSDictionary extends COSBase
+{
+ private static final String PATH_SEPARATOR = "/";
+
+ /**
+ * These are all of the items in the dictionary.
+ */
+ private Map items = new HashMap();
+
+ /**
+ * Used to store original sequence of keys, for testing.
+ */
+ private List keys = new ArrayList();
+
+ /**
+ * Constructor.
+ */
+ public COSDictionary()
+ {
+ //default constructor
+ }
+
+ /**
+ * Copy Constructor. This will make a shallow copy of this dictionary.
+ *
+ * @param dict The dictionary to copy.
+ */
+ public COSDictionary( COSDictionary dict )
+ {
+ items = new HashMap( dict.items );
+ keys = new ArrayList( dict.keys );
+ }
+
+ /**
+ * This will return the number of elements in this dictionary.
+ *
+ * @return The number of elements in the dictionary.
+ */
+ public int size()
+ {
+ return keys.size();
+ }
+
+ /**
+ * This will clear all items in the map.
+ */
+ public void clear()
+ {
+ items.clear();
+ keys.clear();
+ }
+
+ /**
+ * 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.
+ */
+ public COSBase getDictionaryObject( String key )
+ {
+ return getDictionaryObject( COSName.getPDFName( key ) );
+ }
+
+ /**
+ * This is a special case of getDictionaryObject that takes multiple keys, it will handle
+ * the situation where multiple keys could get the same value, ie if either CS or ColorSpace
+ * is used to get the colorspace.
+ * 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 keyList The list of keys to find a value.
+ *
+ * @return The object that matches the key.
+ */
+ public COSBase getDictionaryObject( String[] keyList )
+ {
+ COSBase retval = null;
+ for( int i=0; i<keyList.length && retval == null; i++ )
+ {
+ retval = getDictionaryObject( COSName.getPDFName( keyList[i] ) );
+ }
+ return retval;
+ }
+
+ /**
+ * 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.
+ */
+ public COSBase getDictionaryObject( COSName key )
+ {
+ COSBase retval = (COSBase)items.get( key );
+ if( retval instanceof COSObject )
+ {
+ retval = ((COSObject)retval).getObject();
+ }
+ if( retval instanceof COSNull )
+ {
+ retval = null;
+ }
+ return retval;
+ }
+
+ /**
+ * This will set an item in the dictionary. If value is null then the result
+ * will be the same as removeItem( key ).
+ *
+ * @param key The key to the dictionary object.
+ * @param value The value to the dictionary object.
+ */
+ public void setItem( COSName key, COSBase value )
+ {
+ if( value == null )
+ {
+ removeItem( key );
+ }
+ else
+ {
+ if (!items.containsKey(key))
+ {
+ // insert only if not already there
+ keys.add(key);
+ }
+ items.put( key, value );
+ }
+ }
+
+ /**
+ * This will set an item in the dictionary. If value is null then the result
+ * will be the same as removeItem( key ).
+ *
+ * @param key The key to the dictionary object.
+ * @param value The value to the dictionary object.
+ */
+ public void setItem( COSName key, COSObjectable value )
+ {
+ COSBase base = null;
+ if( value != null )
+ {
+ base = value.getCOSObject();
+ }
+ setItem( key, base );
+ }
+
+ /**
+ * This will set an item in the dictionary. If value is null then the result
+ * will be the same as removeItem( key ).
+ *
+ * @param key The key to the dictionary object.
+ * @param value The value to the dictionary object.
+ */
+ public void setItem( String key, COSObjectable value )
+ {
+ setItem( COSName.getPDFName( key ), value );
+ }
+
+ /**
+ * This will set an item in the dictionary.
+ *
+ * @param key The key to the dictionary object.
+ * @param value The value to the dictionary object.
+ */
+ public void setBoolean( String key, boolean value )
+ {
+ setItem( COSName.getPDFName( key ), COSBoolean.getBoolean( value ) );
+ }
+
+ /**
+ * This will set an item in the dictionary.
+ *
+ * @param key The key to the dictionary object.
+ * @param value The value to the dictionary object.
+ */
+ public void setBoolean( COSName key, boolean value )
+ {
+ setItem( key , COSBoolean.getBoolean( value ) );
+ }
+
+ /**
+ * This will set an item in the dictionary. If value is null then the result
+ * will be the same as removeItem( key ).
+ *
+ * @param key The key to the dictionary object.
+ * @param value The value to the dictionary object.
+ */
+ public void setItem( String key, COSBase value )
+ {
+ setItem( COSName.getPDFName( key ), value );
+ }
+
+ /**
+ * This is a convenience method that will convert the value to a COSName
+ * object. If it is null then the object will be removed.
+ *
+ * @param key The key to the object,
+ * @param value The string value for the name.
+ */
+ public void setName( String key, String value )
+ {
+ setName( COSName.getPDFName( key ), value );
+ }
+
+ /**
+ * This is a convenience method that will convert the value to a COSName
+ * object. If it is null then the object will be removed.
+ *
+ * @param key The key to the object,
+ * @param value The string value for the name.
+ */
+ public void setName( COSName key, String value )
+ {
+ COSName name = null;
+ if( value != null )
+ {
+ name = COSName.getPDFName( value );
+ }
+ setItem( key, name );
+ }
+
+ /**
+ * Set the value of a date entry in the dictionary.
+ *
+ * @param key The key to the date value.
+ * @param date The date value.
+ */
+ public void setDate( String key, Calendar date )
+ {
+ setDate( COSName.getPDFName( key ), date );
+ }
+
+ /**
+ * Set the date object.
+ *
+ * @param key The key to the date.
+ * @param date The date to set.
+ */
+ public void setDate( COSName key, Calendar date )
+ {
+ setString( key, DateConverter.toString( date ) );
+ }
+
+ /**
+ * Set the value of a date entry in the dictionary.
+ *
+ * @param embedded The embedded dictionary.
+ * @param key The key to the date value.
+ * @param date The date value.
+ */
+ public void setEmbeddedDate( String embedded, String key, Calendar date )
+ {
+ setEmbeddedDate( embedded, COSName.getPDFName( key ), date );
+ }
+
+ /**
+ * Set the date object.
+ *
+ * @param embedded The embedded dictionary.
+ * @param key The key to the date.
+ * @param date The date to set.
+ */
+ public void setEmbeddedDate( String embedded, COSName key, Calendar date )
+ {
+ COSDictionary dic = (COSDictionary)getDictionaryObject( embedded );
+ if( dic == null && date != null )
+ {
+ dic = new COSDictionary();
+ setItem( embedded, dic );
+ }
+ if( dic != null )
+ {
+ dic.setDate( key, date );
+ }
+ }
+
+ /**
+ * This is a convenience method that will convert the value to a COSString
+ * object. If it is null then the object will be removed.
+ *
+ * @param key The key to the object,
+ * @param value The string value for the name.
+ */
+ public void setString( String key, String value )
+ {
+ setString( COSName.getPDFName( key ), value );
+ }
+
+ /**
+ * This is a convenience method that will convert the value to a COSString
+ * object. If it is null then the object will be removed.
+ *
+ * @param key The key to the object,
+ * @param value The string value for the name.
+ */
+ public void setString( COSName key, String value )
+ {
+ COSString name = null;
+ if( value != null )
+ {
+ name = new COSString( value );
+ }
+ setItem( key, name );
+ }
+
+ /**
+ * This is a convenience method that will convert the value to a COSString
+ * object. If it is null then the object will be removed.
+ *
+ * @param embedded The embedded dictionary to set the item in.
+ * @param key The key to the object,
+ * @param value The string value for the name.
+ */
+ public void setEmbeddedString( String embedded, String key, String value )
+ {
+ setEmbeddedString( embedded, COSName.getPDFName( key ), value );
+ }
+
+ /**
+ * This is a convenience method that will convert the value to a COSString
+ * object. If it is null then the object will be removed.
+ *
+ * @param embedded The embedded dictionary to set the item in.
+ * @param key The key to the object,
+ * @param value The string value for the name.
+ */
+ public void setEmbeddedString( String embedded, COSName key, String value )
+ {
+ COSDictionary dic = (COSDictionary)getDictionaryObject( embedded );
+ if( dic == null && value != null )
+ {
+ dic = new COSDictionary();
+ setItem( embedded, dic );
+ }
+ if( dic != null )
+ {
+ dic.setString( key, value );
+ }
+ }
+
+ /**
+ * This is a convenience method that will convert the value to a COSInteger
+ * object.
+ *
+ * @param key The key to the object,
+ * @param value The int value for the name.
+ */
+ public void setInt( String key, int value )
+ {
+ setInt( COSName.getPDFName( key ), value );
+ }
+
+ /**
+ * This is a convenience method that will convert the value to a COSInteger
+ * object.
+ *
+ * @param key The key to the object,
+ * @param value The int value for the name.
+ */
+ public void setInt( COSName key, int value )
+ {
+ COSInteger intVal = null;
+ intVal = new COSInteger(value);
+ setItem( key, intVal );
+ }
+
+ /**
+ * This is a convenience method that will convert the value to a COSInteger
+ * object.
+ *
+ * @param embeddedDictionary The embedded dictionary.
+ * @param key The key to the object,
+ * @param value The int value for the name.
+ */
+ public void setEmbeddedInt( String embeddedDictionary, String key, int value )
+ {
+ setEmbeddedInt( embeddedDictionary, COSName.getPDFName( key ), value );
+ }
+
+ /**
+ * This is a convenience method that will convert the value to a COSInteger
+ * object.
+ *
+ * @param embeddedDictionary The embedded dictionary.
+ * @param key The key to the object,
+ * @param value The int value for the name.
+ */
+ public void setEmbeddedInt( String embeddedDictionary, COSName key, int value )
+ {
+ COSDictionary embedded = (COSDictionary)getDictionaryObject( embeddedDictionary );
+ if( embedded == null )
+ {
+ embedded = new COSDictionary();
+ setItem( embeddedDictionary, embedded );
+ }
+ embedded.setInt( key, value );
+ }
+
+ /**
+ * This is a convenience method that will convert the value to a COSFloat
+ * object.
+ *
+ * @param key The key to the object,
+ * @param value The int value for the name.
+ */
+ public void setFloat( String key, float value )
+ {
+ setFloat( COSName.getPDFName( key ), value );
+ }
+
+ /**
+ * This is a convenience method that will convert the value to a COSFloat
+ * object.
+ *
+ * @param key The key to the object,
+ * @param value The int value for the name.
+ */
+ public void setFloat( COSName key, float value )
+ {
+ COSFloat fltVal = new COSFloat( value );
+ setItem( key, fltVal );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param key The key to the item in the dictionary.
+ * @return The name converted to a string.
+ */
+ public String getNameAsString( String key )
+ {
+ return getNameAsString( COSName.getPDFName( key ) );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param key The key to the item in the dictionary.
+ * @return The name converted to a string.
+ */
+ public String getNameAsString( COSName key )
+ {
+ String retval = null;
+ COSName name = (COSName)getDictionaryObject( key );
+ if( name != null )
+ {
+ retval = name.getName();
+ }
+ return retval;
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The value to return if the dictionary item is null.
+ * @return The name converted to a string.
+ */
+ public String getNameAsString( String key, String defaultValue )
+ {
+ return getNameAsString( COSName.getPDFName( key ), defaultValue );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The value to return if the dictionary item is null.
+ * @return The name converted to a string.
+ */
+ public String getNameAsString( COSName key, String defaultValue )
+ {
+ String retval = getNameAsString( key );
+ if( retval == null )
+ {
+ retval = defaultValue;
+ }
+ return retval;
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param key The key to the item in the dictionary.
+ * @return The name converted to a string.
+ */
+ public String getString( String key )
+ {
+ return getString( COSName.getPDFName( key ) );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param key The key to the item in the dictionary.
+ * @return The name converted to a string.
+ */
+ public String getString( COSName key )
+ {
+ String retval = null;
+ COSString name = (COSString)getDictionaryObject( key );
+ if( name != null )
+ {
+ retval = name.getString();
+ }
+ return retval;
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The default value to return.
+ * @return The name converted to a string.
+ */
+ public String getString( String key, String defaultValue )
+ {
+ return getString( COSName.getPDFName( key ), defaultValue );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The default value to return.
+ * @return The name converted to a string.
+ */
+ public String getString( COSName key, String defaultValue )
+ {
+ String retval = getString( key );
+ if( retval == null )
+ {
+ retval = defaultValue;
+ }
+ return retval;
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param embedded The embedded dictionary.
+ * @param key The key to the item in the dictionary.
+ * @return The name converted to a string.
+ */
+ public String getEmbeddedString( String embedded, String key )
+ {
+ return getEmbeddedString( embedded, COSName.getPDFName( key ), null );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param embedded The embedded dictionary.
+ * @param key The key to the item in the dictionary.
+ * @return The name converted to a string.
+ */
+ public String getEmbeddedString( String embedded, COSName key )
+ {
+ return getEmbeddedString( embedded, key, null );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param embedded The embedded dictionary.
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The default value to return.
+ * @return The name converted to a string.
+ */
+ public String getEmbeddedString( String embedded, String key, String defaultValue )
+ {
+ return getEmbeddedString( embedded, COSName.getPDFName( key ), defaultValue );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param embedded The embedded dictionary.
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The default value to return.
+ * @return The name converted to a string.
+ */
+ public String getEmbeddedString( String embedded, COSName key, String defaultValue )
+ {
+ String retval = defaultValue;
+ COSDictionary dic = (COSDictionary)getDictionaryObject( embedded );
+ if( dic != null )
+ {
+ retval = dic.getString( key, defaultValue );
+ }
+ return retval;
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param key The key to the item in the dictionary.
+ * @return The name converted to a string.
+ * @throws IOException If there is an error converting to a date.
+ */
+ public Calendar getDate( String key ) throws IOException
+ {
+ return getDate( COSName.getPDFName( key ) );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param key The key to the item in the dictionary.
+ * @return The name converted to a string.
+ *
+ * @throws IOException If there is an error converting to a date.
+ */
+ public Calendar getDate( COSName key ) throws IOException
+ {
+ COSString date = (COSString)getDictionaryObject( key );
+ return DateConverter.toCalendar( date );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a date. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The default value to return.
+ * @return The name converted to a string.
+ * @throws IOException If there is an error converting to a date.
+ */
+ public Calendar getDate( String key, Calendar defaultValue ) throws IOException
+ {
+ return getDate( COSName.getPDFName( key ), defaultValue );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a date. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The default value to return.
+ * @return The name converted to a string.
+ * @throws IOException If there is an error converting to a date.
+ */
+ public Calendar getDate( COSName key, Calendar defaultValue ) throws IOException
+ {
+ Calendar retval = getDate( key );
+ if( retval == null )
+ {
+ retval = defaultValue;
+ }
+ return retval;
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param embedded The embedded dictionary to get.
+ * @param key The key to the item in the dictionary.
+ * @return The name converted to a string.
+ * @throws IOException If there is an error converting to a date.
+ */
+ public Calendar getEmbeddedDate( String embedded, String key ) throws IOException
+ {
+ return getEmbeddedDate( embedded, COSName.getPDFName( key ), null );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a name and convert it to a string. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param embedded The embedded dictionary to get.
+ * @param key The key to the item in the dictionary.
+ * @return The name converted to a string.
+ *
+ * @throws IOException If there is an error converting to a date.
+ */
+ public Calendar getEmbeddedDate( String embedded, COSName key ) throws IOException
+ {
+ return getEmbeddedDate( embedded, key, null );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a date. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param embedded The embedded dictionary to get.
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The default value to return.
+ * @return The name converted to a string.
+ * @throws IOException If there is an error converting to a date.
+ */
+ public Calendar getEmbeddedDate( String embedded, String key, Calendar defaultValue ) throws IOException
+ {
+ return getEmbeddedDate( embedded, COSName.getPDFName( key ), defaultValue );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a date. Null is returned
+ * if the entry does not exist in the dictionary.
+ *
+ * @param embedded The embedded dictionary to get.
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The default value to return.
+ * @return The name converted to a string.
+ * @throws IOException If there is an error converting to a date.
+ */
+ public Calendar getEmbeddedDate( String embedded, COSName key, Calendar defaultValue ) throws IOException
+ {
+ Calendar retval = defaultValue;
+ COSDictionary eDic = (COSDictionary)getDictionaryObject( embedded );
+ if( eDic != null )
+ {
+ retval = eDic.getDate( key, defaultValue );
+ }
+ return retval;
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a cos boolean and convert it to a primitive boolean.
+ *
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The value returned if the entry is null.
+ *
+ * @return The value converted to a boolean.
+ */
+ public boolean getBoolean( String key, boolean defaultValue )
+ {
+ return getBoolean( COSName.getPDFName( key ), defaultValue );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a COSBoolean and convert it to a primitive boolean.
+ *
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The value returned if the entry is null.
+ *
+ * @return The entry converted to a boolean.
+ */
+ public boolean getBoolean( COSName key, boolean defaultValue )
+ {
+ boolean retval = defaultValue;
+ COSBoolean bool = (COSBoolean)getDictionaryObject( key );
+ if( bool != null )
+ {
+ retval = bool.getValue();
+ }
+ return retval;
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be an int. -1 is returned if there is no value.
+ *
+ * @param key The key to the item in the dictionary.
+ * @return The integer value.
+ */
+ public int getInt( String key )
+ {
+ return getInt( COSName.getPDFName( key ) );
+ }
+
+ /**
+ * Get an integer from an embedded dictionary. Useful for 1-1 mappings. default:-1
+ *
+ * @param embeddedDictionary The name of the embedded dictionary.
+ * @param key The key in the embedded dictionary.
+ *
+ * @return The value of the embedded integer.
+ */
+ public int getEmbeddedInt( String embeddedDictionary, String key )
+ {
+ return getEmbeddedInt( embeddedDictionary, COSName.getPDFName( key ) );
+ }
+
+ /**
+ * Get an integer from an embedded dictionary. Useful for 1-1 mappings. default:-1
+ *
+ * @param embeddedDictionary The name of the embedded dictionary.
+ * @param key The key in the embedded dictionary.
+ *
+ * @return The value of the embedded integer.
+ */
+ public int getEmbeddedInt( String embeddedDictionary, COSName key )
+ {
+ return getEmbeddedInt( embeddedDictionary, key, -1 );
+ }
+
+ /**
+ * Get an integer from an embedded dictionary. Useful for 1-1 mappings.
+ *
+ * @param embeddedDictionary The name of the embedded dictionary.
+ * @param key The key in the embedded dictionary.
+ * @param defaultValue The value if there is no embedded dictionary or it does not contain the key.
+ *
+ * @return The value of the embedded integer.
+ */
+ public int getEmbeddedInt( String embeddedDictionary, String key, int defaultValue )
+ {
+ return getEmbeddedInt( embeddedDictionary, COSName.getPDFName( key ), defaultValue );
+ }
+
+
+ /**
+ * Get an integer from an embedded dictionary. Useful for 1-1 mappings.
+ *
+ * @param embeddedDictionary The name of the embedded dictionary.
+ * @param key The key in the embedded dictionary.
+ * @param defaultValue The value if there is no embedded dictionary or it does not contain the key.
+ *
+ * @return The value of the embedded integer.
+ */
+ public int getEmbeddedInt( String embeddedDictionary, COSName key, int defaultValue )
+ {
+ int retval = defaultValue;
+ COSDictionary embedded = (COSDictionary)getDictionaryObject( embeddedDictionary );
+ if( embedded != null )
+ {
+ retval = embedded.getInt( key, defaultValue );
+ }
+ return retval;
+ }
+
+
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be an int. -1 is returned if there is no value.
+ *
+ * @param key The key to the item in the dictionary.
+ * @return The integer value..
+ */
+ public int getInt( COSName key )
+ {
+ return getInt( key, -1 );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be an integer. If the dictionary value is null then the
+ * default Value will be returned.
+ *
+ * @param keyList The key to the item in the dictionary.
+ * @param defaultValue The value to return if the dictionary item is null.
+ * @return The integer value.
+ */
+ public int getInt( String[] keyList, int defaultValue )
+ {
+ int retval = defaultValue;
+ COSNumber obj = (COSNumber)getDictionaryObject( keyList );
+ if( obj != null )
+ {
+ retval = obj.intValue();
+ }
+ return retval;
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be an integer. If the dictionary value is null then the
+ * default Value will be returned.
+ *
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The value to return if the dictionary item is null.
+ * @return The integer value.
+ */
+ public int getInt( String key, int defaultValue )
+ {
+ return getInt( new String []{ key }, defaultValue );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be an integer. If the dictionary value is null then the
+ * default Value will be returned.
+ *
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The value to return if the dictionary item is null.
+ * @return The integer value.
+ */
+ public int getInt( COSName key, int defaultValue )
+ {
+ return getInt(key.getName(), defaultValue );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be an int. -1 is returned if there is no value.
+ *
+ * @param key The key to the item in the dictionary.
+ * @return The float value.
+ */
+ public float getFloat( String key )
+ {
+ return getFloat( COSName.getPDFName( key ) );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be an float. -1 is returned if there is no value.
+ *
+ * @param key The key to the item in the dictionary.
+ * @return The float value.
+ */
+ public float getFloat( COSName key )
+ {
+ return getFloat( key, -1 );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be a float. If the dictionary value is null then the
+ * default Value will be returned.
+ *
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The value to return if the dictionary item is null.
+ * @return The float value.
+ */
+ public float getFloat( String key, float defaultValue )
+ {
+ return getFloat( COSName.getPDFName( key ), defaultValue );
+ }
+
+ /**
+ * This is a convenience method that will get the dictionary object that
+ * is expected to be an float. If the dictionary value is null then the
+ * default Value will be returned.
+ *
+ * @param key The key to the item in the dictionary.
+ * @param defaultValue The value to return if the dictionary item is null.
+ * @return The float value.
+ */
+ public float getFloat( COSName key, float defaultValue )
+ {
+ float retval = defaultValue;
+ COSNumber obj = (COSNumber)getDictionaryObject( key );
+ if( obj != null )
+ {
+ retval = obj.floatValue();
+ }
+ return retval;
+ }
+
+ /**
+ * This will remove an item for the dictionary. This
+ * will do nothing of the object does not exist.
+ *
+ * @param key The key to the item to remove from the dictionary.
+ */
+ public void removeItem( COSName key )
+ {
+ keys.remove( key );
+ items.remove( key );
+ }
+
+ /**
+ * This will do a lookup into the dictionary.
+ *
+ * @param key The key to the object.
+ *
+ * @return The item that matches the key.
+ */
+ public COSBase getItem( COSName key )
+ {
+ return (COSBase)items.get( key );
+ }
+
+
+
+
+
+ /**
+ * This will get the keys for all objects in the dictionary in the sequence that
+ * they were added.
+ *
+ * @return a list of the keys in the sequence of insertion
+ *
+ */
+ public List keyList()
+ {
+ return keys;
+ }
+
+ /**
+ * This will get all of the values for the dictionary.
+ *
+ * @return All the values for the dictionary.
+ */
+ public Collection getValues()
+ {
+ return items.values();
+ }
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return The object that the visitor returns.
+ *
+ * @throws COSVisitorException If there is an error visiting this object.
+ */
+ public Object accept(ICOSVisitor visitor) throws COSVisitorException
+ {
+ return visitor.visitFromDictionary(this);
+ }
+
+ /**
+ * This will add all of the dictionarys keys/values to this dictionary.
+ *
+ * @param dic The dic to get the keys from.
+ */
+ public void addAll( COSDictionary dic )
+ {
+ Iterator dicKeys = dic.keyList().iterator();
+ while( dicKeys.hasNext() )
+ {
+ COSName key = (COSName)dicKeys.next();
+ COSBase value = dic.getItem( key );
+ setItem( key, value );
+ }
+ }
+
+ /**
+ * This will add all of the dictionarys keys/values to this dictionary, but only
+ * if they don't already exist. If a key already exists in this dictionary then
+ * nothing is changed.
+ *
+ * @param dic The dic to get the keys from.
+ */
+ public void mergeInto( COSDictionary dic )
+ {
+ Iterator dicKeys = dic.keyList().iterator();
+ while( dicKeys.hasNext() )
+ {
+ COSName key = (COSName)dicKeys.next();
+ COSBase value = dic.getItem( key );
+ if( getItem( key ) == null )
+ {
+ setItem( key, value );
+ }
+ }
+ }
+
+ /**
+ * Nice method, gives you every object you want
+ * Arrays works properly too. Try "P/Annots/[k]/Rect"
+ * where k means the index of the Annotsarray.
+ *
+ * @param objPath the relative path to the object.
+ * @return the object
+ */
+ public COSBase getObjectFromPath(String objPath)
+ {
+ COSBase retval = null;
+ String[] path = objPath.split(PATH_SEPARATOR);
+ retval = this;
+
+ for (int i = 0; i < path.length; i++)
+ {
+ if(retval instanceof COSArray)
+ {
+ int idx = new Integer(path[i].replaceAll("\\[","").replaceAll("\\]","")).intValue();
+ retval = ((COSArray)retval).getObject(idx);
+ }
+ else if (retval instanceof COSDictionary)
+ {
+ retval = ((COSDictionary)retval).getDictionaryObject( path[i] );
+ }
+ }
+ return retval;
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/COSDocument.java b/src/main/java/org/pdfbox/cos/COSDocument.java
new file mode 100644
index 0000000..51ae684
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSDocument.java
@@ -0,0 +1,518 @@
+/**
+ * Copyright (c) 2003-2004, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+
+import org.pdfbox.exceptions.COSVisitorException;
+
+import org.pdfbox.pdfparser.PDFObjectStreamParser;
+import org.pdfbox.persistence.util.COSObjectKey;
+
+/**
+ * This is the in-memory representation of the PDF document. You need to call
+ * close() on this object when you are done using it!!
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.26 $
+ */
+public class COSDocument extends COSBase
+{
+ private float version;
+
+ /**
+ * added objects (actually preserving original sequence).
+ */
+ private List objects = new ArrayList();
+
+ /**
+ * a pool of objects read/referenced so far
+ * used to resolve indirect object references.
+ */
+ private Map objectPool = new HashMap();
+
+ /**
+ * Document trailer dictionary.
+ */
+ private COSDictionary trailer;
+
+ /**
+ * This file will store the streams in order to conserve memory.
+ */
+ private RandomAccessFile scratchFile = null;
+ private File tmpFile = null;
+
+ private String headerString = "%PDF-1.4";
+
+ /**
+ * Constructor. Uses the java.io.tmpdir value to create a file
+ * to store the streams.
+ *
+ * @throws IOException If there is an error creating the tmp file.
+ */
+ public COSDocument() throws IOException
+ {
+ this( new File( System.getProperty( "java.io.tmpdir" ) ) );
+ }
+
+ /**
+ * Constructor that will create a create a scratch file in the
+ * following directory.
+ *
+ * @param scratchDir The directory to store a scratch file.
+ *
+ * @throws IOException If there is an error creating the tmp file.
+ */
+ public COSDocument( File scratchDir ) throws IOException
+ {
+ tmpFile = File.createTempFile( "pdfbox", "tmp", scratchDir );
+ scratchFile = new RandomAccessFile( tmpFile, "rw" );
+ }
+
+ /**
+ * Constructor that will use the following random access file for storage
+ * of the PDF streams. The client of this method is responsible for deleting
+ * the storage if necessary that this file will write to. The close method
+ * will close the file though.
+ *
+ * @param file The random access file to use for storage.
+ */
+ public COSDocument( RandomAccessFile file )
+ {
+ scratchFile = file;
+ }
+
+ /**
+ * This will get the scratch file for this document.
+ *
+ * @return The scratch file.
+ */
+ public RandomAccessFile getScratchFile()
+ {
+ return scratchFile;
+ }
+
+ /**
+ * This will get the first dictionary object by type.
+ *
+ * @param type The type of the object.
+ *
+ * @return This will return an object with the specified type.
+ */
+ public COSObject getObjectByType( String type )
+ {
+ return getObjectByType( COSName.getPDFName( type ) );
+ }
+
+ /**
+ * This will get the first dictionary object by type.
+ *
+ * @param type The type of the object.
+ *
+ * @return This will return an object with the specified type.
+ */
+ public COSObject getObjectByType( COSName type )
+ {
+ COSObject retval = null;
+ Iterator iter = objects.iterator();
+ while( iter.hasNext() && retval == null)
+ {
+ COSObject object = (COSObject)iter.next();
+
+ COSBase realObject = object.getObject();
+ if( realObject instanceof COSDictionary )
+ {
+ COSDictionary dic = (COSDictionary)realObject;
+ COSName objectType = (COSName)dic.getItem( COSName.TYPE );
+ if( objectType != null && objectType.equals( type ) )
+ {
+ retval = object;
+ }
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * This will get all dictionary objects by type.
+ *
+ * @param type The type of the object.
+ *
+ * @return This will return an object with the specified type.
+ */
+ public List getObjectsByType( String type )
+ {
+ return getObjectsByType( COSName.getPDFName( type ) );
+ }
+
+ /**
+ * This will get a dictionary object by type.
+ *
+ * @param type The type of the object.
+ *
+ * @return This will return an object with the specified type.
+ */
+ public List getObjectsByType( COSName type )
+ {
+ List retval = new ArrayList();
+ Iterator iter = objects.iterator();
+ while( iter.hasNext() )
+ {
+ COSObject object = (COSObject)iter.next();
+
+ COSBase realObject = object.getObject();
+ if( realObject instanceof COSStream )
+ {
+ realObject = (COSStream)realObject;
+ }
+ if( realObject instanceof COSDictionary )
+ {
+ COSDictionary dic = (COSDictionary)realObject;
+ COSName objectType = (COSName)dic.getItem( COSName.TYPE );
+ if( objectType != null && objectType.equals( type ) )
+ {
+ retval.add( object );
+ }
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * This will print contents to stdout.
+ */
+ public void print()
+ {
+ Iterator iter = objects.iterator();
+ while( iter.hasNext() )
+ {
+ COSObject object = (COSObject)iter.next();
+ System.out.println( object);
+ }
+ }
+
+ /**
+ * This will set the version of this PDF document.
+ *
+ * @param versionValue The version of the PDF document.
+ */
+ public void setVersion( float versionValue )
+ {
+ version = versionValue;
+ }
+
+ /**
+ * This will get the version of this PDF document.
+ *
+ * @return This documents version.
+ */
+ public float getVersion()
+ {
+ return version;
+ }
+
+ /**
+ * This will tell if this is an encrypted document.
+ *
+ * @return true If this document is encrypted.
+ */
+ public boolean isEncrypted()
+ {
+ boolean encrypted = false;
+ if( trailer != null )
+ {
+ encrypted = trailer.getDictionaryObject( "Encrypt" ) != null;
+ }
+ return encrypted;
+ }
+
+ /**
+ * This will get the encryption dictionary if the document is encrypted or null
+ * if the document is not encrypted.
+ *
+ * @return The encryption dictionary.
+ */
+ public COSDictionary getEncryptionDictionary()
+ {
+ return (COSDictionary)trailer.getDictionaryObject( COSName.getPDFName( "Encrypt" ) );
+ }
+
+ /**
+ * This will set the encryption dictionary, this should only be called when
+ * encypting the document.
+ *
+ * @param encDictionary The encryption dictionary.
+ */
+ public void setEncryptionDictionary( COSDictionary encDictionary )
+ {
+ trailer.setItem( COSName.getPDFName( "Encrypt" ), encDictionary );
+ }
+
+ /**
+ * This will get the document ID.
+ *
+ * @return The document id.
+ */
+ public COSArray getDocumentID()
+ {
+ return (COSArray) getTrailer().getItem(COSName.getPDFName("ID"));
+ }
+
+ /**
+ * This will set the document ID.
+ *
+ * @param id The document id.
+ */
+ public void setDocumentID( COSArray id )
+ {
+ getTrailer().setItem(COSName.getPDFName("ID"), id);
+ }
+
+ /**
+ * This will create an object for this document.
+ *
+ * Create an indirect object out of the direct type and include in the document
+ * for later lookup via document a map from direct object to indirect object
+ * is maintained. this provides better support for manual PDF construction.
+ *
+ * @param base the base object to wrap in an indirect object.
+ *
+ * @return The pdf object that wraps the base, or creates a new one.
+ */
+ /**
+ public COSObject createObject( COSBase base )
+ {
+ COSObject obj = (COSObject)objectMap.get(base);
+ if (obj == null)
+ {
+ obj = new COSObject( base );
+ obj.addTo(this);
+ }
+ return obj;
+ }**/
+
+ /**
+ * This will get the document catalog.
+ *
+ * Maybe this should move to an object at PDFEdit level
+ *
+ * @return catalog is the root of all document activities
+ *
+ * @throws IOException If no catalog can be found.
+ */
+ public COSObject getCatalog() throws IOException
+ {
+ COSObject catalog = (COSObject)getObjectByType( COSName.CATALOG );
+ if( catalog == null )
+ {
+ throw new IOException( "Catalog cannot be found" );
+ }
+ return catalog;
+ }
+
+ /**
+ * This will get a list of all available objects.
+ *
+ * @return A list of all objects.
+ */
+ public List getObjects()
+ {
+ return new ArrayList(objects);
+ }
+
+ /**
+ * This will get the document trailer.
+ *
+ * @return the document trailer dict
+ */
+ public COSDictionary getTrailer()
+ {
+ return trailer;
+ }
+
+ /**
+ * // MIT added, maybe this should not be supported as trailer is a persistence construct.
+ * This will set the document trailer.
+ *
+ * @param newTrailer the document trailer dictionary
+ */
+ public void setTrailer(COSDictionary newTrailer)
+ {
+ trailer = newTrailer;
+ }
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return any object, depending on the visitor implementation, or null
+ * @throws COSVisitorException If an error occurs while visiting this object.
+ */
+ public Object accept(ICOSVisitor visitor) throws COSVisitorException
+ {
+ return visitor.visitFromDocument( this );
+ }
+
+ /**
+ * This will close all storage and delete the tmp files.
+ *
+ * @throws IOException If there is an error close resources.
+ */
+ public void close() throws IOException
+ {
+ if( scratchFile != null )
+ {
+ scratchFile.close();
+ scratchFile = null;
+ }
+ if( tmpFile != null )
+ {
+ tmpFile.delete();
+ tmpFile = null;
+ }
+ }
+
+ /**
+ * The sole purpose of this is to inform a client of PDFBox that they
+ * did not close the document.
+ */
+ protected void finalize()
+ {
+ if( tmpFile != null || scratchFile != null )
+ {
+ Throwable t = new Throwable( "Warning: You did not close the PDF Document" );
+ t.printStackTrace();
+ }
+ }
+ /**
+ * @return Returns the headerString.
+ */
+ public String getHeaderString()
+ {
+ return headerString;
+ }
+ /**
+ * @param header The headerString to set.
+ */
+ public void setHeaderString(String header)
+ {
+ headerString = header;
+ }
+
+ /**
+ * This method will search the list of objects for types of ObjStm. If it finds
+ * them then it will parse out all of the objects from the stream that is contains.
+ *
+ * @throws IOException If there is an error parsing the stream.
+ */
+ public void dereferenceObjectStreams() throws IOException
+ {
+ Iterator objStm = getObjectsByType( "ObjStm" ).iterator();
+ while( objStm.hasNext() )
+ {
+ COSObject objStream = (COSObject)objStm.next();
+ COSStream stream = (COSStream)objStream.getObject();
+ PDFObjectStreamParser parser = new PDFObjectStreamParser( stream, this );
+ parser.parse();
+ Iterator compressedObjects = parser.getObjects().iterator();
+ while( compressedObjects.hasNext() )
+ {
+ COSObject next = (COSObject)compressedObjects.next();
+ COSObjectKey key = new COSObjectKey( next );
+ COSObject obj = getObjectFromPool( key );
+ obj.setObject( next.getObject() );
+ }
+ }
+ }
+
+ /**
+ * This will add an object to this document.
+ * the method checks if obj is already present as there may be cyclic dependencies
+ *
+ * @param obj The object to add to the document.
+ * @return The object that was actually added to this document, if an object reference already
+ * existed then that will be returned.
+ *
+ * @throws IOException If there is an error adding the object.
+ */
+ public COSObject addObject(COSObject obj) throws IOException
+ {
+ COSObjectKey key = null;
+ if( obj.getObjectNumber() != null )
+ {
+ key = new COSObjectKey( obj );
+ }
+ COSObject fromPool = getObjectFromPool( key );
+ fromPool.setObject( obj.getObject() );
+ return fromPool;
+ }
+
+ /**
+ * 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 COSObject getObjectFromPool(COSObjectKey key) throws IOException
+ {
+ COSObject obj = null;
+ if( key != null )
+ {
+ obj = (COSObject) objectPool.get(key);
+ }
+ if (obj == null)
+ {
+ // this was a forward reference, make "proxy" object
+ obj = new COSObject(null);
+ if( key != null )
+ {
+ obj.setObjectNumber( new COSInteger( key.getNumber() ) );
+ obj.setGenerationNumber( new COSInteger( key.getGeneration() ) );
+ objectPool.put(key, obj);
+ }
+ objects.add( obj );
+ }
+
+ return obj;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/COSFloat.java b/src/main/java/org/pdfbox/cos/COSFloat.java
new file mode 100644
index 0000000..eab0180
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSFloat.java
@@ -0,0 +1,173 @@
+/**
+ * Copyright (c) 2003-2004, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+
+import org.pdfbox.exceptions.COSVisitorException;
+
+/**
+ * This class represents a floating point number in a PDF document.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.15 $
+ */
+public class COSFloat extends COSNumber
+{
+ private float value;
+
+ /**
+ * Constructor.
+ *
+ * @param aFloat The primitive float object that this object wraps.
+ */
+ public COSFloat( float aFloat )
+ {
+ value = aFloat;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param aFloat The primitive float object that this object wraps.
+ *
+ * @throws IOException If aFloat is not a float.
+ */
+ public COSFloat( String aFloat ) throws IOException
+ {
+ try
+ {
+ value = Float.parseFloat( aFloat );
+ }
+ catch( NumberFormatException e )
+ {
+ throw new IOException( "Error expected floating point number actual='" +aFloat + "'" );
+ }
+ }
+
+ /**
+ * The value of the float object that this one wraps.
+ *
+ * @return The value of this object.
+ */
+ public float floatValue()
+ {
+ return value;
+ }
+
+ /**
+ * The value of the double object that this one wraps.
+ *
+ * @return The double of this object.
+ */
+ public double doubleValue()
+ {
+ return value;
+ }
+
+ /**
+ * This will get the integer value of this object.
+ *
+ * @return The int value of this object,
+ */
+ public long longValue()
+ {
+ return (long)value;
+ }
+
+ /**
+ * This will get the integer value of this object.
+ *
+ * @return The int value of this object,
+ */
+ public int intValue()
+ {
+ return (int)value;
+ }
+
+ /**
+ * @see Object#equals( Object )
+ */
+ public boolean equals( Object o )
+ {
+ return o instanceof COSFloat && Float.floatToIntBits(((COSFloat)o).value) == Float.floatToIntBits(value);
+ }
+
+ /**
+ * @see Object#hashCode()
+ */
+ public int hashCode()
+ {
+ return Float.floatToIntBits(value);
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ public String toString()
+ {
+ return "COSFloat{" + value + "}";
+ }
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return any object, depending on the visitor implementation, or null
+ * @throws COSVisitorException If an error occurs while visiting this object.
+ */
+ public Object accept(ICOSVisitor visitor) throws COSVisitorException
+ {
+ return visitor.visitFromFloat(this);
+ }
+
+ /**
+ * This will output this string as a PDF object.
+ *
+ * @param output The stream to write to.
+ * @throws IOException If there is an error writing to the stream.
+ */
+ public void writePDF( OutputStream output ) throws IOException
+ {
+ DecimalFormat formatDecimal = (DecimalFormat)NumberFormat.getNumberInstance();
+ formatDecimal.setMaximumFractionDigits( 10 );
+ formatDecimal.setGroupingUsed( false );
+ DecimalFormatSymbols symbols = formatDecimal.getDecimalFormatSymbols();
+ symbols.setDecimalSeparator( '.' );
+ formatDecimal.setDecimalFormatSymbols( symbols );
+ output.write(formatDecimal.format( value ).getBytes());
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/COSInteger.java b/src/main/java/org/pdfbox/cos/COSInteger.java
new file mode 100644
index 0000000..0a523bd
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSInteger.java
@@ -0,0 +1,190 @@
+/**
+ * Copyright (c) 2003, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.pdfbox.exceptions.COSVisitorException;
+
+/**
+ *
+ * This class represents an integer number in a PDF document.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.11 $
+ */
+public class COSInteger extends COSNumber
+{
+
+ private long value;
+
+ /**
+ * constructor.
+ *
+ * @param val The integer value of this object.
+ */
+ public COSInteger( long val )
+ {
+ value = val;
+ }
+
+ /**
+ * constructor.
+ *
+ * @param val The integer value of this object.
+ */
+ public COSInteger( int val )
+ {
+ this( (long)val );
+ }
+
+ /**
+ * This will create a new PDF Int object using a string.
+ *
+ * @param val The string value of the integer.
+ *
+ * @throws IOException If the val is not an integer type.
+ */
+ public COSInteger( String val ) throws IOException
+ {
+ try
+ {
+ value = Long.parseLong( val );
+ }
+ catch( NumberFormatException e )
+ {
+ throw new IOException( "Error: value is not an integer type actual='" + val + "'" );
+ }
+ }
+
+ /**
+ * @see Object#equals( Object )
+ */
+ public boolean equals(Object o)
+ {
+ return o instanceof COSInteger && ((COSInteger)o).intValue() == intValue();
+ }
+
+ /**
+ * @see Object#hashCode()
+ */
+ public int hashCode()
+ {
+ //taken from java.lang.Long
+ return (int)(value ^ (value >> 32));
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ public String toString()
+ {
+ return "COSInt{" + value + "}";
+ }
+
+ /**
+ * Change the value of this reference.
+ *
+ * @param newValue The new value.
+ */
+ public void setValue( long newValue )
+ {
+ value = newValue;
+ }
+
+
+
+ /**
+ * polymorphic access to value as float.
+ *
+ * @return The float value of this object.
+ */
+ public float floatValue()
+ {
+ return (float)value;
+ }
+
+ /**
+ * polymorphic access to value as float.
+ *
+ * @return The double value of this object.
+ */
+ public double doubleValue()
+ {
+ return (double)value;
+ }
+
+ /**
+ * Polymorphic access to value as int
+ * This will get the integer value of this object.
+ *
+ * @return The int value of this object,
+ */
+ public int intValue()
+ {
+ return (int)value;
+ }
+
+ /**
+ * Polymorphic access to value as int
+ * This will get the integer value of this object.
+ *
+ * @return The int value of this object,
+ */
+ public long longValue()
+ {
+ return value;
+ }
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return any object, depending on the visitor implementation, or null
+ * @throws COSVisitorException If an error occurs while visiting this object.
+ */
+ public Object accept(ICOSVisitor visitor) throws COSVisitorException
+ {
+ return visitor.visitFromInt(this);
+ }
+
+ /**
+ * This will output this string as a PDF object.
+ *
+ * @param output The stream to write to.
+ * @throws IOException If there is an error writing to the stream.
+ */
+ public void writePDF( OutputStream output ) throws IOException
+ {
+ output.write(String.valueOf(value).getBytes());
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/COSName.java b/src/main/java/org/pdfbox/cos/COSName.java
new file mode 100644
index 0000000..8532cc4
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSName.java
@@ -0,0 +1,572 @@
+/**
+ * Copyright (c) 2003-2005, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.pdfbox.exceptions.COSVisitorException;
+import org.pdfbox.persistence.util.COSHEXTable;
+
+
+/**
+ * This class represents a PDF named object.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.38 $
+ */
+public final class COSName extends COSBase implements Comparable
+{
+ /**
+ * Note: This is synchronized because a HashMap must be synchronized if accessed by
+ * multiple threads.
+ */
+ private static Map nameMap = Collections.synchronizedMap( new HashMap(8192) );
+
+
+ /**
+ * A common COSName value.
+ */
+ public static final COSName AA = new COSName( "AA" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName ACRO_FORM = new COSName( "AcroForm" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName ANNOTS = new COSName( "Annots" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName ART_BOX = new COSName("ArtBox" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName ASCII85_DECODE = new COSName( "ASCII85Decode" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName ASCII85_DECODE_ABBREVIATION = new COSName( "A85" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName ASCII_HEX_DECODE = new COSName( "ASCIIHexDecode" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName ASCII_HEX_DECODE_ABBREVIATION = new COSName( "AHx" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName AP = new COSName( "AP" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName B = new COSName( "B" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName BASE_ENCODING = new COSName( "BaseEncoding" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName BASE_FONT = new COSName( "BaseFont" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName BBOX = new COSName( "BBox" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName BLEED_BOX = new COSName("BleedBox" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName CATALOG = new COSName( "Catalog" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName CALGRAY = new COSName( "CalGray" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName CALRGB = new COSName( "CalRGB" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName CCITTFAX_DECODE = new COSName( "CCITTFaxDecode" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName CCITTFAX_DECODE_ABBREVIATION = new COSName( "CCF" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName COLORSPACE = new COSName( "ColorSpace" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName CONTENTS = new COSName( "Contents" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName COUNT = new COSName( "Count" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName CROP_BOX = new COSName( "CropBox" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName DESCENDANT_FONTS = new COSName( "DescendantFonts" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName DIFFERENCES = new COSName( "Differences" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName DCT_DECODE = new COSName( "DCTDecode" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName DCT_DECODE_ABBREVIATION = new COSName( "DCT" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName DEVICECMYK = new COSName( "DeviceCMYK" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName DEVICEGRAY = new COSName( "DeviceGray" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName DEVICEN = new COSName( "DeviceN" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName DEVICERGB = new COSName( "DeviceRGB" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName DV = new COSName( "DV" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName ENCODING = new COSName( "Encoding" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FIELDS = new COSName( "Fields" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FILTER = new COSName( "Filter" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FIRST_CHAR = new COSName( "FirstChar" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FLATE_DECODE = new COSName( "FlateDecode" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FLATE_DECODE_ABBREVIATION = new COSName( "Fl" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FONT = new COSName( "Font" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FONT_FILE = new COSName("FontFile");
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FONT_FILE2 = new COSName("FontFile2");
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FONT_FILE3 = new COSName("FontFile3");
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FONT_DESC = new COSName("FontDescriptor");
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FONT_MATRIX = new COSName("FontMatrix" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FORMTYPE = new COSName( "FormType" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName FRM = new COSName( "FRM" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName HEIGHT = new COSName( "Height" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName ICCBASED = new COSName( "ICCBased" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName IDENTITY_H = new COSName( "Identity-H" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName IMAGE = new COSName( "Image" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName INDEXED = new COSName( "Indexed" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName INFO = new COSName( "Info" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName JPX_DECODE = new COSName( "JPXDecode" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName KIDS = new COSName( "Kids" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName LAB = new COSName( "Lab" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName LAST_CHAR = new COSName( "LastChar" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName LENGTH = new COSName( "Length" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName LENGTH1 = new COSName( "Length1" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName LZW_DECODE = new COSName( "LZWDecode" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName LZW_DECODE_ABBREVIATION = new COSName( "LZW" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName MAC_ROMAN_ENCODING = new COSName( "MacRomanEncoding" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName MATRIX = new COSName( "Matrix" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName MEDIA_BOX = new COSName( "MediaBox" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName METADATA = new COSName( "Metadata" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName N = new COSName( "N" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName NAME = new COSName( "Name" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName P = new COSName( "P" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName PAGE = new COSName( "Page" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName PAGES = new COSName( "Pages" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName PARENT = new COSName( "Parent" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName PATTERN = new COSName( "Pattern" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName PDF_DOC_ENCODING = new COSName( "PDFDocEncoding" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName PREV = new COSName( "Prev" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName R = new COSName( "R" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName RESOURCES = new COSName( "Resources" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName ROOT = new COSName( "Root" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName ROTATE = new COSName( "Rotate" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName RUN_LENGTH_DECODE = new COSName( "RunLengthDecode" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName RUN_LENGTH_DECODE_ABBREVIATION = new COSName( "RL" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName SEPARATION = new COSName( "Separation" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName STANDARD_ENCODING = new COSName( "StandardEncoding" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName SUBTYPE = new COSName( "Subtype" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName TRIM_BOX = new COSName("TrimBox" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName TRUE_TYPE = new COSName("TrueType" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName TO_UNICODE = new COSName( "ToUnicode" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName TYPE = new COSName( "Type" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName TYPE0 = new COSName( "Type0" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName V = new COSName( "V" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName VERSION = new COSName( "Version" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName WIDTHS = new COSName( "Widths" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName WIN_ANSI_ENCODING = new COSName( "WinAnsiEncoding" );
+ /**
+ * A common COSName value.
+ */
+ public static final COSName XOBJECT = new COSName( "XObject" );
+
+ /**
+ * The prefix to a PDF name.
+ */
+ public static final byte[] NAME_PREFIX = new byte[] { 47 }; // The / character
+ /**
+ * The escape character for a name.
+ */
+ public static final byte[] NAME_ESCAPE = new byte[] { 35 }; //The # character
+
+ private String name;
+ private int hashCode;
+
+ /**
+ * This will get a COSName object with that name.
+ *
+ * @param aName The name of the object.
+ *
+ * @return A COSName with the specified name.
+ */
+ public static final COSName getPDFName( String aName )
+ {
+ COSName name = null;
+ if( aName != null )
+ {
+ name = (COSName)nameMap.get( aName );
+ if( name == null )
+ {
+ //name is added to map in the constructor
+ name = new COSName( aName );
+ }
+ }
+ return name;
+ }
+
+ /**
+ * Private constructor. This will limit the number of COSName objects.
+ * that are created.
+ *
+ * @param aName The name of the COSName object.
+ */
+ private COSName( String aName )
+ {
+ name = aName;
+ nameMap.put( aName, this );
+ hashCode = name.hashCode();
+ }
+
+ /**
+ * This will get the name of this COSName object.
+ *
+ * @return The name of the object.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ public String toString()
+ {
+ return "COSName{" + name + "}";
+ }
+
+ /**
+ * @see Object#equals( Object )
+ */
+ public boolean equals( Object o )
+ {
+ boolean retval = this == o;
+ if( !retval && o instanceof COSName )
+ {
+ COSName other = (COSName)o;
+ retval = name == other.name || name.equals( other.name );
+ }
+ return retval;
+ }
+
+ /**
+ * @see Object#hashCode()
+ */
+ public int hashCode()
+ {
+ return hashCode;
+ }
+
+ /**
+ * @see Comparable#compareTo( Object )
+ */
+ public int compareTo(Object o)
+ {
+ COSName other = (COSName)o;
+ return this.name.compareTo( other.name );
+ }
+
+
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return any object, depending on the visitor implementation, or null
+ * @throws COSVisitorException If an error occurs while visiting this object.
+ */
+ public Object accept(ICOSVisitor visitor) throws COSVisitorException
+ {
+ return visitor.visitFromName(this);
+ }
+
+ /**
+ * This will output this string as a PDF object.
+ *
+ * @param output The stream to write to.
+ * @throws IOException If there is an error writing to the stream.
+ */
+ public void writePDF( OutputStream output ) throws IOException
+ {
+ output.write(NAME_PREFIX);
+ byte[] bytes = getName().getBytes();
+ for (int i = 0; i < bytes.length;i++)
+ {
+ int current = ((bytes[i]+256)%256);
+
+ if(current <= 32 || current >= 127 ||
+ current == '(' ||
+ current == ')' ||
+ current == '[' ||
+ current == ']' ||
+ current == '/' ||
+ current == '%' ||
+ current == '<' ||
+ current == '>' ||
+ current == NAME_ESCAPE[0] )
+ {
+ output.write(NAME_ESCAPE);
+ output.write(COSHEXTable.TABLE[current]);
+ }
+ else
+ {
+ output.write(current);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/COSNull.java b/src/main/java/org/pdfbox/cos/COSNull.java
new file mode 100644
index 0000000..15356b5
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSNull.java
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2003-2004, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.pdfbox.exceptions.COSVisitorException;
+
+/**
+ * This class represents a null PDF object.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.12 $
+ */
+public class COSNull extends COSBase
+{
+ /**
+ * The null token.
+ */
+ public static final byte[] NULL_BYTES = new byte[] {110, 117, 108, 108}; //"null".getBytes( "ISO-8859-1" );
+
+ /**
+ * The one null object in the system.
+ */
+ public static final COSNull NULL = new COSNull();
+
+ /**
+ * Constructor.
+ */
+ private COSNull()
+ {
+ //limit creation to one instance.
+ }
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return any object, depending on the visitor implementation, or null
+ * @throws COSVisitorException If an error occurs while visiting this object.
+ */
+ public Object accept( ICOSVisitor visitor ) throws COSVisitorException
+ {
+ return visitor.visitFromNull( this );
+ }
+
+ /**
+ * This will output this string as a PDF object.
+ *
+ * @param output The stream to write to.
+ * @throws IOException If there is an error writing to the stream.
+ */
+ public void writePDF( OutputStream output ) throws IOException
+ {
+ output.write(NULL_BYTES);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/COSNumber.java b/src/main/java/org/pdfbox/cos/COSNumber.java
new file mode 100644
index 0000000..c629f66
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSNumber.java
@@ -0,0 +1,115 @@
+/**
+ * Copyright (c) 2003, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import java.io.IOException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class represents an abstract number in a PDF document.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.9 $
+ */
+public abstract class COSNumber extends COSBase
+{
+ /**
+ * ZERO.
+ */
+ public static final COSInteger ZERO = new COSInteger( 0 );
+ /**
+ * ONE.
+ */
+ public static final COSInteger ONE = new COSInteger( 1 );
+ private static final Map COMMON_NUMBERS = new HashMap();
+
+ static
+ {
+ COMMON_NUMBERS.put( "0", ZERO );
+ COMMON_NUMBERS.put( "1", ONE );
+ }
+
+ /**
+ * This will get the float value of this number.
+ *
+ * @return The float value of this object.
+ */
+ public abstract float floatValue();
+
+ /**
+ * This will get the double value of this number.
+ *
+ * @return The double value of this number.
+ */
+ public abstract double doubleValue();
+
+ /**
+ * This will get the integer value of this number.
+ *
+ * @return The integer value of this number.
+ */
+ public abstract int intValue();
+
+ /**
+ * This will get the long value of this number.
+ *
+ * @return The long value of this number.
+ */
+ public abstract long longValue();
+
+ /**
+ * This factory method will get the appropriate number object.
+ *
+ * @param number The string representation of the number.
+ *
+ * @return A number object, either float or int.
+ *
+ * @throws IOException If the string is not a number.
+ */
+ public static COSNumber get( String number ) throws IOException
+ {
+ COSNumber result = (COSNumber)COMMON_NUMBERS.get( number );
+ if( result == null )
+ {
+ if (number.indexOf('.') >= 0)
+ {
+ result = new COSFloat( number );
+ }
+ else
+ {
+ result = new COSInteger( number );
+ }
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/COSObject.java b/src/main/java/org/pdfbox/cos/COSObject.java
new file mode 100644
index 0000000..28f2316
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSObject.java
@@ -0,0 +1,226 @@
+/**
+ * Copyright (c) 2003, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import org.pdfbox.exceptions.COSVisitorException;
+
+import java.io.IOException;
+
+import org.apache.log4j.Logger;
+
+/**
+ * This class represents a PDF object.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.35 $
+ */
+public class COSObject extends COSBase
+{
+ private static Logger log = Logger.getLogger(COSObject.class);
+
+ private COSBase baseObject;
+ private COSInteger objectNumber;
+ private COSInteger generationNumber;
+
+ /**
+ * Constructor.
+ *
+ * @param object The object that this encapsulates.
+ *
+ * @throws IOException If there is an error with the object passed in.
+ */
+ public COSObject( COSBase object ) throws IOException
+ {
+ setObject( object );
+ }
+
+ /**
+ * This will get the dictionary object in this object that has the name key and
+ * if it is a pdfobjref then it will dereference that and return it.
+ *
+ * @param key The key to the value that we are searching for.
+ *
+ * @return The pdf object that matches the key.
+ */
+ public COSBase getDictionaryObject( COSName key )
+ {
+ COSBase retval =null;
+ if( baseObject instanceof COSDictionary )
+ {
+ retval = ((COSDictionary)baseObject).getDictionaryObject( key );
+ }
+ return retval;
+ }
+
+ /**
+ * This will get the dictionary object in this object that has the name key.
+ *
+ * @param key The key to the value that we are searching for.
+ *
+ * @return The pdf object that matches the key.
+ */
+ public COSBase getItem( COSName key )
+ {
+ COSBase retval =null;
+ if( baseObject instanceof COSDictionary )
+ {
+ retval = ((COSDictionary)baseObject).getItem( key );
+ }
+ return retval;
+ }
+
+ /**
+ * This will get the object that this object encapsulates.
+ *
+ * @return The encapsulated object.
+ */
+ public COSBase getObject()
+ {
+ return baseObject;
+ }
+
+ /**
+ * This will set the object that this object encapsulates.
+ *
+ * @param object The new object to encapsulate.
+ *
+ * @throws IOException If there is an error setting the updated object.
+ */
+ public void setObject( COSBase object ) throws IOException
+ {
+ baseObject = object;
+ /*if( baseObject == null )
+ {
+ baseObject = object;
+ }
+ else
+ {
+ //This is for when an object appears twice in the
+ //pdf file we really want to replace it such that
+ //object references still work correctly.
+ //see owcp-as-received.pdf for an example
+ if( baseObject instanceof COSDictionary )
+ {
+ COSDictionary dic = (COSDictionary)baseObject;
+ COSDictionary dicObject = (COSDictionary)object;
+ dic.clear();
+ dic.addAll( dicObject );
+ }
+ else if( baseObject instanceof COSArray )
+ {
+ COSArray array = (COSArray)baseObject;
+ COSArray arrObject = (COSArray)object;
+ array.clear();
+ for( int i=0; i<arrObject.size(); i++ )
+ {
+ array.add( arrObject.get( i ) );
+ }
+ }
+ else if( baseObject instanceof COSStream )
+ {
+ COSStream oldStream = (COSStream)baseObject;
+ System.out.println( "object:" + object.getClass().getName() );
+ COSStream newStream = (COSStream)object;
+ oldStream.replaceWithStream( newStream );
+ }
+ else if( baseObject instanceof COSInteger )
+ {
+ COSInteger oldInt = (COSInteger)baseObject;
+ COSInteger newInt = (COSInteger)object;
+ oldInt.setValue( newInt.longValue() );
+ }
+ else if( baseObject == null )
+ {
+ baseObject = object;
+ }
+ else
+ {
+ throw new IOException( "Unknown object substitution type:" + baseObject );
+ }
+ }*/
+
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ public String toString()
+ {
+ return "COSObject{" +
+ (objectNumber == null ? "unknown" : "" + objectNumber.intValue() ) + ", " +
+ (generationNumber == null ? "unknown" : "" + generationNumber.intValue() ) +
+ "}";
+ }
+
+ /** Getter for property objectNumber.
+ * @return Value of property objectNumber.
+ */
+ public COSInteger getObjectNumber()
+ {
+ return objectNumber;
+ }
+
+ /** Setter for property objectNumber.
+ * @param objectNum New value of property objectNumber.
+ */
+ public void setObjectNumber(COSInteger objectNum)
+ {
+ objectNumber = objectNum;
+ }
+
+ /** Getter for property generationNumber.
+ * @return Value of property generationNumber.
+ */
+ public COSInteger getGenerationNumber()
+ {
+ return generationNumber;
+ }
+
+ /** Setter for property generationNumber.
+ * @param generationNumberValue New value of property generationNumber.
+ */
+ public void setGenerationNumber(COSInteger generationNumberValue)
+ {
+ generationNumber = generationNumberValue;
+ }
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return any object, depending on the visitor implementation, or null
+ * @throws COSVisitorException If an error occurs while visiting this object.
+ */
+ public Object accept( ICOSVisitor visitor ) throws COSVisitorException
+ {
+ return getObject() != null ? getObject().accept( visitor ) : COSNull.NULL.accept( visitor );
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/COSStream.java b/src/main/java/org/pdfbox/cos/COSStream.java
new file mode 100644
index 0000000..206a854
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSStream.java
@@ -0,0 +1,495 @@
+/**
+ * Copyright (c) 200-2005, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.pdfbox.filter.Filter;
+import org.pdfbox.filter.FilterManager;
+
+import org.pdfbox.pdfparser.PDFStreamParser;
+
+import org.pdfbox.exceptions.COSVisitorException;
+
+import org.pdfbox.io.RandomAccessFileInputStream;
+import org.pdfbox.io.RandomAccessFileOutputStream;
+
+/**
+ * This class represents a stream object in a PDF document.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.36 $
+ */
+public class COSStream extends COSDictionary
+{
+ private static final int BUFFER_SIZE=16384;
+ private static Logger log = Logger.getLogger(COSStream.class);
+
+ private RandomAccessFile file;
+ /**
+ * The stream with all of the filters applied.
+ */
+ private RandomAccessFileOutputStream filteredStream;
+
+ /**
+ * The stream with no filters, this contains the useful data.
+ */
+ private RandomAccessFileOutputStream unFilteredStream;
+
+ /**
+ * Constructor. Creates a new stream with an empty dictionary.
+ *
+ * @param storage The intermediate storage for the stream.
+ */
+ public COSStream( RandomAccessFile storage )
+ {
+ super();
+ file = storage;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param dictionary The dictionary that is associated with this stream.
+ * @param storage The intermediate storage for the stream.
+ */
+ public COSStream( COSDictionary dictionary, RandomAccessFile storage )
+ {
+ super( dictionary );
+ file = storage;
+ }
+
+ /**
+ * This will replace this object with the data from the new object. This
+ * is used to easily maintain referential integrity when changing references
+ * to new objects.
+ *
+ * @param stream The stream that have the new values in it.
+ */
+ public void replaceWithStream( COSStream stream )
+ {
+ this.clear();
+ this.addAll( stream );
+ file = stream.file;
+ filteredStream = stream.filteredStream;
+ unFilteredStream = stream.unFilteredStream;
+ }
+
+ /**
+ * This will get the scratch file associated with this stream.
+ *
+ * @return The scratch file where this stream is being stored.
+ */
+ public RandomAccessFile getScratchFile()
+ {
+ return file;
+ }
+
+ /**
+ * This will get all the tokens in the stream.
+ *
+ * @return All of the tokens in the stream.
+ *
+ * @throws IOException If there is an error parsing the stream.
+ */
+ public List getStreamTokens() throws IOException
+ {
+ PDFStreamParser parser = new PDFStreamParser( this );
+ parser.parse();
+ return parser.getTokens();
+ }
+
+ /**
+ * This will get the stream with all of the filters applied.
+ *
+ * @return the bytes of the physical (endoced) stream
+ *
+ * @throws IOException when encoding/decoding causes an exception
+ */
+ public InputStream getFilteredStream() throws IOException
+ {
+ if( filteredStream == null )
+ {
+ doEncode();
+ }
+ long position = filteredStream.getPosition();
+ long length = filteredStream.getLength();
+
+ RandomAccessFileInputStream input =
+ new RandomAccessFileInputStream( file, position, length );
+ return new BufferedInputStream( input, BUFFER_SIZE );
+ }
+
+ /**
+ * This will get the logical content stream with none of the filters.
+ *
+ * @return the bytes of the logical (decoded) stream
+ *
+ * @throws IOException when encoding/decoding causes an exception
+ */
+ public InputStream getUnfilteredStream() throws IOException
+ {
+ InputStream retval = null;
+ if( unFilteredStream == null )
+ {
+ doDecode();
+ }
+
+ //if unFilteredStream is still null then this stream has not been
+ //created yet, so we should return null.
+ if( unFilteredStream != null )
+ {
+ long position = unFilteredStream.getPosition();
+ long length = unFilteredStream.getLength();
+ RandomAccessFileInputStream input =
+ new RandomAccessFileInputStream( file, position, length );
+ retval = new BufferedInputStream( input, BUFFER_SIZE );
+ }
+ else
+ {
+ // We should check if the COSStream contains data, maybe it
+ // has been created with a RandomAccessFile - which is not
+ // necessary empty.
+ // In this case, the creation was been done as an input, this should
+ // be the unfiltered file, since no filter has been applied yet.
+// if ( (file != null) &&
+// (file.length() > 0) )
+// {
+// retval = new RandomAccessFileInputStream( file,
+// 0,
+// file.length() );
+// }
+// else
+// {
+ //if there is no stream data then simply return an empty stream.
+ retval = new ByteArrayInputStream( new byte[0] );
+// }
+ }
+ return retval;
+ }
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return any object, depending on the visitor implementation, or null
+ * @throws COSVisitorException If an error occurs while visiting this object.
+ */
+ public Object accept(ICOSVisitor visitor) throws COSVisitorException
+ {
+ return visitor.visitFromStream(this);
+ }
+
+ /**
+ * This will decode the physical byte stream applying all of the filters to the stream.
+ *
+ * @throws IOException If there is an error applying a filter to the stream.
+ */
+ private void doDecode() throws IOException
+ {
+ if( log.isDebugEnabled() )
+ {
+ log.debug("doDecode() start");
+ }
+// FIXME: We shouldn't keep the same reference?
+ unFilteredStream = filteredStream;
+
+ COSBase filters = getFilters();
+ if( filters == null )
+ {
+ if( log.isDebugEnabled() )
+ {
+ log.debug("doDecode() - No filter to apply");
+ }
+ }
+ else if( filters instanceof COSName )
+ {
+ if( log.isDebugEnabled() )
+ {
+ log.debug("doDecode( COSName )");
+ }
+ doDecode( (COSName)filters );
+ }
+ else if( filters instanceof COSArray )
+ {
+ if( log.isDebugEnabled() )
+ {
+ log.debug("doDecode( COSArray )");
+ }
+ COSArray filterArray = (COSArray)filters;
+ for( int i=0; i<filterArray.size(); i++ )
+ {
+ COSName filterName = (COSName)filterArray.get( i );
+ doDecode( filterName );
+ }
+ }
+ else
+ {
+ throw new IOException( "Error: Unknown filter type:" + filters );
+ }
+ if( log.isDebugEnabled() )
+ {
+ log.debug("doDecode() end");
+ }
+ }
+
+ /**
+ * This will decode applying a single filter on the stream.
+ *
+ * @param filterName The name of the filter.
+ *
+ * @throws IOException If there is an error parsing the stream.
+ */
+ private void doDecode( COSName filterName ) throws IOException
+ {
+ long start = System.currentTimeMillis();
+ if( log.isDebugEnabled() )
+ {
+ log.debug("doDecode( " + filterName.getName() + " ) dic=" + this +
+ " read.length="+unFilteredStream.getLength() );
+ }
+
+ FilterManager manager = getFilterManager();
+ Filter filter = manager.getFilter( filterName );
+ InputStream input;
+
+ boolean done = false;
+ IOException exception = null;
+ long position = unFilteredStream.getPosition();
+ long length = unFilteredStream.getLength();
+
+ if( length == 0 )
+ {
+ //if the length is zero then don't bother trying to decode
+ //some filters don't work when attempting to decode
+ //with a zero length stream. See zlib_error_01.pdf
+ unFilteredStream = new RandomAccessFileOutputStream( file );
+ done = true;
+ }
+ else
+ {
+ //ok this is a simple hack, sometimes we read a couple extra
+ //bytes that shouldn't be there, so we encounter an error we will just
+ //try again with one less byte.
+ for( int tryCount=0; !done && tryCount<5; tryCount++ )
+ {
+ try
+ {
+ input = new BufferedInputStream(
+ new RandomAccessFileInputStream( file, position, length ), BUFFER_SIZE );
+ unFilteredStream = new RandomAccessFileOutputStream( file );
+ filter.decode( input, unFilteredStream, this );
+ done = true;
+ }
+ catch( IOException io )
+ {
+ length--;
+ exception = io;
+ }
+ }
+ }
+ if( !done )
+ {
+ throw exception;
+ }
+ long stop = System.currentTimeMillis();
+ if( log.isDebugEnabled() )
+ {
+ log.debug("doDecode( " + filterName.getName() + " ) done time=" + (stop-start) );
+ }
+ }
+
+ /**
+ * This will encode the logical byte stream applying all of the filters to the stream.
+ *
+ * @throws IOException If there is an error applying a filter to the stream.
+ */
+ private void doEncode() throws IOException
+ {
+ filteredStream = unFilteredStream;
+
+ COSBase filters = getFilters();
+ if( filters == null )
+ {
+ log.debug( "No filters for stream" );
+ //there is no filter to apply
+ }
+ else if( filters instanceof COSName )
+ {
+ doEncode( (COSName)filters );
+ }
+ else if( filters instanceof COSArray )
+ {
+ // apply filters in reverse order
+ COSArray filterArray = (COSArray)filters;
+ for( int i=filterArray.size()-1; i>=0; i-- )
+ {
+ COSName filterName = (COSName)filterArray.get( i );
+ doEncode( filterName );
+ }
+ }
+ }
+
+ /**
+ * This will encode applying a single filter on the stream.
+ *
+ * @param filterName The name of the filter.
+ *
+ * @throws IOException If there is an error parsing the stream.
+ */
+ private void doEncode( COSName filterName ) throws IOException
+ {
+ FilterManager manager = getFilterManager();
+ Filter filter = manager.getFilter( filterName );
+ InputStream input;
+
+ input = new BufferedInputStream(
+ new RandomAccessFileInputStream( file, filteredStream.getPosition(),
+ filteredStream.getLength() ), BUFFER_SIZE );
+ filteredStream = new RandomAccessFileOutputStream( file );
+ filter.encode( input, filteredStream, this );
+ }
+
+ /**
+ * This will return the filters to apply to the byte stream.
+ * The method will return
+ * - null if no filters are to be applied
+ * - a COSName if one filter is to be applied
+ * - a COSArray containing COSNames if multiple filters are to be applied
+ *
+ * @return the COSBase object representing the filters
+ */
+ public COSBase getFilters()
+ {
+ return getDictionaryObject(COSName.FILTER);
+ }
+
+ /**
+ * This will create a new stream for which filtered byte should be
+ * written to. You probably don't want this but want to use the
+ * createUnfilteredStream, which is used to write raw bytes to.
+ *
+ * @return A stream that can be written to.
+ *
+ * @throws IOException If there is an error creating the stream.
+ */
+ public OutputStream createFilteredStream() throws IOException
+ {
+ filteredStream = new RandomAccessFileOutputStream( file );
+ unFilteredStream = null;
+ return new BufferedOutputStream( filteredStream, BUFFER_SIZE );
+ }
+
+ /**
+ * This will create a new stream for which filtered byte should be
+ * written to. You probably don't want this but want to use the
+ * createUnfilteredStream, which is used to write raw bytes to.
+ *
+ * @param expectedLength An entry where a length is expected.
+ *
+ * @return A stream that can be written to.
+ *
+ * @throws IOException If there is an error creating the stream.
+ */
+ public OutputStream createFilteredStream( COSBase expectedLength ) throws IOException
+ {
+ filteredStream = new RandomAccessFileOutputStream( file );
+ filteredStream.setExpectedLength( expectedLength );
+ unFilteredStream = null;
+ return new BufferedOutputStream( filteredStream, BUFFER_SIZE );
+ }
+
+ /**
+ * set the filters to be applied to the stream.
+ *
+ * @param filters The filters to set on this stream.
+ *
+ * @throws IOException If there is an error clearing the old filters.
+ */
+ public void setFilters(COSBase filters) throws IOException
+ {
+ setItem(COSName.FILTER, filters);
+ // kill cached filtered streams
+ filteredStream = null;
+ }
+
+ /**
+ * This will create an output stream that can be written to.
+ *
+ * @return An output stream which raw data bytes should be written to.
+ *
+ * @throws IOException If there is an error creating the stream.
+ */
+ public OutputStream createUnfilteredStream() throws IOException
+ {
+ unFilteredStream = new RandomAccessFileOutputStream( file );
+ filteredStream = null;
+ return new BufferedOutputStream( unFilteredStream, BUFFER_SIZE );
+ }
+
+ /**
+ * This will print a byte array as a hex string to standard output.
+ *
+ * @param data The array to print.
+ */
+ private static void printHexString( byte[] data )
+ {
+ for( int i=0; i<data.length; i++ )
+ {
+ int nextByte = (data[i] + 256)%256;
+ String hexString = Integer.toHexString( nextByte );
+ if( hexString.length() < 2 )
+ {
+ hexString = "0" + hexString;
+ }
+ System.out.print( hexString );
+ if( i != 0 && (i+1) % 2 == 0 )
+ {
+ System.out.print( " " );
+ }
+ if( i!= 0 && i % 20 == 0 )
+ {
+ System.out.println();
+ }
+ }
+ System.out.println();
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/COSString.java b/src/main/java/org/pdfbox/cos/COSString.java
new file mode 100644
index 0000000..2b882f9
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/COSString.java
@@ -0,0 +1,403 @@
+/**
+ * Copyright (c) 2003-2005, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.pdfbox.persistence.util.COSHEXTable;
+
+import org.pdfbox.exceptions.COSVisitorException;
+
+/**
+ * This represents a string object in a PDF document.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.26 $
+ */
+public class COSString extends COSBase
+{
+ /**
+ * One of the open string tokens.
+ */
+ public static final byte[] STRING_OPEN = new byte[]{ 40 }; //"(".getBytes();
+ /**
+ * One of the close string tokens.
+ */
+ public static final byte[] STRING_CLOSE = new byte[]{ 41 }; //")".getBytes( "ISO-8859-1" );
+ /**
+ * One of the open string tokens.
+ */
+ public static final byte[] HEX_STRING_OPEN = new byte[]{ 60 }; //"<".getBytes( "ISO-8859-1" );
+ /**
+ * One of the close string tokens.
+ */
+ public static final byte[] HEX_STRING_CLOSE = new byte[]{ 62 }; //">".getBytes( "ISO-8859-1" );
+ /**
+ * the escape character in strings.
+ */
+ public static final byte[] ESCAPE = new byte[]{ 92 }; //"\\".getBytes( "ISO-8859-1" );
+
+ /**
+ * CR escape characters.
+ */
+ public static final byte[] CR_ESCAPE = new byte[]{ 92, 114 }; //"\\r".getBytes( "ISO-8859-1" );
+ /**
+ * LF escape characters.
+ */
+ public static final byte[] LF_ESCAPE = new byte[]{ 92, 110 }; //"\\n".getBytes( "ISO-8859-1" );
+ /**
+ * HT escape characters.
+ */
+ public static final byte[] HT_ESCAPE = new byte[]{ 92, 116 }; //"\\t".getBytes( "ISO-8859-1" );
+ /**
+ * BS escape characters.
+ */
+ public static final byte[] BS_ESCAPE = new byte[]{ 92, 98 }; //"\\b".getBytes( "ISO-8859-1" );
+ /**
+ * FF escape characters.
+ */
+ public static final byte[] FF_ESCAPE = new byte[]{ 92, 102 }; //"\\f".getBytes( "ISO-8859-1" );
+
+ private ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ /**
+ * Constructor.
+ */
+ public COSString()
+ {
+ }
+
+ /**
+ * Explicit constructor for ease of manual PDF construction.
+ *
+ * @param value The string value of the object.
+ */
+ public COSString( String value )
+ {
+ try
+ {
+ boolean unicode16 = false;
+ char[] chars = value.toCharArray();
+ for( int i=0; i<chars.length; i++ )
+ {
+ if( chars[i] > 255 )
+ {
+ unicode16 = true;
+ }
+ }
+ if( unicode16 )
+ {
+ out.write( 0xFE );
+ out.write( 0xFF );
+ out.write( value.getBytes( "UTF-16BE" ) );
+ }
+ else
+ {
+ out.write(value.getBytes());
+ }
+ }
+ catch (IOException ignore)
+ {
+ ignore.printStackTrace();
+ //should never happen
+ }
+ }
+
+ /**
+ * Explicit constructor for ease of manual PDF construction.
+ *
+ * @param value The string value of the object.
+ */
+ public COSString( byte[] value )
+ {
+ try
+ {
+ out.write( value );
+ }
+ catch (IOException ignore)
+ {
+ ignore.printStackTrace();
+ //should never happen
+ }
+ }
+
+ /**
+ * This will create a COS string from a string of hex characters.
+ *
+ * @param hex A hex string.
+ * @return A cos string with the hex characters converted to their actual bytes.
+ * @throws IOException If there is an error with the hex string.
+ */
+ public static COSString createFromHexString( String hex ) throws IOException
+ {
+ COSString retval = new COSString();
+ StringBuffer hexBuffer = new StringBuffer( hex.trim() );
+ //if odd number then the last hex digit is assumed to be 0
+ if( hexBuffer.length() % 2 == 1 )
+ {
+ hexBuffer.append( "0" );
+ }
+ for( int i=0; i<hexBuffer.length();)
+ {
+ String hexChars = "" + hexBuffer.charAt( i++ ) + hexBuffer.charAt( i++ );
+ try
+ {
+ retval.append( Integer.parseInt( hexChars, 16 ) );
+ }
+ catch( NumberFormatException e )
+ {
+ throw new IOException( "Error: Expected hex number, actual='" + hexChars + "'" );
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * This will take this string and create a hex representation of the bytes that make the string.
+ *
+ * @return A hex string representing the bytes in this string.
+ */
+ public String getHexString()
+ {
+ StringBuffer retval = new StringBuffer( out.size() * 2 );
+ byte[] data = getBytes();
+ for( int i=0; i<data.length; i++ )
+ {
+ retval.append( COSHEXTable.HEX_TABLE[ (data[i]+256)%256 ] );
+ }
+
+ return retval.toString();
+ }
+
+ /**
+ * This will get the string that this object wraps.
+ *
+ * @return The wrapped string.
+ */
+ public String getString()
+ {
+ String retval;
+ String encoding = "ISO-8859-1";
+ byte[] data = getBytes();
+ int start = 0;
+ if( data.length > 2 )
+ {
+ if( data[0] == (byte)0xFF && data[1] == (byte)0xFE )
+ {
+ encoding = "UTF-16LE";
+ start=2;
+ }
+ else if( data[0] == (byte)0xFE && data[1] == (byte)0xFF )
+ {
+ encoding = "UTF-16BE";
+ start=2;
+ }
+ }
+ try
+ {
+ if( encoding != null )
+ {
+ retval = new String( getBytes(), start, data.length-start, encoding );
+ }
+ else
+ {
+ retval = new String( getBytes() );
+ }
+ }
+ catch( UnsupportedEncodingException e )
+ {
+ //should never happen
+ e.printStackTrace();
+ retval = new String( getBytes() );
+ }
+ return retval;
+ }
+
+ /**
+ * This will append a byte[] to the string.
+ *
+ * @param data The byte[] to add to this string.
+ *
+ * @throws IOException If an IO error occurs while writing the byte.
+ */
+ public void append( byte[] data ) throws IOException
+ {
+ out.write( data );
+ }
+
+ /**
+ * This will append a byte to the string.
+ *
+ * @param in The byte to add to this string.
+ *
+ * @throws IOException If an IO error occurs while writing the byte.
+ */
+ public void append( int in ) throws IOException
+ {
+ out.write( in );
+ }
+
+ /**
+ * This will reset the internal buffer.
+ */
+ public void reset()
+ {
+ out.reset();
+ }
+
+ /**
+ * This will get the bytes of the string.
+ *
+ * @return A byte array that represents the string.
+ */
+ public byte[] getBytes()
+ {
+ return out.toByteArray();
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ public String toString()
+ {
+ return "COSString{" + new String( getBytes() ) + "}";
+ }
+
+ /**
+ * This will output this string as a PDF object.
+ *
+ * @param output The stream to write to.
+ * @throws IOException If there is an error writing to the stream.
+ */
+ public void writePDF( OutputStream output ) throws IOException
+ {
+ boolean outsideASCII = false;
+ //Lets first check if we need to escape this string.
+ byte[] bytes = getBytes();
+ for( int i=0; i<bytes.length && !outsideASCII; i++ )
+ {
+ //if the byte is negative then it is an eight bit byte and is
+ //outside the ASCII range.
+ outsideASCII = bytes[i] <0;
+ }
+ if( !outsideASCII )
+ {
+ output.write(STRING_OPEN);
+ for( int i=0; i<bytes.length; i++ )
+ {
+ int b = (bytes[i]+256)%256;
+ switch( b )
+ {
+ case '(':
+ case ')':
+ case '\\':
+ {
+ output.write(ESCAPE);
+ output.write(b);
+ break;
+ }
+ case 10: //LF
+ {
+ output.write( LF_ESCAPE );
+ break;
+ }
+ case 13: // CR
+ {
+ output.write( CR_ESCAPE );
+ break;
+ }
+ case '\t':
+ {
+ output.write( HT_ESCAPE );
+ break;
+ }
+ case '\b':
+ {
+ output.write( BS_ESCAPE );
+ break;
+ }
+ case '\f':
+ {
+ output.write( FF_ESCAPE );
+ break;
+ }
+ default:
+ {
+ output.write( b );
+ }
+ }
+ }
+ output.write(STRING_CLOSE);
+ }
+ else
+ {
+ output.write(HEX_STRING_OPEN);
+ for(int i=0; i<bytes.length; i++ )
+ {
+ output.write( COSHEXTable.TABLE[ (bytes[i]+256)%256 ] );
+ }
+ output.write(HEX_STRING_CLOSE);
+ }
+ }
+
+
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return any object, depending on the visitor implementation, or null
+ * @throws COSVisitorException If an error occurs while visiting this object.
+ */
+ public Object accept(ICOSVisitor visitor) throws COSVisitorException
+ {
+ return visitor.visitFromString( this );
+ }
+
+ /**
+ * @see Object#equals( Object )
+ */
+ public boolean equals(Object obj)
+ {
+ return (obj instanceof COSString) && java.util.Arrays.equals(((COSString) obj).getBytes(), getBytes());
+ }
+
+ /**
+ * @see Object#hashCode()
+ */
+ public int hashCode()
+ {
+ return getBytes().hashCode();
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/ICOSVisitor.java b/src/main/java/org/pdfbox/cos/ICOSVisitor.java
new file mode 100644
index 0000000..04b7542
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/ICOSVisitor.java
@@ -0,0 +1,132 @@
+/**
+ * Copyright (c) 2003, www.pdfbox.org
+ * 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. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 REGENTS OR 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.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.cos;
+
+import org.pdfbox.exceptions.COSVisitorException;
+
+/**
+ * An interface for visiting a PDF document at the type (COS) level.
+ *
+ * @author Michael Traut
+ * @version $Revision: 1.6 $
+ */
+public interface ICOSVisitor
+{
+ /**
+ * Notification of visit to Array object.
+ *
+ * @param obj The Object that is being visited.
+ * @return any Object depending on the visitor implementation, or null
+ * @throws COSVisitorException If there is an error while visiting this object.
+ */
+ public Object visitFromArray( COSArray obj ) throws COSVisitorException;
+
+ /**
+ * Notification of visit to boolean object.
+ *
+ * @param obj The Object that is being visited.
+ * @return any Object depending on the visitor implementation, or null
+ * @throws COSVisitorException If there is an error while visiting this object.
+ */
+ public Object visitFromBoolean( COSBoolean obj ) throws COSVisitorException;
+
+ /**
+ * Notification of visit to dictionary object.
+ *
+ * @param obj The Object that is being visited.
+ * @return any Object depending on the visitor implementation, or null
+ * @throws COSVisitorException If there is an error while visiting this object.
+ */
+ public Object visitFromDictionary( COSDictionary obj ) throws COSVisitorException;
+
+ /**
+ * Notification of visit to document object.
+ *
+ * @param obj The Object that is being visited.
+ * @return any Object depending on the visitor implementation, or null
+ * @throws COSVisitorException If there is an error while visiting this object.
+ */
+ public Object visitFromDocument( COSDocument obj ) throws COSVisitorException;
+
+ /**
+ * Notification of visit to float object.
+ *
+ * @param obj The Object that is being visited.
+ * @return any Object depending on the visitor implementation, or null
+ * @throws COSVisitorException If there is an error while visiting this object.
+ */
+ public Object visitFromFloat( COSFloat obj ) throws COSVisitorException;
+
+ /**
+ * Notification of visit to integer object.
+ *
+ * @param obj The Object that is being visited.
+ * @return any Object depending on the visitor implementation, or null
+ * @throws COSVisitorException If there is an error while visiting this object.
+ */
+ public Object visitFromInt( COSInteger obj ) throws COSVisitorException;
+
+ /**
+ * Notification of visit to name object.
+ *
+ * @param obj The Object that is being visited.
+ * @return any Object depending on the visitor implementation, or null
+ * @throws COSVisitorException If there is an error while visiting this object.
+ */
+ public Object visitFromName( COSName obj ) throws COSVisitorException;
+
+ /**
+ * Notification of visit to null object.
+ *
+ * @param obj The Object that is being visited.
+ * @return any Object depending on the visitor implementation, or null
+ * @throws COSVisitorException If there is an error while visiting this object.
+ */
+ public Object visitFromNull( COSNull obj ) throws COSVisitorException;
+
+ /**
+ * Notification of visit to stream object.
+ *
+ * @param obj The Object that is being visited.
+ * @return any Object depending on the visitor implementation, or null
+ * @throws COSVisitorException If there is an error while visiting this object.
+ */
+ public Object visitFromStream( COSStream obj ) throws COSVisitorException;
+
+ /**
+ * Notification of visit to string object.
+ *
+ * @param obj The Object that is being visited.
+ * @return any Object depending on the visitor implementation, or null
+ * @throws COSVisitorException If there is an error while visiting this object.
+ */
+ public Object visitFromString( COSString obj ) throws COSVisitorException;
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/cos/package.html b/src/main/java/org/pdfbox/cos/package.html
new file mode 100644
index 0000000..4db3df3
--- /dev/null
+++ b/src/main/java/org/pdfbox/cos/package.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+
+</head>
+<body>
+These are the low level objects that make up a PDF document.
+<br/><br/>
+
+See the <A href="http://partners.adobe.com/asn/developer/acrosdk/docs/filefmtspecs/PDFReference.pdf">PDF Reference 1.4</A>.
+</body>
+</html>