Index: pdfbox/src/test/java/org/apache/pdfbox/multipdf/PdfMergeUtilityPagesTest.java
===================================================================
--- pdfbox/src/test/java/org/apache/pdfbox/multipdf/PdfMergeUtilityPagesTest.java (nonexistent)
+++ pdfbox/src/test/java/org/apache/pdfbox/multipdf/PdfMergeUtilityPagesTest.java (working copy)
@@ -0,0 +1,262 @@
+package org.apache.pdfbox.multipdf;
+
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.io.IOUtils;
+import org.apache.pdfbox.io.MemoryUsageSetting;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.junit.Before;
+import org.junit.Ignore;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test works using maven target dir to merge files
+ *
+ * Created by Gary.Potagal on 11/9/2017.
+ */
+
+public class PdfMergeUtilityPagesTest extends TestCase {
+ private static final Log LOG = LogFactory.getLog(PdfMergeUtilityPagesTest.class);
+ private static final long K = 1024l;
+ private static final long MEG = K * K;
+ //private static final long GIG = K * MEG;
+
+
+ private static final String SRCDIR = "src/test/resources/input/merge";
+ private static final String TARGETTESTDIR = "target/test-output/merge/pages";
+ private static final String SCRATCHDIR = "target/test-output/merge/pages/scratch";
+
+
+ private File testsDataFolder;
+ double totalSeconds = 0;
+ long totalPages = 0;
+ DecimalFormat decimal3Format = new DecimalFormat("###,#,##0.000");
+ DecimalFormat decimal0Format = new DecimalFormat("###,#,##0");
+
+ @Override
+ protected void setUp() throws Exception {
+ testsDataFolder = new File(new StringBuilder(SRCDIR).append(File.separator).append("pages").toString());
+ System.out.println(testsDataFolder.getPath());
+
+
+ File tmpPdfPathFolder = new File(SCRATCHDIR);
+ LOG.info("Creating scratch directory: " + tmpPdfPathFolder.getAbsolutePath());
+ if(tmpPdfPathFolder.exists()) {
+ tmpPdfPathFolder.delete();
+ }
+ tmpPdfPathFolder.mkdirs();
+ // create test files before running other tests to so not in recent disk cache
+ generatedMergeTestData("pdf_sample_1.pdf", "pdf_sample_1-100pages", 100);
+ generatedMergeTestData("pdf_sample_1.pdf", "pdf_sample_1-200pages",200);
+ generatedMergeTestData("pdf_sample_1.pdf", "pdf_sample_1-300pages",300);
+ generatedMergeTestData("pdf_sample_1.pdf", "pdf_sample_1-400pages",400);
+
+ }
+
+
+ public void testPerformanceMerge() throws IOException {
+
+ totalSeconds = 0.0;
+ totalPages = 0;
+ long defaultMemory = 10 * MEG;
+
+ for(int pass = 0; pass < 1; pass++) {
+
+
+ runMergeTest("pdf_sample_1-100pages", defaultMemory, 74 * MEG);
+ runMergeTest("pdf_sample_1-200pages", defaultMemory, 315 * MEG);
+ runMergeTest("pdf_sample_1-300pages", defaultMemory, 710 * MEG);
+ runMergeTest("pdf_sample_1-400pages", defaultMemory, 1240 * MEG);
+
+
+ }
+ double average = (((double)totalPages) / totalSeconds);
+ LOG.info(String.format(
+ "Summary: Pages: %d, Time(s): %s, Pages/Second: %s", totalPages, decimal3Format.format(totalSeconds), decimal3Format.format(average)));
+ }
+
+
+ private void generatedMergeTestData(String sourceDocument, String dataSet, int copies) throws IOException {
+
+ File source = new File(testsDataFolder, sourceDocument);
+ String directoryPrefix = source.getName().replace(".pdf", "");
+ File targetDirectory = new File(testsDataFolder, dataSet);
+ if (targetDirectory.exists()) {
+ LOG.info("Already Generated: " + dataSet);
+ return;
+ }
+ LOG.info("Generating: " + dataSet);
+ targetDirectory.mkdirs();
+
+ for (int copy = 1; copy <= copies; copy++) {
+
+ FileInputStream in = null;
+ FileOutputStream out = null;
+
+ try {
+ in = new FileInputStream(source);
+ File newFile = new File(targetDirectory, new StringBuilder(Integer.toString(copy)).append("-").append(directoryPrefix).append(".pdf").toString());
+
+ out = new FileOutputStream(newFile);
+ IOUtils.copy(in, out);
+ }finally {
+ IOUtils.closeQuietly(in);
+ IOUtils.closeQuietly(out);
+ }
+ }
+
+ }
+
+
+ private void runMergeTest(String dataSet, long maxMemorySize, long maxMemoryPlusDiskSize) throws IOException {
+ List testFiles = new ArrayList();
+ int testPages = 0;
+
+ File testFolder = new File(testsDataFolder, dataSet);
+ File[] files = testFolder.listFiles();
+ long sourceSize = 0;
+ for(File f: files) {
+ String[] splits = f.getName().split("_");
+ String pages = splits[splits.length-1].replace(".pdf", "");
+ testPages += Integer.parseInt(pages);
+ sourceSize += f.length();
+ testFiles.add(f.getAbsolutePath());
+
+ }
+
+ File outFile = createOutputFile(TARGETTESTDIR, dataSet + "-mergeOutFile.pdf");
+ if (!outFile.exists()) {
+ outFile.createNewFile();
+ }
+ long startTime = System.currentTimeMillis();
+ merge(testFiles,
+ new FileOutputStream(outFile),
+ maxMemorySize,
+ maxMemoryPlusDiskSize);
+ double deltaSeconds = System.currentTimeMillis() - startTime;
+ deltaSeconds /= 1000.0f;
+ totalSeconds += deltaSeconds;
+ totalPages += testPages;
+ assertTrue(String.format("File %s did not get created", outFile), outFile.exists());
+ int pagesMerged = countPages(outFile.getPath());
+ double average = (((double)pagesMerged) / deltaSeconds);
+ long outputSize = outFile.length();
+ float ratio = maxMemoryPlusDiskSize / outputSize;
+ LOG.info(String.format("Test Name: %s; Files: %d; Pages: %s; Time(s): %s; Pages/Second: %s; MaxMainMemoryBytes(MB): %s; MaxStorageBytes(MB): %s; Total Sources Size(K): %s; Merged File Size(K): %s; Ratio MaxStorageBytes/Merged File Size: %s",
+ dataSet, files.length, testPages, decimal3Format.format(deltaSeconds), decimal3Format.format(average),
+ decimal0Format.format(maxMemorySize/MEG), decimal0Format.format(maxMemoryPlusDiskSize/MEG),
+ decimal0Format.format(sourceSize/K), decimal0Format.format(outputSize/K), decimal0Format.format(ratio)));
+ assertEquals(String.format("Test Name: {}", dataSet), testPages, pagesMerged);
+ }
+
+
+
+ /** Utility Functions **/
+
+
+
+ /**
+ * Create output file in Test output directory
+ *
+ * @param outPath - pdf.out.path defined in test properties file
+ * @param name - file name
+ * @return - File Object with file path set up
+ * @throws IOException - if file can't be created
+ */
+ private File createOutputFile(final String outPath, final String name) throws IOException {
+
+ String fdfOutFilePath = new StringBuilder(outPath)
+ .append(File.separator).append(name).toString();
+
+ File outFolder = new File(outPath);
+ if (!outFolder.exists()) {
+ outFolder.mkdir();
+ }
+
+ File outFile = new File(fdfOutFilePath);
+ if (outFile.exists()) {
+ outFile.delete();
+ }
+ outFile.createNewFile();
+ return outFile;
+ }
+
+ /**
+ * Open a PDF Document and return number of pages
+ * @param path of the PDF Document
+ * @return
+ * @throws IOException
+ */
+ private int countPages(final String path) throws IOException {
+ int pages = 0;
+
+ PDDocument doc = PDDocument.load(new File(path));
+ pages = doc.getNumberOfPages();
+ doc.close();
+ return pages;
+ }
+
+
+ /**
+ * Use PDFMergeUtility to merge, validates that file exists
+ *
+ * @param documents
+ * @param out
+ * @param maxMainMemoryBytes
+ * @param maxStorageBytes
+ * @throws IOException
+ */
+ private void merge(List documents,
+ OutputStream out,
+ long maxMainMemoryBytes,
+ long maxStorageBytes)
+ throws IOException {
+
+ PDFMergerUtility mergePdf = new PDFMergerUtility();
+ mergePdf.setDestinationStream(out);
+
+ int sourceCount = 0;
+
+ for (String document : documents) {
+ sourceCount = sourceCount + addSource(document, mergePdf);
+ }
+
+ if(sourceCount == 0) {
+ throw new IOException("Unable to find any resources form the URIs passed in");
+ }
+
+ MemoryUsageSetting setting = MemoryUsageSetting.setupMixed(maxMainMemoryBytes, maxStorageBytes);
+ setting.setTempDir(new File(SCRATCHDIR));
+ LOG.debug(String.format("Using %d max storage bytes in tmp location %s", maxStorageBytes, setting.getTempDir().getPath()));
+ long startTime = System.currentTimeMillis();
+ mergePdf.mergeDocuments(setting);
+ long endTime = System.currentTimeMillis();
+ LOG.debug(String.format("Merged %d sources in %d milliseconds", sourceCount, endTime - startTime));
+
+ }
+
+
+ private int addSource(final String document, final PDFMergerUtility mergePDF) {
+
+ //Warn, but don't exist if the file is not found
+ File sourceFile = new File(document);
+ try {
+ mergePDF.addSource(sourceFile);
+ } catch (FileNotFoundException e) {
+ LOG.warn("File not found, skipping: " + document);
+ return 0;
+ }
+
+ return 1;
+ }
+}
Index: pdfbox/src/test/resources/input/merge/pages/pdf_sample_1.pdf
===================================================================
--- pdfbox/src/test/resources/input/merge/pages/pdf_sample_1.pdf (nonexistent)
+++ pdfbox/src/test/resources/input/merge/pages/pdf_sample_1.pdf (working copy)
@@ -0,0 +1,99 @@
+%PDF-1.3
%
+7 0 obj
<>
endobj
+13 0 obj
<>/Filter/FlateDecode/ID[<4DC91A1875A6D707AEC203BB021C93A0>]/Index[7 21]/Info 6 0 R/Length 52/Prev 7657/Root 8 0 R/Size 28/Type/XRef/W[1 2 1]>>stream
+hbbd``b` H0 6G #4,#Ɲ_ L
+endstream
endobj
startxref
+0
+%%EOF
+
+27 0 obj
<>stream
+hb```a`` 6$р,
t&8Z-,
+endstream
endobj
8 0 obj
<>
endobj
9 0 obj
<>
endobj
10 0 obj
<>stream
+hTmo0+q"UHЎZ&[?DBW~w .+҈|0&'"&FTȈ$&gZၭDHb!($UQ&\4
+/c~4߶:Ń*-M [4M%M}xgg>ydlBgWSMG^f,C?P6uMPrt>=Ҹ\A^ؐPB
CTJV5*/mmx!DBј?_OO64 EalS,"/$k&F/Ǫx=DX1UE#4~9(wI3o9DDB &_,at9ٲƴVIM>gi$`2Hӻlmγb0mLolVq,Y*z0:ت>|݁F_Ӽn*]|{wHl|lONlb\/IFJ~ki*}}ֺ//[->Aw GS0{ 4w}YcvtЂ)@dCcѦVOAf{u;B)ДءpO
ؽ z'#>Ke|$ʑ]|94Nj,-0藤]Ir|̆x$۾e(E>Ӆܩbb=\q1
+bW@? >Њ
+endstream
endobj
11 0 obj
<>stream
+HWKo6Fs[t)b+n$*dSi{-
+,ZPr曙o?tۮ aqR@2!9-^FxU&QȽ^Q/SbśE[1IQT_u-qk,Ya}I#pwYGsȉpFj *08,sﲔqP+NEf#_ZsBh[2
C8YNbQ?0k+W&'PjQ̐ܛeZfZ8́]F/{"MVK
az2 S>Wega$Y+RH}uPWP\TxpWHV%sEߠ__4zS=^aIp
+(0A#HOѶ@#f
n&*I !@0bNq$`+Ʀ>ӤDO;FN4^1;
+s}M{:LrdN"dLQt
O
rhdbbTp*/qEUCv#^=2`#F`E&((,2?Q ӶWIߘ@BcdRM{\>(/.*rQ?\NHD/hZW3YsU5Dj/.NT[QE&ƿ3 QQ?#?5ߋ6iݦЦmt7q1ڞ"/Ȇ)e
+z(˭kPq.]4oCDIlAqz+la{g,~..Cypd+ L0
+4¾L*7ov4giPeD%]lY g'դJI^X,GM)-,H
j*>1
36f`Zpdj@B6M䈈۳AAIwVn?~-J?3~vFn4/l*,S`dDA .Y*ysDOtAaD%w ]sh>7IN~S:IT8sO驽*y,`:+a)e*<&CFRͣ_yi>dU}p_D]F ]c4K]heQxsWā?v
+
+endstream
endobj
12 0 obj
<>stream
+HT0>GCUX:#
+iVз')Kӝ-͡!@\ة4&V(AnJ"<
*(gشsoAY#`s+8h'hPנ(IZ.b5tG/ʋ]!Ve^u[M1ֲ(e0ߋxezK Ci?
+
+endstream
endobj
1 0 obj
<>stream
+
+
+
+
+ application/pdf
+
+
+ cdaily
+
+
+
+
+ This is a test PDF file
+
+
+
+
+ 2000-06-29T10:21:08+11:00
+ Microsoft Word 8.0
+ 2013-10-28T15:24:13-04:00
+ 2013-10-28T15:24:13-04:00
+
+
+ Acrobat Distiller 4.0 for Windows
+
+
+ uuid:0805e221-80a8-459e-a522-635ed5c1e2e6
+ uuid:62d6ae6d-43c4-472d-9b28-7c4add8f9e46
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+endstream
endobj
2 0 obj
<>stream
+h2U0Pw/+Q0L)T$ w
+endstream
endobj
3 0 obj
<>stream
+h<
+0E_
*UJX .ױI@@2E{| MSvLY
+oUB]O+S
+G#GxTy' O gA|)xն gg;d
+endstream
endobj
4 0 obj
<>/Filter/FlateDecode/ID[<4DC91A1875A6D707AEC203BB021C93A0>]/Info 6 0 R/Length 37/Root 8 0 R/Size 7/Type/XRef/W[1 2 0]>>stream
+hbb```b=?$` *Y
+endstream
endobj
startxref
+116
+%%EOF
Property changes on: pdfbox/src/test/resources/input/merge/pages/pdf_sample_1.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property