Program: 24652
Project: 24652
Buggy source:
/** 
 * Do the work of joining the FOP output and a PDF together. This involves several steps: 1. Based on parameters specified in the PipeFOP command, determine how the pages will overlap. 2. Merge bookmarks and metadata 3. Output the pages  
 */
private void mergePdf(XPathContext context,File origPdfData,File fileToAppend,MergeMode mergeMode,MergeAt mergeAt,OutputStream outStream) throws IOException, DocumentException, BadPdfFormatException, XPathException {
  RandomAccessFileOrArray[] randFiles=new RandomAccessFileOrArray[2];
  PdfReader[] readers=new PdfReader[2];
  HashMap<String,String>[] infos=new HashMap[2];
  int[] nInPages=new int[2];
  int[] pageOffsets=new int[2];
  int nOutPages=0;
  randFiles[0]=(origPdfData.length() > 1024 * 1024) ? new BufferedRandomAccessFile(origPdfData.toString()) : new RandomAccessFileOrArray(origPdfData.toString());
  randFiles[1]=(fileToAppend.length() > 1024 * 1024) ? new BufferedRandomAccessFile(fileToAppend.toString()) : new RandomAccessFileOrArray(fileToAppend.toString());
  readers[0]=new PdfReader(randFiles[0],null);
  readers[1]=new PdfReader(randFiles[1],null);
  for (int i=0; i < 2; i++) {
    readers[i].consolidateNamedDestinations();
    infos[i]=readers[i].getInfo();
    nInPages[i]=readers[i].getNumberOfPages();
  }
switch (mergeMode) {
case SEQUENTIAL:
    nOutPages=nInPages[0] + nInPages[1];
switch (mergeAt) {
case START:
    pageOffsets[0]=nInPages[1];
  pageOffsets[1]=0;
break;
case END:
pageOffsets[0]=0;
pageOffsets[1]=nInPages[0];
break;
}
break;
case OVERLAY:
case UNDERLAY:
nOutPages=Math.max(nInPages[0],nInPages[1]);
pageOffsets[0]=0;
if (mergeAt == MergeAt.END) pageOffsets[1]=Math.max(0,nInPages[0] - nInPages[1]);
 else pageOffsets[1]=0;
break;
}
Document pdfDocument=new Document(readers[0].getPageSizeWithRotation(1));
PdfCopy pdfWriter=new PdfCopy(pdfDocument,outStream);
pdfDocument.open();
mergeMetadata(infos,pdfWriter,context);
ArrayList allBookmarks=new ArrayList();
for (int i=0; i < 2; i++) {
List bookmarks=SimpleBookmark.getBookmark(readers[i]);
if (bookmarks != null) {
if (pageOffsets[i] != 0) SimpleBookmark.shiftPageNumbers(bookmarks,pageOffsets[i],null);
allBookmarks.addAll(bookmarks);
}
}
PageInfo[] basePages=new PageInfo[nOutPages];
PageInfo[] mergePages=new PageInfo[nOutPages];
for (int i=0; i < nOutPages; i++) {
for (int j=0; j < 2; j++) {
int inPageNum=i - pageOffsets[j];
if (inPageNum < 0 || inPageNum >= nInPages[j]) continue;
PageInfo info=new PageInfo();
info.reader=readers[j];
info.pageNum=inPageNum + 1;
if (basePages[i] == null) basePages[i]=info;
 else {
info.impPage=pdfWriter.getImportedPage(info.reader,info.pageNum);
info.image=Image.getInstance(info.impPage);
mergePages[i]=info;
}
}
}
for (int i=0; i < nOutPages; i++) {
PageInfo basePage=basePages[i];
PageInfo mergePage=mergePages[i];
boolean over=mergeMode == MergeMode.OVERLAY;
basePage.impPage=pdfWriter.getImportedPage(basePage.reader,basePage.pageNum);
if (mergePage != null) {
PageStamp ps=pdfWriter.createPageStamp(basePage.impPage);
PdfContentByte contentBuf=null;
if (over) contentBuf=ps.getOverContent();
 else contentBuf=ps.getUnderContent();
Image img=Image.getInstance(mergePage.image);
int rotation=mergePage.reader.getPageRotation(mergePage.pageNum);
float w=basePage.impPage.getWidth();
float h=basePage.impPage.getHeight();
switch (rotation) {
case 0:
contentBuf.addImage(img,w,0,0,h,0,0);
break;
case 90:
contentBuf.addImage(img,0,-h,w,0,0,h);
break;
case 180:
contentBuf.addImage(img,-w,0,0,-h,w,h);
break;
case 270:
contentBuf.addImage(img,0,h,-w,0,w,0);
break;
}
ps.alterContents();
}
pdfWriter.addPage(basePage.impPage);
}
if (!allBookmarks.isEmpty()) pdfWriter.setOutlines(allBookmarks);
pdfDocument.close();
}

Fixed version (ground truth):
/** 
 * Do the work of joining the FOP output and a PDF together. This involves several steps: 1. Based on parameters specified in the PipeFOP command, determine how the pages will overlap. 2. Merge bookmarks and metadata 3. Output the pages  
 */
private void mergePdf(XPathContext context,File origPdfData,File fileToAppend,MergeMode mergeMode,MergeAt mergeAt,OutputStream outStream) throws IOException, DocumentException, BadPdfFormatException, XPathException {
  RandomAccessFileOrArray[] randFiles=new RandomAccessFileOrArray[2];
  PdfReader[] readers=new PdfReader[2];
  HashMap<String,String>[] infos=new HashMap[2];
  int[] nInPages=new int[2];
  int[] pageOffsets=new int[2];
  int nOutPages=0;
  try {
    randFiles[0]=(origPdfData.length() > 1024 * 1024) ? new BufferedRandomAccessFile(origPdfData.toString()) : new RandomAccessFileOrArray(origPdfData.toString());
    randFiles[1]=(fileToAppend.length() > 1024 * 1024) ? new BufferedRandomAccessFile(fileToAppend.toString()) : new RandomAccessFileOrArray(fileToAppend.toString());
    readers[0]=new PdfReader(randFiles[0],null);
    readers[1]=new PdfReader(randFiles[1],null);
    for (int i=0; i < 2; i++) {
      readers[i].consolidateNamedDestinations();
      infos[i]=readers[i].getInfo();
      nInPages[i]=readers[i].getNumberOfPages();
    }
switch (mergeMode) {
case SEQUENTIAL:
      nOutPages=nInPages[0] + nInPages[1];
switch (mergeAt) {
case START:
      pageOffsets[0]=nInPages[1];
    pageOffsets[1]=0;
  break;
case END:
pageOffsets[0]=0;
pageOffsets[1]=nInPages[0];
break;
}
break;
case OVERLAY:
case UNDERLAY:
nOutPages=Math.max(nInPages[0],nInPages[1]);
pageOffsets[0]=0;
if (mergeAt == MergeAt.END) pageOffsets[1]=Math.max(0,nInPages[0] - nInPages[1]);
 else pageOffsets[1]=0;
break;
}
Document pdfDocument=new Document(readers[0].getPageSizeWithRotation(1));
PdfCopy pdfWriter=new PdfCopy(pdfDocument,outStream);
pdfDocument.open();
mergeMetadata(infos,pdfWriter,context);
ArrayList allBookmarks=new ArrayList();
for (int i=0; i < 2; i++) {
List bookmarks=SimpleBookmark.getBookmark(readers[i]);
if (bookmarks != null) {
if (pageOffsets[i] != 0) SimpleBookmark.shiftPageNumbers(bookmarks,pageOffsets[i],null);
allBookmarks.addAll(bookmarks);
}
}
PageInfo[] basePages=new PageInfo[nOutPages];
PageInfo[] mergePages=new PageInfo[nOutPages];
for (int i=0; i < nOutPages; i++) {
for (int j=0; j < 2; j++) {
int inPageNum=i - pageOffsets[j];
if (inPageNum < 0 || inPageNum >= nInPages[j]) continue;
PageInfo info=new PageInfo();
info.reader=readers[j];
info.pageNum=inPageNum + 1;
if (basePages[i] == null) basePages[i]=info;
 else {
info.impPage=pdfWriter.getImportedPage(info.reader,info.pageNum);
info.image=Image.getInstance(info.impPage);
mergePages[i]=info;
}
}
}
for (int i=0; i < nOutPages; i++) {
PageInfo basePage=basePages[i];
PageInfo mergePage=mergePages[i];
boolean over=mergeMode == MergeMode.OVERLAY;
basePage.impPage=pdfWriter.getImportedPage(basePage.reader,basePage.pageNum);
if (mergePage != null) {
PageStamp ps=pdfWriter.createPageStamp(basePage.impPage);
PdfContentByte contentBuf=null;
if (over) contentBuf=ps.getOverContent();
 else contentBuf=ps.getUnderContent();
Image img=Image.getInstance(mergePage.image);
int rotation=mergePage.reader.getPageRotation(mergePage.pageNum);
float w=basePage.impPage.getWidth();
float h=basePage.impPage.getHeight();
switch (rotation) {
case 0:
contentBuf.addImage(img,w,0,0,h,0,0);
break;
case 90:
contentBuf.addImage(img,0,-h,w,0,0,h);
break;
case 180:
contentBuf.addImage(img,-w,0,0,-h,w,h);
break;
case 270:
contentBuf.addImage(img,0,h,-w,0,w,0);
break;
}
ps.alterContents();
}
pdfWriter.addPage(basePage.impPage);
}
if (!allBookmarks.isEmpty()) pdfWriter.setOutlines(allBookmarks);
pdfDocument.close();
}
  finally {
if (randFiles[0] != null) try {
randFiles[0].close();
}
 catch (Exception e) {
}
if (randFiles[1] != null) try {
randFiles[1].close();
}
 catch (Exception e) {
}
}
}