/*
* Copyright 2006-2012 ICEsoft Technologies Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS
* IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.icepdf.core.pobjects;
import org.icepdf.core.io.SeekableByteArrayInputStream;
import org.icepdf.core.io.SeekableInput;
import org.icepdf.core.io.SeekableInputConstrainedWrapper;
import org.icepdf.core.util.Library;
import org.icepdf.core.util.Parser;
import java.util.Hashtable;
import java.util.logging.Logger;
import java.util.logging.Level;
/**
* @author Mark Collette
* @since 2.0
*/
public class ObjectStream extends Stream {
private static final Logger logger =
Logger.getLogger(Form.class.toString());
private boolean m_bInited;
private SeekableInput m_DecodedStream;
private int[] m_iaObjectNumbers;
private long[] m_laObjectOffset;
/**
* Create a new instance of a Stream.
*
* @param l library containing a hash of all document objects
* @param h hashtable of parameters specific to the Stream object.
* @param streamInputWrapper Accessor to stream byte data
*/
public ObjectStream(Library l, Hashtable h, SeekableInputConstrainedWrapper streamInputWrapper) {
super(l, h, streamInputWrapper);
}
public synchronized void init() {
if (m_bInited)
return;
m_bInited = true;
int numObjects = library.getInt(entries, "N");
long firstObjectsOffset = library.getLong(entries, "First");
byte[] data = getBytes();
m_DecodedStream = new SeekableByteArrayInputStream(data);
m_DecodedStream.beginThreadAccess();
m_iaObjectNumbers = new int[numObjects];
m_laObjectOffset = new long[numObjects];
try{
Parser parser = new Parser(m_DecodedStream);
for (int i = 0; i < numObjects; i++) {
m_iaObjectNumbers[i] = parser.getIntSurroundedByWhitespace();
m_laObjectOffset[i] = parser.getLongSurroundedByWhitespace() + firstObjectsOffset;
}
}
finally {
m_DecodedStream.endThreadAccess();
}
}
public boolean loadObject(Library library, int objectIndex) {
//System.out.println("ObjectStream.loadObject() objectIndex: " + objectIndex);
init();
if (m_iaObjectNumbers == null ||
m_laObjectOffset == null ||
m_iaObjectNumbers.length != m_laObjectOffset.length ||
objectIndex < 0 ||
objectIndex >= m_iaObjectNumbers.length) {
//System.out.println("ObjectStream.loadObject() init failed");
return false;
}
boolean gotSomething = false;
try {
int objectNumber = m_iaObjectNumbers[objectIndex];
long position = m_laObjectOffset[objectIndex];
//System.out.println("ObjectStream.loadObject() objectNumber: " + objectNumber + ", position: " + position);
m_DecodedStream.beginThreadAccess();
m_DecodedStream.seekAbsolute(position);
Parser parser = new Parser(m_DecodedStream, Parser.PARSE_MODE_OBJECT_STREAM);
// Parser.getObject() either does 1 of 3 things:
// 1. Gets a core object (Dictionary or Stream), adds it to Library by object Reference, returns PObject
// 2. Gets a non-core-object, leaves it on stack, returns null
// 3. Gets a non-core-object, returns it
Object ob = parser.getObject(library);
if (ob == null) {
Reference ref = new Reference(objectNumber, 0);
ob = parser.addPObject(library, ref);
} else if (!(ob instanceof PObject)) {
Reference ref = new Reference(objectNumber, 0);
library.addObject(ob, ref);
}
// assign object reference, needed for encrypting and state saving
if (ob != null && ob instanceof Dictionary){
((Dictionary)ob).setPObjectReference(
new Reference(objectNumber, 0));
}
//System.out.println("ObjectStream.loadObject() ob: " + ob + ", ob.class: " + ob.getClass().getName());
gotSomething = (ob != null);
}
catch (Exception e) {
logger.log(Level.FINE, "Error loading PDF object.", e);
}
finally {
m_DecodedStream.endThreadAccess();
}
return gotSomething;
}
public void dispose(boolean cache) {
m_bInited = false;
m_DecodedStream = null;
m_iaObjectNumbers = null;
m_laObjectOffset = null;
super.dispose(cache);
}
}