private static void appendSyntaxString(PdfIndirectReference reference) { stringBuilder .append(reference.getObjNumber()) .append(" ") .append(reference.getGenNumber()) .append(" R"); }
private void write(PdfIndirectReference indirectReference) { if (document != null && !indirectReference.getDocument().equals(document)) { throw new PdfException(PdfException.PdfIndirectObjectBelongsToOtherPdfDocument); } if (indirectReference.isFree()) { Logger logger = LoggerFactory.getLogger(PdfOutputStream.class); logger.error(LogMessageConstant.FLUSHED_OBJECT_CONTAINS_FREE_REFERENCE); write(PdfNull.PDF_NULL); } else if (indirectReference.getRefersTo() == null) { Logger logger = LoggerFactory.getLogger(PdfOutputStream.class); logger.error(LogMessageConstant.FLUSHED_OBJECT_CONTAINS_REFERENCE_WHICH_NOT_REFER_TO_ANY_OBJECT); write(PdfNull.PDF_NULL); } else if (indirectReference.getGenNumber() == 0) { writeInteger(indirectReference.getObjNumber()). writeBytes(endIndirectWithZeroGenNr); } else { writeInteger(indirectReference.getObjNumber()). writeSpace(). writeInteger(indirectReference.getGenNumber()). writeBytes(endIndirect); } }
Integer leastFreeRefObjNum = null; for (Map.Entry<Integer, PdfIndirectReference> entry : freeReferencesLinkedList.entrySet()) { if (entry.getKey() <= 0 || xref[entry.getKey()].getGenNumber() >= MAX_GENERATION) { continue; if (!freeRef.isFree()) { return null; PdfIndirectReference prevFreeRef = freeReferencesLinkedList.remove(freeRef.getObjNumber()); if (prevFreeRef != null) { freeReferencesLinkedList.put((int) freeRef.getOffset(), prevFreeRef); ((PdfIndirectReference) prevFreeRef.setState(PdfObject.MODIFIED)).setOffset(freeRef.getOffset());
IndirectRefDescription(PdfIndirectReference reference) { this.docId = reference.getDocument().getDocumentId(); this.objNr = reference.getObjNumber(); this.genNr = reference.getGenNumber(); }
private void appendNewRefToFreeList(PdfIndirectReference reference) { reference.setOffset(0); if (freeReferencesLinkedList.<Integer, PdfIndirectReference>isEmpty()) { assert false; // free references list is not initialized yet return; } PdfIndirectReference lastFreeRef = freeReferencesLinkedList.get(0); ((PdfIndirectReference) lastFreeRef.setState(PdfObject.MODIFIED)).setOffset(reference.getObjNumber()); freeReferencesLinkedList.put(reference.getObjNumber(), lastFreeRef); freeReferencesLinkedList.put(0, reference); }
PdfIndirectReference createNewIndirectReference(PdfDocument document) { PdfIndirectReference reference = new PdfIndirectReference(document, ++count); add(reference); return (PdfIndirectReference) reference.setState(PdfObject.MODIFIED); }
switch (type) { case 0: newReference = (PdfIndirectReference) new PdfIndirectReference(pdfDocument, base, field3, field2).setState(PdfObject.FREE); break; case 1: newReference = new PdfIndirectReference(pdfDocument, base, field3, field2); break; case 2: newReference = new PdfIndirectReference(pdfDocument, base, 0, field3); newReference.setObjStreamNumber((int) field2); break; default: boolean refReadingState = reference != null && reference.checkState(PdfObject.READING) && reference.getGenNumber() == newReference.getGenNumber(); boolean refFirstEncountered = reference == null || !refReadingState && reference.getDocument() == null; // for references that are added by xref table itself (like 0 entry) reference.setOffset(newReference.getOffset()); reference.setObjStreamNumber(newReference.getObjStreamNumber()); reference.clearState(PdfObject.READING);
try { currentIndirectReference = reference; if (reference.getObjStreamNumber() > 0) { PdfStream objectStream = (PdfStream) pdfDocument.getXref(). get(reference.getObjStreamNumber()).getRefersTo(false); readObjectStream(objectStream); return reference.refersTo; } else if (reference.getOffset() > 0) { PdfObject object; try { tokens.seek(reference.getOffset()); tokens.nextValidToken(); if (tokens.getTokenType() != PdfTokenizer.TokenType.Obj || tokens.getObjNr() != reference.getObjNumber() || tokens.getGenNr() != reference.getGenNumber()) { tokens.throwError(PdfException.InvalidOffsetForObject1, reference.toString()); if (fixXref && reference.getObjStreamNumber() == 0) { fixXref(); object = readObject(reference, false);
/** * Adds indirect reference to list of indirect objects. * * @param reference indirect reference to add. */ public PdfIndirectReference add(PdfIndirectReference reference) { if (reference == null) { return null; } int objNr = reference.getObjNumber(); this.count = Math.max(this.count, objNr); ensureCount(objNr); xref[objNr] = reference; return reference; }
void initFreeReferencesList(PdfDocument pdfDocument) { freeReferencesLinkedList.clear(); xref[0].setState(PdfObject.FREE); // ensure zero object is free TreeSet<Integer> freeReferences = new TreeSet<>(); for (int i = 1; i < size(); ++i) { PdfIndirectReference ref = xref[i]; if (ref == null || ref.isFree()) { freeReferences.add(i); while (!freeReferences.<Integer>isEmpty()) { int currFreeRefObjNr = -1; if (prevFreeRef.getOffset() <= Integer.MAX_VALUE) { currFreeRefObjNr = (int) prevFreeRef.getOffset(); continue; xref[next] = (PdfIndirectReference) new PdfIndirectReference(pdfDocument, next, 0).setState(PdfObject.FREE).setState(PdfObject.MODIFIED); } else if (xref[next].getGenNumber() == MAX_GENERATION && xref[next].getOffset() == 0) { continue; if (prevFreeRef.getOffset() != (long)next) { ((PdfIndirectReference) prevFreeRef.setState(PdfObject.MODIFIED)).setOffset(next); if (prevFreeRef.getOffset() != 0) { ((PdfIndirectReference) prevFreeRef.setState(PdfObject.MODIFIED)).setOffset(0);
boolean refReadingState = reference != null && reference.checkState(PdfObject.READING) && reference.getGenNumber() == gen; boolean refFirstEncountered = reference == null || !refReadingState && reference.getDocument() == null; // for references that are added by xref table itself (like 0 entry) reference = new PdfIndirectReference(pdfDocument, num, gen, pos); } else if (reference.checkState(PdfObject.READING) && reference.getGenNumber() == gen) { reference.setOffset(pos); reference.clearState(PdfObject.READING); } else { continue; reference.setState(PdfObject.FREE);
/** * Gets a PdfWriter associated with the document object belongs to. * * @return PdfWriter. */ protected PdfWriter getWriter() { if (getDocument() != null) return getDocument().getWriter(); return null; }
protected PdfObject readReference(boolean readAsDirect) { int num = tokens.getObjNr(); PdfXrefTable table = pdfDocument.getXref(); PdfIndirectReference reference = table.get(num); if (reference != null) { if (reference.isFree()) { Logger logger = LoggerFactory.getLogger(PdfReader.class); logger.warn(MessageFormatUtil.format(LogMessageConstant.INVALID_INDIRECT_REFERENCE, tokens.getObjNr(), tokens.getGenNr())); return createPdfNullInstance(readAsDirect); } if (reference.getGenNumber() != tokens.getGenNr()) { if (fixedXref) { Logger logger = LoggerFactory.getLogger(PdfReader.class); logger.warn(MessageFormatUtil.format(LogMessageConstant.INVALID_INDIRECT_REFERENCE, tokens.getObjNr(), tokens.getGenNr())); return createPdfNullInstance(readAsDirect); } else { throw new PdfException(PdfException.InvalidIndirectReference1, MessageFormatUtil.format("{0} {1} R", reference.getObjNumber(), reference.getGenNumber())); } } } else { reference = table.add((PdfIndirectReference) new PdfIndirectReference(pdfDocument, num, tokens.getGenNr(), 0).setState(PdfObject.READING)); } return reference; }
public PdfObject getRefersTo() { return getRefersTo(true); }
@Override public String toString() { StringBuilder states = new StringBuilder(" "); if (checkState(FREE)) { states.append("Free; "); } if (checkState(MODIFIED)) { states.append("Modified; "); } if (checkState(MUST_BE_FLUSHED)) { states.append("MustBeFlushed; "); } if (checkState(READING)) { states.append("Reading; "); } if (checkState(FLUSHED)) { states.append("Flushed; "); } if (checkState(ORIGINAL_OBJECT_STREAM)) { states.append("OriginalObjectStream; "); } if (checkState(FORBID_RELEASE)) { states.append("ForbidRelease; "); } if (checkState(READ_ONLY)) { states.append("ReadOnly; "); } return MessageFormatUtil.format("{0} {1} R{2}", Integer.toString(getObjNumber()), Integer.toString(getGenNumber()), states.substring(0, states.length() - 1)); }
for (int i = count; i > 0; --i) { PdfIndirectReference lastRef = xref[i]; if (lastRef == null || lastRef.isFree()) { removeFreeRefFromList(i); --count; for (int i = first; i < first + len; i++) { PdfIndirectReference reference = xrefTable.get(i); if (reference.isFree()) { xrefStream.getOutputStream().write(0); xrefStream.getOutputStream().write(reference.getOffset(), offsetSize); xrefStream.getOutputStream().write(reference.getGenNumber(), 2); } else if (reference.getObjStreamNumber() == 0) { xrefStream.getOutputStream().write(1); xrefStream.getOutputStream().write(reference.getOffset(), offsetSize); xrefStream.getOutputStream().write(reference.getGenNumber(), 2); } else { xrefStream.getOutputStream().write(2); xrefStream.getOutputStream().write(reference.getObjStreamNumber(), offsetSize); xrefStream.getOutputStream().write(reference.getIndex(), 2); StringBuilder off = new StringBuilder("0000000000").append(reference.getOffset()); StringBuilder gen = new StringBuilder("00000").append(reference.getGenNumber()); writer.writeString(off.substring(off.length() - 10, off.length())).writeSpace(). writeString(gen.substring(gen.length() - 5, gen.length())).writeSpace(); if (reference.isFree()) { writer.writeBytes(freeXRefEntry); } else {
protected void readObjectStream(PdfStream objectStream) throws IOException { int objectStreamNumber = objectStream.getIndirectReference().getObjNumber(); int first = objectStream.getAsNumber(PdfName.First).intValue(); int n = objectStream.getAsNumber(PdfName.N).intValue(); if (reference.getObjStreamNumber() == objectStreamNumber) { reference.setRefersTo(obj); obj.setIndirectReference(reference); objectStream.getIndirectReference().setState(PdfObject.ORIGINAL_OBJECT_STREAM); } finally { tokens = saveTokens;
protected void freeReference(PdfIndirectReference reference) { if (reference.isFree()) { return; } if (reference.checkState(PdfObject.MUST_BE_FLUSHED)) { Logger logger = LoggerFactory.getLogger(PdfXrefTable.class); logger.error(LogMessageConstant.INDIRECT_REFERENCE_USED_IN_FLUSHED_OBJECT_MADE_FREE); return; } if (reference.checkState(PdfObject.FLUSHED)) { Logger logger = LoggerFactory.getLogger(PdfXrefTable.class); logger.error(LogMessageConstant.ALREADY_FLUSHED_INDIRECT_OBJECT_MADE_FREE); return; } reference.setState(PdfObject.FREE).setState(PdfObject.MODIFIED); appendNewRefToFreeList(reference); if (reference.getGenNumber() < MAX_GENERATION) { reference.genNr++; } }
/** * Flushes all modified objects which have not been flushed yet. Used in case incremental updates. * @param forbiddenToFlush {@link Set<PdfIndirectReference>} of references that are forbidden to be flushed automatically. */ protected void flushModifiedWaitingObjects(Set<PdfIndirectReference> forbiddenToFlush) { PdfXrefTable xref = document.getXref(); for (int i = 1; i < xref.size(); i++) { PdfIndirectReference indirectReference = xref.get(i); if (null != indirectReference && !indirectReference.isFree() && !forbiddenToFlush.contains(indirectReference)) { boolean isModified = indirectReference.checkState(PdfObject.MODIFIED); if (isModified) { PdfObject obj = indirectReference.getRefersTo(false); if (obj != null) { if (!obj.equals(objectStream)) { obj.flush(); } } } } } if (objectStream != null && objectStream.getSize() > 0) { objectStream.flush(); objectStream = null; } }
if (isFlushed() || getIndirectReference() == null || getIndirectReference().isFree()) { PdfDocument document = getIndirectReference().getDocument(); if (document != null) { if (document.isAppendMode() && !isModified()) { && getType() != INDIRECT_REFERENCE && getIndirectReference().getGenNumber() == 0);