KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > pdf > AbstractPDFStream


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 /* $Id: AbstractPDFStream.java 426576 2006-07-28 15:44:37Z jeremias $ */
19  
20 package org.apache.fop.pdf;
21
22 import java.io.IOException JavaDoc;
23 import java.io.OutputStream JavaDoc;
24
25 import org.apache.commons.io.output.CountingOutputStream;
26 import org.apache.fop.util.CloseBlockerOutputStream;
27
28 /**
29  * This is an abstract base class for PDF streams.
30  */

31 public abstract class AbstractPDFStream extends PDFObject {
32
33     /** The filters that should be applied */
34     private PDFFilterList filters;
35
36     /**
37      * Constructor for AbstractPDFStream.
38      */

39     public AbstractPDFStream() {
40         super();
41     }
42
43     /**
44      * Sets up the default filters for this stream if they haven't been set
45      * from outside.
46      */

47     protected void setupFilterList() {
48         if (!getFilterList().isInitialized()) {
49             getFilterList().addDefaultFilters(
50                 getDocumentSafely().getFilterMap(),
51                 PDFFilterList.DEFAULT_FILTER);
52         }
53         prepareImplicitFilters();
54         getDocument().applyEncryption(this);
55     }
56
57     /**
58      * Returns the associated filter list.
59      * @return the filter list
60      */

61     public PDFFilterList getFilterList() {
62         if (this.filters == null) {
63             if (getDocument() == null) {
64                 this.filters = new PDFFilterList();
65             } else {
66                 this.filters = new PDFFilterList(getDocument().isEncryptionActive());
67                 //this.filters = new PDFFilterList(false);
68
}
69         }
70         return this.filters;
71     }
72
73     /**
74      * Returns a value that hints at the size of the encoded stream. This is
75      * used to optimize buffer allocation so fewer buffer reallocations are
76      * necessary.
77      * @return an estimated size (0 if no hint can be given)
78      * @throws IOException in case of an I/O problem
79      */

80     protected abstract int getSizeHint() throws IOException JavaDoc;
81     
82     /**
83      * Sends the raw stream data to the target OutputStream.
84      * @param out OutputStream to write to
85      * @throws IOException In case of an I/O problem
86      */

87     protected abstract void outputRawStreamData(OutputStream JavaDoc out)
88             throws IOException JavaDoc;
89
90     /**
91      * Output just the stream data enclosed by stream/endstream markers
92      * @param encodedStream already encoded/filtered stream to write
93      * @param out OutputStream to write to
94      * @return int number of bytes written
95      * @throws IOException in case of an I/O problem
96      */

97     protected int outputStreamData(StreamCache encodedStream, OutputStream JavaDoc out) throws IOException JavaDoc {
98         int length = 0;
99         byte[] p = encode("stream\n");
100         out.write(p);
101         length += p.length;
102         
103         encodedStream.outputContents(out);
104         length += encodedStream.getSize();
105         
106         p = encode("\nendstream");
107         out.write(p);
108         length += p.length;
109         return length;
110     }
111
112     /**
113      * Encodes the raw data stream for output to a PDF file.
114      * @return the encoded stream
115      * @throws IOException in case of an I/O problem
116      */

117     protected StreamCache encodeStream() throws IOException JavaDoc {
118         //Allocate a temporary buffer to find out the size of the encoded stream
119
final StreamCache encodedStream = StreamCacheFactory.getInstance().
120                 createStreamCache(getSizeHint());
121         OutputStream JavaDoc filteredOutput =
122                 getFilterList().applyFilters(encodedStream.getOutputStream());
123         outputRawStreamData(filteredOutput);
124         filteredOutput.flush();
125         filteredOutput.close();
126         return encodedStream;
127     }
128
129     /**
130      * Encodes and writes a stream directly to an OutputStream. The length of
131      * the stream, in this case, is set on a PDFNumber object that has to be
132      * prepared beforehand.
133      * @param out OutputStream to write to
134      * @param refLength PDFNumber object to receive the stream length
135      * @return number of bytes written (header and trailer included)
136      * @throws IOException in case of an I/O problem
137      */

138     protected int encodeAndWriteStream(OutputStream JavaDoc out, PDFNumber refLength)
139                 throws IOException JavaDoc {
140         int bytesWritten = 0;
141         //Stream header
142
byte[] buf = encode("stream\n");
143         out.write(buf);
144         bytesWritten += buf.length;
145         
146         //Stream contents
147
CloseBlockerOutputStream cbout = new CloseBlockerOutputStream(out);
148         CountingOutputStream cout = new CountingOutputStream(cbout);
149         OutputStream JavaDoc filteredOutput =
150                 getFilterList().applyFilters(cout);
151         outputRawStreamData(filteredOutput);
152         filteredOutput.close();
153         refLength.setNumber(new Integer JavaDoc(cout.getCount()));
154         bytesWritten += cout.getCount();
155             
156         //Stream trailer
157
buf = encode("\nendstream");
158         out.write(buf);
159         bytesWritten += buf.length;
160         
161         return bytesWritten;
162     }
163
164     /**
165      * Overload the base object method so we don't have to copy
166      * byte arrays around so much
167      * @see org.apache.fop.pdf.PDFObject#output(OutputStream)
168      */

169     protected int output(OutputStream JavaDoc stream) throws IOException JavaDoc {
170         int length = 0;
171         setupFilterList();
172         
173         StreamCache encodedStream = null;
174         PDFNumber refLength = null;
175         final String JavaDoc lengthEntry;
176         if (getDocument().isEncodingOnTheFly()) {
177             refLength = new PDFNumber();
178             getDocumentSafely().registerObject(refLength);
179             lengthEntry = refLength.referencePDF();
180         } else {
181             encodedStream = encodeStream();
182             lengthEntry = Integer.toString(encodedStream.getSize() + 1);
183         }
184         
185         String JavaDoc filterEntry = getFilterList().buildFilterDictEntries();
186         byte[] p = encode(buildStreamDict(lengthEntry));
187
188         stream.write(p);
189         length += p.length;
190         
191         //Send encoded stream to target OutputStream
192
if (encodedStream == null) {
193             int bytesWritten = encodeAndWriteStream(stream, refLength);
194             length += bytesWritten;
195         } else {
196             length += outputStreamData(encodedStream, stream);
197             encodedStream.clear(); //Encoded stream can now be discarded
198
}
199         
200         p = encode("\nendobj\n");
201         stream.write(p);
202         length += p.length;
203         return length;
204     }
205
206     /**
207      * Constructs the dictionary for the stream. Override this method if you
208      * need additional entries.
209      * @param lengthEntry value for the /Length entry
210      * @return the newly constructed dictionary
211      */

212     protected String JavaDoc buildStreamDict(String JavaDoc lengthEntry) {
213         final String JavaDoc filterEntry = getFilterList().buildFilterDictEntries();
214         return (getObjectID()
215             + "<< /Length " + lengthEntry + "\n"
216             + filterEntry
217             + "\n>>\n");
218     }
219
220     /**
221      * Prepares implicit filters (such as the DCTFilter for JPEG images). You
222      * must make sure that the appropriate filters are in the filter list at
223      * the right places.
224      */

225     protected void prepareImplicitFilters() {
226         //nop: No default implicit filters
227
}
228
229 }
230
Popular Tags