001: /**
002: * Copyright (c) 2003-2006, www.pdfbox.org
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are met:
007: *
008: * 1. Redistributions of source code must retain the above copyright notice,
009: * this list of conditions and the following disclaimer.
010: * 2. Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: * 3. Neither the name of pdfbox; nor the names of its
014: * contributors may be used to endorse or promote products derived from this
015: * software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
021: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: *
028: * http://www.pdfbox.org
029: *
030: */package org.pdfbox.pdmodel.common;
031:
032: import java.io.ByteArrayInputStream;
033: import java.io.InputStream;
034: import java.io.IOException;
035: import java.io.OutputStream;
036: import java.io.SequenceInputStream;
037:
038: import java.util.ArrayList;
039: import java.util.List;
040: import java.util.Vector;
041:
042: import org.pdfbox.cos.COSArray;
043: import org.pdfbox.cos.COSBase;
044: import org.pdfbox.cos.COSDictionary;
045: import org.pdfbox.cos.COSName;
046: import org.pdfbox.cos.COSStream;
047: import org.pdfbox.cos.ICOSVisitor;
048:
049: import org.pdfbox.exceptions.COSVisitorException;
050: import org.pdfbox.io.RandomAccess;
051:
052: import org.pdfbox.pdfparser.PDFStreamParser;
053:
054: /**
055: * This will take an array of streams and sequence them together.
056: *
057: * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
058: * @version $Revision: 1.9 $
059: */
060: public class COSStreamArray extends COSStream {
061: private COSArray streams;
062:
063: /**
064: * The first stream will be used to delegate some of the methods for this
065: * class.
066: */
067: private COSStream firstStream;
068:
069: /**
070: * Constructor.
071: *
072: * @param array The array of COSStreams to concatenate together.
073: */
074: public COSStreamArray(COSArray array) {
075: super (new COSDictionary(), null);
076: streams = array;
077: if (array.size() > 0) {
078: firstStream = (COSStream) array.getObject(0);
079: }
080: }
081:
082: /**
083: * This will get the scratch file associated with this stream.
084: *
085: * @return The scratch file where this stream is being stored.
086: */
087: public RandomAccess getScratchFile() {
088: return firstStream.getScratchFile();
089: }
090:
091: /**
092: * This will get an object from this streams dictionary.
093: *
094: * @param key The key to the object.
095: *
096: * @return The dictionary object with the key or null if one does not exist.
097: */
098: public COSBase getItem(COSName key) {
099: return firstStream.getItem(key);
100: }
101:
102: /**
103: * This will get an object from this streams dictionary and dereference it
104: * if necessary.
105: *
106: * @param key The key to the object.
107: *
108: * @return The dictionary object with the key or null if one does not exist.
109: */
110: public COSBase getDictionaryObject(COSName key) {
111: return firstStream.getDictionaryObject(key);
112: }
113:
114: /**
115: * {@inheritDoc}
116: */
117: public String toString() {
118: String result = "COSStream{}";
119: return result;
120: }
121:
122: /**
123: * This will get all the tokens in the stream.
124: *
125: * @return All of the tokens in the stream.
126: *
127: * @throws IOException If there is an error parsing the stream.
128: */
129: public List getStreamTokens() throws IOException {
130: List retval = null;
131: if (streams.size() > 0) {
132: PDFStreamParser parser = new PDFStreamParser(this );
133: parser.parse();
134: retval = parser.getTokens();
135: } else {
136: retval = new ArrayList();
137: }
138: return retval;
139: }
140:
141: /**
142: * This will get the dictionary that is associated with this stream.
143: *
144: * @return the object that is associated with this stream.
145: */
146: public COSDictionary getDictionary() {
147: return firstStream;
148: }
149:
150: /**
151: * This will get the stream with all of the filters applied.
152: *
153: * @return the bytes of the physical (endoced) stream
154: *
155: * @throws IOException when encoding/decoding causes an exception
156: */
157: public InputStream getFilteredStream() throws IOException {
158: throw new IOException(
159: "Error: Not allowed to get filtered stream from array of streams.");
160: /**
161: Vector inputStreams = new Vector();
162: byte[] inbetweenStreamBytes = "\n".getBytes();
163:
164: for( int i=0;i<streams.size(); i++ )
165: {
166: COSStream stream = (COSStream)streams.getObject( i );
167: }
168:
169: return new SequenceInputStream( inputStreams.elements() );
170: **/
171: }
172:
173: /**
174: * This will get the logical content stream with none of the filters.
175: *
176: * @return the bytes of the logical (decoded) stream
177: *
178: * @throws IOException when encoding/decoding causes an exception
179: */
180: public InputStream getUnfilteredStream() throws IOException {
181: Vector inputStreams = new Vector();
182: byte[] inbetweenStreamBytes = "\n".getBytes();
183:
184: for (int i = 0; i < streams.size(); i++) {
185: COSStream stream = (COSStream) streams.getObject(i);
186: inputStreams.add(stream.getUnfilteredStream());
187: //handle the case where there is no whitespace in the
188: //between streams in the contents array, without this
189: //it is possible that two operators will get concatenated
190: //together
191: inputStreams.add(new ByteArrayInputStream(
192: inbetweenStreamBytes));
193: }
194:
195: return new SequenceInputStream(inputStreams.elements());
196: }
197:
198: /**
199: * visitor pattern double dispatch method.
200: *
201: * @param visitor The object to notify when visiting this object.
202: * @return any object, depending on the visitor implementation, or null
203: * @throws COSVisitorException If an error occurs while visiting this object.
204: */
205: public Object accept(ICOSVisitor visitor)
206: throws COSVisitorException {
207: return streams.accept(visitor);
208: }
209:
210: /**
211: * This will return the filters to apply to the byte stream
212: * the method will return.
213: * - null if no filters are to be applied
214: * - a COSName if one filter is to be applied
215: * - a COSArray containing COSNames if multiple filters are to be applied
216: *
217: * @return the COSBase object representing the filters
218: */
219: public COSBase getFilters() {
220: return firstStream.getFilters();
221: }
222:
223: /**
224: * This will create a new stream for which filtered byte should be
225: * written to. You probably don't want this but want to use the
226: * createUnfilteredStream, which is used to write raw bytes to.
227: *
228: * @return A stream that can be written to.
229: *
230: * @throws IOException If there is an error creating the stream.
231: */
232: public OutputStream createFilteredStream() throws IOException {
233: return firstStream.createFilteredStream();
234: }
235:
236: /**
237: * This will create a new stream for which filtered byte should be
238: * written to. You probably don't want this but want to use the
239: * createUnfilteredStream, which is used to write raw bytes to.
240: *
241: * @param expectedLength An entry where a length is expected.
242: *
243: * @return A stream that can be written to.
244: *
245: * @throws IOException If there is an error creating the stream.
246: */
247: public OutputStream createFilteredStream(COSBase expectedLength)
248: throws IOException {
249: return firstStream.createFilteredStream(expectedLength);
250: }
251:
252: /**
253: * set the filters to be applied to the stream.
254: *
255: * @param filters The filters to set on this stream.
256: *
257: * @throws IOException If there is an error clearing the old filters.
258: */
259: public void setFilters(COSBase filters) throws IOException {
260: //should this be allowed? Should this
261: //propagate to all streams in the array?
262: firstStream.setFilters(filters);
263: }
264:
265: /**
266: * This will create an output stream that can be written to.
267: *
268: * @return An output stream which raw data bytes should be written to.
269: *
270: * @throws IOException If there is an error creating the stream.
271: */
272: public OutputStream createUnfilteredStream() throws IOException {
273: return firstStream.createUnfilteredStream();
274: }
275:
276: /**
277: * Appends a new stream to the array that represents this object's stream.
278: *
279: * @param streamToAppend The stream to append.
280: */
281: public void appendStream(COSStream streamToAppend) {
282: streams.add(streamToAppend);
283: }
284:
285: }
|