KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > pdfbox > cos > COSString


1 /**
2  * Copyright (c) 2003-2006, www.pdfbox.org
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  * 3. Neither the name of pdfbox; nor the names of its
14  * contributors may be used to endorse or promote products derived from this
15  * software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * http://www.pdfbox.org
29  *
30  */

31 package org.pdfbox.cos;
32
33 import java.io.ByteArrayOutputStream JavaDoc;
34 import java.io.IOException JavaDoc;
35 import java.io.OutputStream JavaDoc;
36 import java.io.UnsupportedEncodingException JavaDoc;
37
38 import org.pdfbox.persistence.util.COSHEXTable;
39
40 import org.pdfbox.exceptions.COSVisitorException;
41
42 /**
43  * This represents a string object in a PDF document.
44  *
45  * @author <a HREF="mailto:ben@benlitchfield.com">Ben Litchfield</a>
46  * @version $Revision: 1.29 $
47  */

48 public class COSString extends COSBase
49 {
50     /**
51      * One of the open string tokens.
52      */

53     public static final byte[] STRING_OPEN = new byte[]{ 40 }; //"(".getBytes();
54
/**
55      * One of the close string tokens.
56      */

57     public static final byte[] STRING_CLOSE = new byte[]{ 41 }; //")".getBytes( "ISO-8859-1" );
58
/**
59      * One of the open string tokens.
60      */

61     public static final byte[] HEX_STRING_OPEN = new byte[]{ 60 }; //"<".getBytes( "ISO-8859-1" );
62
/**
63      * One of the close string tokens.
64      */

65     public static final byte[] HEX_STRING_CLOSE = new byte[]{ 62 }; //">".getBytes( "ISO-8859-1" );
66
/**
67      * the escape character in strings.
68      */

69     public static final byte[] ESCAPE = new byte[]{ 92 }; //"\\".getBytes( "ISO-8859-1" );
70

71     /**
72      * CR escape characters.
73      */

74     public static final byte[] CR_ESCAPE = new byte[]{ 92, 114 }; //"\\r".getBytes( "ISO-8859-1" );
75
/**
76      * LF escape characters.
77      */

78     public static final byte[] LF_ESCAPE = new byte[]{ 92, 110 }; //"\\n".getBytes( "ISO-8859-1" );
79
/**
80      * HT escape characters.
81      */

82     public static final byte[] HT_ESCAPE = new byte[]{ 92, 116 }; //"\\t".getBytes( "ISO-8859-1" );
83
/**
84      * BS escape characters.
85      */

86     public static final byte[] BS_ESCAPE = new byte[]{ 92, 98 }; //"\\b".getBytes( "ISO-8859-1" );
87
/**
88      * FF escape characters.
89      */

90     public static final byte[] FF_ESCAPE = new byte[]{ 92, 102 }; //"\\f".getBytes( "ISO-8859-1" );
91

92     private ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc();
93
94     /**
95      * Forces the string to be serialized in literal form but not hexa form.
96      */

97     private boolean forceLiteralForm = false;
98     
99     
100     /**
101      * Constructor.
102      */

103     public COSString()
104     {
105     }
106
107     /**
108      * Explicit constructor for ease of manual PDF construction.
109      *
110      * @param value The string value of the object.
111      */

112     public COSString( String JavaDoc value )
113     {
114         try
115         {
116             boolean unicode16 = false;
117             char[] chars = value.toCharArray();
118             for( int i=0; i<chars.length; i++ )
119             {
120                 if( chars[i] > 255 )
121                 {
122                     unicode16 = true;
123                 }
124             }
125             if( unicode16 )
126             {
127                 out.write( 0xFE );
128                 out.write( 0xFF );
129                 out.write( value.getBytes( "UTF-16BE" ) );
130             }
131             else
132             {
133                 out.write(value.getBytes("ISO-8859-1"));
134             }
135         }
136         catch (IOException JavaDoc ignore)
137         {
138             ignore.printStackTrace();
139             //should never happen
140
}
141     }
142
143     /**
144      * Explicit constructor for ease of manual PDF construction.
145      *
146      * @param value The string value of the object.
147      */

148     public COSString( byte[] value )
149     {
150         try
151         {
152             out.write( value );
153         }
154         catch (IOException JavaDoc ignore)
155         {
156             ignore.printStackTrace();
157             //should never happen
158
}
159     }
160     
161     /**
162      * Forces the string to be written in literal form instead of hexadecimal form.
163      *
164      * @param v if v is true the string will be written in literal form, otherwise it will
165      * be written in hexa if necessary.
166      */

167     
168     public void setForceLiteralForm(boolean v)
169     {
170         forceLiteralForm = v;
171     }
172     
173     /**
174      * This will create a COS string from a string of hex characters.
175      *
176      * @param hex A hex string.
177      * @return A cos string with the hex characters converted to their actual bytes.
178      * @throws IOException If there is an error with the hex string.
179      */

180     public static COSString createFromHexString( String JavaDoc hex ) throws IOException JavaDoc
181     {
182         COSString retval = new COSString();
183         StringBuffer JavaDoc hexBuffer = new StringBuffer JavaDoc( hex.trim() );
184         //if odd number then the last hex digit is assumed to be 0
185
if( hexBuffer.length() % 2 == 1 )
186         {
187             hexBuffer.append( "0" );
188         }
189         for( int i=0; i<hexBuffer.length();)
190         {
191             String JavaDoc hexChars = "" + hexBuffer.charAt( i++ ) + hexBuffer.charAt( i++ );
192             try
193             {
194                 retval.append( Integer.parseInt( hexChars, 16 ) );
195             }
196             catch( NumberFormatException JavaDoc e )
197             {
198                 throw new IOException JavaDoc( "Error: Expected hex number, actual='" + hexChars + "'" );
199             }
200         }
201         return retval;
202     }
203     
204     /**
205      * This will take this string and create a hex representation of the bytes that make the string.
206      *
207      * @return A hex string representing the bytes in this string.
208      */

209     public String JavaDoc getHexString()
210     {
211         StringBuffer JavaDoc retval = new StringBuffer JavaDoc( out.size() * 2 );
212         byte[] data = getBytes();
213         for( int i=0; i<data.length; i++ )
214         {
215             retval.append( COSHEXTable.HEX_TABLE[ (data[i]+256)%256 ] );
216         }
217         
218         return retval.toString();
219     }
220
221     /**
222      * This will get the string that this object wraps.
223      *
224      * @return The wrapped string.
225      */

226     public String JavaDoc getString()
227     {
228         String JavaDoc retval;
229         String JavaDoc encoding = "ISO-8859-1";
230         byte[] data = getBytes();
231         int start = 0;
232         if( data.length > 2 )
233         {
234             if( data[0] == (byte)0xFF && data[1] == (byte)0xFE )
235             {
236                 encoding = "UTF-16LE";
237                 start=2;
238             }
239             else if( data[0] == (byte)0xFE && data[1] == (byte)0xFF )
240             {
241                 encoding = "UTF-16BE";
242                 start=2;
243             }
244         }
245         try
246         {
247             retval = new String JavaDoc( getBytes(), start, data.length-start, encoding );
248         }
249         catch( UnsupportedEncodingException JavaDoc e )
250         {
251             //should never happen
252
e.printStackTrace();
253             retval = new String JavaDoc( getBytes() );
254         }
255         return retval;
256     }
257
258     /**
259      * This will append a byte[] to the string.
260      *
261      * @param data The byte[] to add to this string.
262      *
263      * @throws IOException If an IO error occurs while writing the byte.
264      */

265     public void append( byte[] data ) throws IOException JavaDoc
266     {
267         out.write( data );
268     }
269
270     /**
271      * This will append a byte to the string.
272      *
273      * @param in The byte to add to this string.
274      *
275      * @throws IOException If an IO error occurs while writing the byte.
276      */

277     public void append( int in ) throws IOException JavaDoc
278     {
279         out.write( in );
280     }
281
282     /**
283      * This will reset the internal buffer.
284      */

285     public void reset()
286     {
287         out.reset();
288     }
289
290     /**
291      * This will get the bytes of the string.
292      *
293      * @return A byte array that represents the string.
294      */

295     public byte[] getBytes()
296     {
297         return out.toByteArray();
298     }
299
300     /**
301      * {@inheritDoc}
302      */

303     public String JavaDoc toString()
304     {
305         return "COSString{" + new String JavaDoc( getBytes() ) + "}";
306     }
307     
308     /**
309      * This will output this string as a PDF object.
310      *
311      * @param output The stream to write to.
312      * @throws IOException If there is an error writing to the stream.
313      */

314     public void writePDF( OutputStream JavaDoc output ) throws IOException JavaDoc
315     {
316         boolean outsideASCII = false;
317         //Lets first check if we need to escape this string.
318
byte[] bytes = getBytes();
319         for( int i=0; i<bytes.length && !outsideASCII; i++ )
320         {
321             //if the byte is negative then it is an eight bit byte and is
322
//outside the ASCII range.
323
outsideASCII = bytes[i] <0;
324         }
325         if( !outsideASCII || forceLiteralForm )
326         {
327             output.write(STRING_OPEN);
328             for( int i=0; i<bytes.length; i++ )
329             {
330                 int b = (bytes[i]+256)%256;
331                 switch( b )
332                 {
333                     case '(':
334                     case ')':
335                     case '\\':
336                     {
337                         output.write(ESCAPE);
338                         output.write(b);
339                         break;
340                     }
341                     case 10: //LF
342
{
343                         output.write( LF_ESCAPE );
344                         break;
345                     }
346                     case 13: // CR
347
{
348                         output.write( CR_ESCAPE );
349                         break;
350                     }
351                     case '\t':
352                     {
353                         output.write( HT_ESCAPE );
354                         break;
355                     }
356                     case '\b':
357                     {
358                         output.write( BS_ESCAPE );
359                         break;
360                     }
361                     case '\f':
362                     {
363                         output.write( FF_ESCAPE );
364                         break;
365                     }
366                     default:
367                     {
368                         output.write( b );
369                     }
370                 }
371             }
372             output.write(STRING_CLOSE);
373         }
374         else
375         {
376             output.write(HEX_STRING_OPEN);
377             for(int i=0; i<bytes.length; i++ )
378             {
379                 output.write( COSHEXTable.TABLE[ (bytes[i]+256)%256 ] );
380             }
381             output.write(HEX_STRING_CLOSE);
382         }
383     }
384
385
386
387     /**
388      * visitor pattern double dispatch method.
389      *
390      * @param visitor The object to notify when visiting this object.
391      * @return any object, depending on the visitor implementation, or null
392      * @throws COSVisitorException If an error occurs while visiting this object.
393      */

394     public Object JavaDoc accept(ICOSVisitor visitor) throws COSVisitorException
395     {
396         return visitor.visitFromString( this );
397     }
398
399     /**
400      * {@inheritDoc}
401      */

402     public boolean equals(Object JavaDoc obj)
403     {
404         return (obj instanceof COSString) && java.util.Arrays.equals(((COSString) obj).getBytes(), getBytes());
405     }
406
407     /**
408      * {@inheritDoc}
409      */

410     public int hashCode()
411     {
412         return getBytes().hashCode();
413     }
414 }
Popular Tags