@@ -1307,6 +1307,7 @@ protected void fixXref() throws IOException {
13071307 }
13081308 }
13091309
1310+
13101311 protected void rebuildXref () throws IOException {
13111312 xrefStm = false ;
13121313 hybridXref = false ;
@@ -1316,40 +1317,70 @@ protected void rebuildXref() throws IOException {
13161317 tokens .seek (0 );
13171318 trailer = null ;
13181319 ByteBuffer buffer = new ByteBuffer (24 );
1319- PdfTokenizer lineTokenizer =
1320- new PdfTokenizer (new RandomAccessFileOrArray (new ReusableRandomAccessSource (buffer )));
1321- for (; ; ) {
1322- long pos = tokens .getPosition ();
1323- buffer .reset ();
1320+ try (PdfTokenizer lineTokenizer = new PdfTokenizer (
1321+ new RandomAccessFileOrArray (new ReusableRandomAccessSource (buffer )))) {
1322+ Long trailerIndex = null ;
13241323
1325- // added boolean because of mailing list issue (17 Feb. 2014)
1326- if (!tokens .readLineSegment (buffer , true ))
1327- break ;
1328- if (buffer .get (0 ) == 't' ) {
1329- if (!PdfTokenizer .checkTrailer (buffer ))
1330- continue ;
1331- tokens .seek (pos );
1332- tokens .nextToken ();
1333- pos = tokens .getPosition ();
1334- try {
1335- PdfDictionary dic = (PdfDictionary ) readObject (false );
1336- if (dic .get (PdfName .Root , false ) != null )
1337- trailer = dic ;
1338- else
1339- tokens .seek (pos );
1340- } catch (Exception e ) {
1341- tokens .seek (pos );
1324+ for (; ; ) {
1325+ long pos = tokens .getPosition ();
1326+ buffer .reset ();
1327+
1328+ // added boolean because of mailing list issue (17 Feb. 2014)
1329+ if (!tokens .readLineSegment (buffer , true )) {
1330+ break ;
13421331 }
1343- } else if (buffer .get (0 ) >= '0' && buffer .get (0 ) <= '9' ) {
1344- int [] obj = PdfTokenizer .checkObjectStart (lineTokenizer );
1345- if (obj == null )
1346- continue ;
1347- int num = obj [0 ];
1348- int gen = obj [1 ];
1349- if (xref .get (num ) == null || xref .get (num ).getGenNumber () <= gen ) {
1350- xref .add (new PdfIndirectReference (pdfDocument , num , gen , pos ));
1332+ if (buffer .get (0 ) == 't' ) {
1333+ if (!PdfTokenizer .checkTrailer (buffer )) {
1334+ continue ;
1335+ }
1336+ tokens .seek (pos );
1337+ tokens .nextToken ();
1338+ pos = tokens .getPosition ();
1339+ if (isCurrentObjectATrailer ()) {
1340+ // if the pdf is linearized it is possible that the trailer has been read
1341+ // before the actual objects it refers to this causes the trailer to have
1342+ // objects in READING state that's why we keep track of the position of the
1343+ // trailer and then asign it when the whole pdf has been loaded
1344+ trailerIndex = pos ;
1345+ } else {
1346+ tokens .seek (pos );
1347+ }
1348+ } else if (buffer .get (0 ) >= '0' && buffer .get (0 ) <= '9' ) {
1349+ int [] obj = PdfTokenizer .checkObjectStart (lineTokenizer );
1350+ if (obj == null ) {
1351+ continue ;
1352+ }
1353+ int num = obj [0 ];
1354+ int gen = obj [1 ];
1355+ if (xref .get (num ) == null || xref .get (num ).getGenNumber () <= gen ) {
1356+ xref .add (new PdfIndirectReference (pdfDocument , num , gen , pos ));
1357+ }
13511358 }
13521359 }
1360+ // now that the document has been read fully the underlying trailer references won't be
1361+ // in READING state when the pdf has been linearised now we can assign the trailer
1362+ // and it will have the right references
1363+ setTrailerFromTrailerIndex (trailerIndex );
1364+ }
1365+ }
1366+
1367+ private boolean isCurrentObjectATrailer () {
1368+ try {
1369+ final PdfDictionary dic = (PdfDictionary ) readObject (false );
1370+ return dic .get (PdfName .Root , false ) != null ;
1371+ } catch (Exception e ) {
1372+ return false ;
1373+ }
1374+ }
1375+
1376+ private void setTrailerFromTrailerIndex (Long trailerIndex ) throws IOException {
1377+ if (trailerIndex == null ) {
1378+ throw new PdfException (KernelExceptionMessageConstant .TRAILER_NOT_FOUND );
1379+ }
1380+ tokens .seek ((long )trailerIndex );
1381+ final PdfDictionary dic = (PdfDictionary ) readObject (false );
1382+ if (dic .get (PdfName .Root , false ) != null ) {
1383+ trailer = dic ;
13531384 }
13541385 if (trailer == null ) {
13551386 throw new PdfException (KernelExceptionMessageConstant .TRAILER_NOT_FOUND );
0 commit comments