新疆交投路损赔补偿系统 v1.0.2版本的 MD5 值为:5e336668c8c96e65d739f00d1fa2a3b9
以下内容为反编译后的 CompareTool.java 源代码,内容仅作参考
package com.itextpdf.testutils;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Meta;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PRIndirectReference;
import com.itextpdf.text.pdf.PRStream;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfArray;
import com.itextpdf.text.pdf.PdfBoolean;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfIndirectReference;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfNumber;
import com.itextpdf.text.pdf.PdfObject;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.RefKey;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.PdfContentStreamProcessor;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.SimpleTextExtractionStrategy;
import com.itextpdf.text.pdf.parser.TaggedPdfReaderTool;
import com.itextpdf.text.pdf.parser.TextExtractionStrategy;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import com.itextpdf.text.xml.XMLUtil;
import com.itextpdf.text.xml.xmp.PdfProperties;
import com.itextpdf.text.xml.xmp.XmpBasicProperties;
import com.itextpdf.xmp.XMPException;
import com.itextpdf.xmp.XMPMeta;
import com.itextpdf.xmp.XMPMetaFactory;
import com.itextpdf.xmp.XMPUtils;
import com.itextpdf.xmp.options.SerializeOptions;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class CompareTool {
private static final String cannotOpenTargetDirectory = "Cannot open target directory for <filename>.";
private static final String differentPages = "File <filename> differs on page <pagenumber>.";
private static final String gsFailed = "GhostScript failed for <filename>.";
private static final String ignoredAreasPrefix = "ignored_areas_";
private static final String undefinedGsPath = "Path to GhostScript is not specified. Please use -DgsExec=<path_to_ghostscript> (e.g. -DgsExec=\"C:/Program Files/gs/gs9.14/bin/gswin32c.exe\")";
private static final String unexpectedNumberOfPages = "Unexpected number of pages for <filename>.";
private String cmpImage;
List<PdfDictionary> cmpPages;
List<RefKey> cmpPagesRef;
private String cmpPdf;
private String cmpPdfName;
private String compareExec;
private String gsExec;
private String outImage;
List<PdfDictionary> outPages;
List<RefKey> outPagesRef;
private String outPdf;
private String outPdfName;
private final String gsParams = " -dNOPAUSE -dBATCH -sDEVICE=png16m -r150 -sOutputFile=<outputfile> <inputfile>";
private final String compareParams = " <image1> <image2> <difference>";
public CompareTool(String outPdf, String cmpPdf) {
init(outPdf, cmpPdf);
this.gsExec = System.getProperty("gsExec");
this.compareExec = System.getProperty("compareExec");
}
public String compare(String outPath, String differenceImagePrefix) throws IOException, InterruptedException, DocumentException {
return compare(outPath, differenceImagePrefix, null);
}
public String compare(String outPath, String differenceImagePrefix, Map<Integer, List<Rectangle>> ignoredAreas) throws IOException, InterruptedException, DocumentException {
return compare(outPath, differenceImagePrefix, ignoredAreas, (List<Integer>) null);
}
protected String compare(String outPath, String differenceImagePrefix, Map<Integer, List<Rectangle>> ignoredAreas, List<Integer> equalPages) throws IOException, InterruptedException, DocumentException {
File[] imageFiles;
File[] cmpImageFiles;
if (this.gsExec == null) {
return undefinedGsPath;
}
if (!new File(this.gsExec).exists()) {
return new File(this.gsExec).getAbsolutePath() + " does not exist";
}
if (!outPath.endsWith("/")) {
outPath = outPath + "/";
}
File targetDir = new File(outPath);
if (!targetDir.exists()) {
targetDir.mkdir();
} else {
for (File file : targetDir.listFiles(new PngFileFilter())) {
file.delete();
}
for (File file2 : targetDir.listFiles(new CmpPngFileFilter())) {
file2.delete();
}
}
File diffFile = new File(outPath + differenceImagePrefix);
if (diffFile.exists()) {
diffFile.delete();
}
if (ignoredAreas != null && !ignoredAreas.isEmpty()) {
PdfReader cmpReader = new PdfReader(this.cmpPdf);
PdfReader outReader = new PdfReader(this.outPdf);
PdfStamper outStamper = new PdfStamper(outReader, new FileOutputStream(outPath + ignoredAreasPrefix + this.outPdfName));
PdfStamper cmpStamper = new PdfStamper(cmpReader, new FileOutputStream(outPath + ignoredAreasPrefix + this.cmpPdfName));
for (Map.Entry<Integer, List<Rectangle>> entry : ignoredAreas.entrySet()) {
int pageNumber = entry.getKey().intValue();
List<Rectangle> rectangles = entry.getValue();
if (rectangles != null && !rectangles.isEmpty()) {
PdfContentByte outCB = outStamper.getOverContent(pageNumber);
PdfContentByte cmpCB = cmpStamper.getOverContent(pageNumber);
for (Rectangle rect : rectangles) {
rect.setBackgroundColor(BaseColor.BLACK);
outCB.rectangle(rect);
cmpCB.rectangle(rect);
}
}
}
outStamper.close();
cmpStamper.close();
outReader.close();
cmpReader.close();
init(outPath + ignoredAreasPrefix + this.outPdfName, outPath + ignoredAreasPrefix + this.cmpPdfName);
}
if (targetDir.exists()) {
getClass();
String gsParams = " -dNOPAUSE -dBATCH -sDEVICE=png16m -r150 -sOutputFile=<outputfile> <inputfile>".replace("<outputfile>", outPath + this.cmpImage).replace("<inputfile>", this.cmpPdf);
Process p = Runtime.getRuntime().exec(this.gsExec + gsParams);
BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader bre = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while (true) {
String line = bri.readLine();
if (line == null) {
break;
}
System.out.println(line);
}
bri.close();
while (true) {
String line2 = bre.readLine();
if (line2 == null) {
break;
}
System.out.println(line2);
}
bre.close();
if (p.waitFor() == 0) {
getClass();
String gsParams2 = " -dNOPAUSE -dBATCH -sDEVICE=png16m -r150 -sOutputFile=<outputfile> <inputfile>".replace("<outputfile>", outPath + this.outImage).replace("<inputfile>", this.outPdf);
Process p2 = Runtime.getRuntime().exec(this.gsExec + gsParams2);
BufferedReader bri2 = new BufferedReader(new InputStreamReader(p2.getInputStream()));
BufferedReader bre2 = new BufferedReader(new InputStreamReader(p2.getErrorStream()));
while (true) {
String line3 = bri2.readLine();
if (line3 == null) {
break;
}
System.out.println(line3);
}
bri2.close();
while (true) {
String line4 = bre2.readLine();
if (line4 == null) {
break;
}
System.out.println(line4);
}
bre2.close();
int exitValue = p2.waitFor();
if (exitValue == 0) {
File[] imageFiles2 = targetDir.listFiles(new PngFileFilter());
File[] cmpImageFiles2 = targetDir.listFiles(new CmpPngFileFilter());
boolean bUnexpectedNumberOfPages = false;
if (imageFiles2.length != cmpImageFiles2.length) {
bUnexpectedNumberOfPages = true;
}
int cnt = Math.min(imageFiles2.length, cmpImageFiles2.length);
if (cnt < 1) {
return "No files for comparing!!!\nThe result or sample pdf file is not processed by GhostScript.";
}
Arrays.sort(imageFiles2, new ImageNameComparator());
Arrays.sort(cmpImageFiles2, new ImageNameComparator());
String differentPagesFail = null;
for (int i = 0; i < cnt; i++) {
if (equalPages == null || !equalPages.contains(Integer.valueOf(i))) {
System.out.print("Comparing page " + Integer.toString(i + 1) + " (" + imageFiles2[i].getAbsolutePath() + ")...");
FileInputStream is1 = new FileInputStream(imageFiles2[i]);
FileInputStream is2 = new FileInputStream(cmpImageFiles2[i]);
boolean cmpResult = compareStreams(is1, is2);
is1.close();
is2.close();
if (!cmpResult) {
if (this.compareExec != null && new File(this.compareExec).exists()) {
getClass();
String compareParams = " <image1> <image2> <difference>".replace("<image1>", imageFiles2[i].getAbsolutePath()).replace("<image2>", cmpImageFiles2[i].getAbsolutePath()).replace("<difference>", outPath + differenceImagePrefix + Integer.toString(i + 1) + ".png");
Process p3 = Runtime.getRuntime().exec(this.compareExec + compareParams);
BufferedReader bre3 = new BufferedReader(new InputStreamReader(p3.getErrorStream()));
while (true) {
String line5 = bre3.readLine();
if (line5 == null) {
break;
}
System.out.println(line5);
}
bre3.close();
int cmpExitValue = p3.waitFor();
if (cmpExitValue == 0) {
if (differentPagesFail == null) {
String differentPagesFail2 = differentPages.replace("<filename>", this.outPdf).replace("<pagenumber>", Integer.toString(i + 1));
differentPagesFail = differentPagesFail2 + "\nPlease, examine " + outPath + differenceImagePrefix + Integer.toString(i + 1) + ".png for more details.";
} else {
differentPagesFail = "File " + this.outPdf + " differs.\nPlease, examine difference images for more details.";
}
} else {
differentPagesFail = differentPages.replace("<filename>", this.outPdf).replace("<pagenumber>", Integer.toString(i + 1));
}
System.out.println(differentPagesFail);
} else {
String differentPagesFail3 = differentPages.replace("<filename>", this.outPdf).replace("<pagenumber>", Integer.toString(i + 1));
differentPagesFail = differentPagesFail3 + "\nYou can optionally specify path to ImageMagick compare tool (e.g. -DcompareExec=\"C:/Program Files/ImageMagick-6.5.4-2/compare.exe\") to visualize differences.";
break;
}
} else {
System.out.println("done.");
}
}
}
if (differentPagesFail == null) {
if (bUnexpectedNumberOfPages) {
String differentPagesFail4 = unexpectedNumberOfPages.replace("<filename>", this.outPdf);
return differentPagesFail4;
}
return null;
}
return differentPagesFail;
}
return gsFailed.replace("<filename>", this.outPdf);
}
return gsFailed.replace("<filename>", this.cmpPdf);
}
return cannotOpenTargetDirectory.replace("<filename>", this.outPdf);
}
public String compare(String outPdf, String cmpPdf, String outPath, String differenceImagePrefix, Map<Integer, List<Rectangle>> ignoredAreas) throws IOException, InterruptedException, DocumentException {
init(outPdf, cmpPdf);
return compare(outPath, differenceImagePrefix, ignoredAreas);
}
public String compare(String outPdf, String cmpPdf, String outPath, String differenceImagePrefix) throws IOException, InterruptedException, DocumentException {
return compare(outPdf, cmpPdf, outPath, differenceImagePrefix, null);
}
public String compareByContent(String outPath, String differenceImagePrefix, Map<Integer, List<Rectangle>> ignoredAreas) throws DocumentException, InterruptedException, IOException {
PdfReader outReader = new PdfReader(this.outPdf);
this.outPages = new ArrayList();
this.outPagesRef = new ArrayList();
loadPagesFromReader(outReader, this.outPages, this.outPagesRef);
PdfReader cmpReader = new PdfReader(this.cmpPdf);
this.cmpPages = new ArrayList();
this.cmpPagesRef = new ArrayList();
loadPagesFromReader(cmpReader, this.cmpPages, this.cmpPagesRef);
if (this.outPages.size() != this.cmpPages.size()) {
return compare(outPath, differenceImagePrefix, ignoredAreas);
}
List<Integer> equalPages = new ArrayList<>(this.cmpPages.size());
for (int i = 0; i < this.cmpPages.size(); i++) {
if (objectsIsEquals(this.outPages.get(i), this.cmpPages.get(i))) {
equalPages.add(Integer.valueOf(i));
}
}
outReader.close();
cmpReader.close();
if (equalPages.size() == this.cmpPages.size()) {
return null;
}
String message = compare(outPath, differenceImagePrefix, ignoredAreas, equalPages);
if (message == null || message.length() == 0) {
return "Compare by content fails. No visual differences";
}
return message;
}
public String compareByContent(String outPath, String differenceImagePrefix) throws DocumentException, InterruptedException, IOException {
return compareByContent(outPath, differenceImagePrefix, null);
}
public String compareByContent(String outPdf, String cmpPdf, String outPath, String differenceImagePrefix, Map<Integer, List<Rectangle>> ignoredAreas) throws DocumentException, InterruptedException, IOException {
init(outPdf, cmpPdf);
return compareByContent(outPath, differenceImagePrefix, ignoredAreas);
}
public String compareByContent(String outPdf, String cmpPdf, String outPath, String differenceImagePrefix) throws DocumentException, InterruptedException, IOException {
return compareByContent(outPdf, cmpPdf, outPath, differenceImagePrefix, null);
}
private void loadPagesFromReader(PdfReader reader, List<PdfDictionary> pages, List<RefKey> pagesRef) {
PdfObject pagesDict = reader.getCatalog().get(PdfName.PAGES);
addPagesFromDict(pagesDict, pages, pagesRef);
}
private void addPagesFromDict(PdfObject dictRef, List<PdfDictionary> pages, List<RefKey> pagesRef) {
PdfDictionary dict = (PdfDictionary) PdfReader.getPdfObject(dictRef);
if (dict.isPages()) {
PdfArray kids = dict.getAsArray(PdfName.KIDS);
if (kids != null) {
Iterator i$ = kids.iterator();
while (i$.hasNext()) {
PdfObject kid = i$.next();
addPagesFromDict(kid, pages, pagesRef);
}
}
} else if (dict.isPage()) {
pages.add(dict);
pagesRef.add(new RefKey((PdfIndirectReference) ((PRIndirectReference) dictRef)));
}
}
private boolean objectsIsEquals(PdfDictionary outDict, PdfDictionary cmpDict) throws IOException {
for (PdfName key : cmpDict.getKeys()) {
if (key.compareTo(PdfName.PARENT) != 0) {
if (key.compareTo(PdfName.BASEFONT) == 0 || key.compareTo(PdfName.FONTNAME) == 0) {
PdfObject cmpObj = cmpDict.getDirectObject(key);
if (cmpObj.isName() && cmpObj.toString().indexOf(43) > 0) {
PdfObject outObj = outDict.getDirectObject(key);
if (!outObj.isName()) {
return false;
}
String cmpName = cmpObj.toString().substring(cmpObj.toString().indexOf(43));
String outName = outObj.toString().substring(outObj.toString().indexOf(43));
if (!cmpName.equals(outName)) {
return false;
}
}
}
if (!objectsIsEquals(outDict.get(key), cmpDict.get(key))) {
return false;
}
}
}
return true;
}
private boolean objectsIsEquals(PdfObject outObj, PdfObject cmpObj) throws IOException {
PdfObject outDirectObj = PdfReader.getPdfObject(outObj);
PdfObject cmpDirectObj = PdfReader.getPdfObject(cmpObj);
if (outDirectObj == null || cmpDirectObj.type() != outDirectObj.type()) {
return false;
}
if (cmpDirectObj.isDictionary()) {
PdfDictionary cmpDict = (PdfDictionary) cmpDirectObj;
PdfDictionary outDict = (PdfDictionary) outDirectObj;
if (cmpDict.isPage()) {
if (outDict.isPage()) {
RefKey cmpRefKey = new RefKey((PdfIndirectReference) ((PRIndirectReference) cmpObj));
RefKey outRefKey = new RefKey((PdfIndirectReference) ((PRIndirectReference) outObj));
return this.cmpPagesRef.contains(cmpRefKey) && this.cmpPagesRef.indexOf(cmpRefKey) == this.outPagesRef.indexOf(outRefKey);
}
return false;
} else if (!objectsIsEquals(outDict, cmpDict)) {
return false;
}
} else if (cmpDirectObj.isStream()) {
if (!objectsIsEquals((PRStream) outDirectObj, (PRStream) cmpDirectObj)) {
return false;
}
} else if (cmpDirectObj.isArray()) {
if (!objectsIsEquals((PdfArray) outDirectObj, (PdfArray) cmpDirectObj)) {
return false;
}
} else if (cmpDirectObj.isName()) {
if (!objectsIsEquals((PdfName) outDirectObj, (PdfName) cmpDirectObj)) {
return false;
}
} else if (cmpDirectObj.isNumber()) {
if (!objectsIsEquals((PdfNumber) outDirectObj, (PdfNumber) cmpDirectObj)) {
return false;
}
} else if (cmpDirectObj.isString()) {
if (!objectsIsEquals((PdfString) outDirectObj, (PdfString) cmpDirectObj)) {
return false;
}
} else if (cmpDirectObj.isBoolean()) {
if (!objectsIsEquals((PdfBoolean) outDirectObj, (PdfBoolean) cmpDirectObj)) {
return false;
}
} else {
throw new UnsupportedOperationException();
}
return true;
}
private boolean objectsIsEquals(PRStream outStream, PRStream cmpStream) throws IOException {
return Arrays.equals(PdfReader.getStreamBytesRaw(outStream), PdfReader.getStreamBytesRaw(cmpStream));
}
private boolean objectsIsEquals(PdfArray outArray, PdfArray cmpArray) throws IOException {
if (outArray == null || outArray.size() != cmpArray.size()) {
return false;
}
for (int i = 0; i < cmpArray.size(); i++) {
if (!objectsIsEquals(outArray.getPdfObject(i), cmpArray.getPdfObject(i))) {
return false;
}
}
return true;
}
private boolean objectsIsEquals(PdfName outName, PdfName cmpName) {
return cmpName.compareTo(outName) == 0;
}
private boolean objectsIsEquals(PdfNumber outNumber, PdfNumber cmpNumber) {
return cmpNumber.doubleValue() == outNumber.doubleValue();
}
private boolean objectsIsEquals(PdfString outString, PdfString cmpString) {
return Arrays.equals(cmpString.getBytes(), outString.getBytes());
}
private boolean objectsIsEquals(PdfBoolean outBoolean, PdfBoolean cmpBoolean) {
return Arrays.equals(cmpBoolean.getBytes(), outBoolean.getBytes());
}
public String compareXmp() {
return compareXmp(false);
}
public String compareXmp(boolean ignoreDateAndProducerProperties) {
PdfReader cmpReader = null;
PdfReader outReader = null;
try {
PdfReader cmpReader2 = new PdfReader(this.cmpPdf);
try {
PdfReader outReader2 = new PdfReader(this.outPdf);
try {
byte[] cmpBytes = cmpReader2.getMetadata();
byte[] outBytes = outReader2.getMetadata();
if (ignoreDateAndProducerProperties) {
XMPMeta xmpMeta = XMPMetaFactory.parseFromBuffer(cmpBytes);
XMPUtils.removeProperties(xmpMeta, "http://ns.adobe.com/xap/1.0/", XmpBasicProperties.CREATEDATE, true, true);
XMPUtils.removeProperties(xmpMeta, "http://ns.adobe.com/xap/1.0/", XmpBasicProperties.MODIFYDATE, true, true);
XMPUtils.removeProperties(xmpMeta, "http://ns.adobe.com/xap/1.0/", XmpBasicProperties.METADATADATE, true, true);
XMPUtils.removeProperties(xmpMeta, "http://ns.adobe.com/pdf/1.3/", PdfProperties.PRODUCER, true, true);
cmpBytes = XMPMetaFactory.serializeToBuffer(xmpMeta, new SerializeOptions(8192));
XMPMeta xmpMeta2 = XMPMetaFactory.parseFromBuffer(outBytes);
XMPUtils.removeProperties(xmpMeta2, "http://ns.adobe.com/xap/1.0/", XmpBasicProperties.CREATEDATE, true, true);
XMPUtils.removeProperties(xmpMeta2, "http://ns.adobe.com/xap/1.0/", XmpBasicProperties.MODIFYDATE, true, true);
XMPUtils.removeProperties(xmpMeta2, "http://ns.adobe.com/xap/1.0/", XmpBasicProperties.METADATADATE, true, true);
XMPUtils.removeProperties(xmpMeta2, "http://ns.adobe.com/pdf/1.3/", PdfProperties.PRODUCER, true, true);
outBytes = XMPMetaFactory.serializeToBuffer(xmpMeta2, new SerializeOptions(8192));
}
if (compareXmls(cmpBytes, outBytes)) {
if (cmpReader2 != null) {
cmpReader2.close();
}
if (outReader2 != null) {
outReader2.close();
}
return null;
}
if (cmpReader2 != null) {
cmpReader2.close();
}
if (outReader2 != null) {
outReader2.close();
}
return "The XMP packages different!";
} catch (XMPException e) {
outReader = outReader2;
cmpReader = cmpReader2;
if (cmpReader != null) {
cmpReader.close();
}
if (outReader != null) {
outReader.close();
return "XMP parsing failure!";
}
return "XMP parsing failure!";
} catch (IOException e2) {
outReader = outReader2;
cmpReader = cmpReader2;
if (cmpReader != null) {
cmpReader.close();
}
if (outReader != null) {
outReader.close();
return "XMP parsing failure!";
}
return "XMP parsing failure!";
} catch (ParserConfigurationException e3) {
outReader = outReader2;
cmpReader = cmpReader2;
if (cmpReader != null) {
cmpReader.close();
}
if (outReader != null) {
outReader.close();
return "XMP parsing failure!";
}
return "XMP parsing failure!";
} catch (SAXException e4) {
outReader = outReader2;
cmpReader = cmpReader2;
if (cmpReader != null) {
cmpReader.close();
}
if (outReader != null) {
outReader.close();
return "XMP parsing failure!";
}
return "XMP parsing failure!";
} catch (Throwable th) {
th = th;
outReader = outReader2;
cmpReader = cmpReader2;
if (cmpReader != null) {
cmpReader.close();
}
if (outReader != null) {
outReader.close();
}
throw th;
}
} catch (XMPException e5) {
cmpReader = cmpReader2;
} catch (IOException e6) {
cmpReader = cmpReader2;
} catch (ParserConfigurationException e7) {
cmpReader = cmpReader2;
} catch (SAXException e8) {
cmpReader = cmpReader2;
} catch (Throwable th2) {
th = th2;
cmpReader = cmpReader2;
}
} catch (XMPException e9) {
} catch (IOException e10) {
} catch (ParserConfigurationException e11) {
} catch (SAXException e12) {
} catch (Throwable th3) {
th = th3;
}
}
public boolean compareXmls(byte[] xml1, byte[] xml2) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setCoalescing(true);
dbf.setIgnoringElementContentWhitespace(true);
dbf.setIgnoringComments(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc1 = db.parse(new ByteArrayInputStream(xml1));
doc1.normalizeDocument();
Document doc2 = db.parse(new ByteArrayInputStream(xml2));
doc2.normalizeDocument();
return doc2.isEqualNode(doc1);
}
public String compareDocumentInfo(String outPdf, String cmpPdf) throws IOException {
System.out.println("Comparing document info...");
String message = null;
PdfReader outReader = new PdfReader(outPdf);
PdfReader cmpReader = new PdfReader(cmpPdf);
String[] cmpInfo = convertInfo(cmpReader.getInfo());
String[] outInfo = convertInfo(outReader.getInfo());
int i = 0;
while (true) {
if (i >= cmpInfo.length) {
break;
} else if (cmpInfo[i].equals(outInfo[i])) {
i++;
} else {
message = "Document info fail";
break;
}
}
outReader.close();
cmpReader.close();
return message;
}
private boolean linksAreSame(PdfAnnotation.PdfImportedLink cmpLink, PdfAnnotation.PdfImportedLink outLink) {
if (cmpLink.getDestinationPage() == outLink.getDestinationPage() && cmpLink.getRect().toString().equals(outLink.getRect().toString())) {
Map<PdfName, PdfObject> cmpParams = cmpLink.getParameters();
Map<PdfName, PdfObject> outParams = outLink.getParameters();
if (cmpParams.size() == outParams.size()) {
for (Map.Entry<PdfName, PdfObject> cmpEntry : cmpParams.entrySet()) {
PdfObject cmpObj = cmpEntry.getValue();
if (outParams.containsKey(cmpEntry.getKey())) {
PdfObject outObj = outParams.get(cmpEntry.getKey());
if (cmpObj.type() == outObj.type()) {
switch (cmpObj.type()) {
case 1:
case 2:
case 3:
case 4:
case 8:
if (cmpObj.toString().equals(outObj.toString())) {
break;
} else {
return false;
}
}
} else {
return false;
}
} else {
return false;
}
}
return true;
}
return false;
}
return false;
}
public String compareLinks(String outPdf, String cmpPdf) throws IOException {
System.out.println("Comparing link annotations...");
String message = null;
PdfReader outReader = new PdfReader(outPdf);
PdfReader cmpReader = new PdfReader(cmpPdf);
int i = 0;
while (true) {
if (i >= outReader.getNumberOfPages() || i >= cmpReader.getNumberOfPages()) {
break;
}
List<PdfAnnotation.PdfImportedLink> outLinks = outReader.getLinks(i + 1);
List<PdfAnnotation.PdfImportedLink> cmpLinks = cmpReader.getLinks(i + 1);
if (cmpLinks.size() != outLinks.size()) {
message = String.format("Different number of links on page %d.", Integer.valueOf(i + 1));
break;
}
int j = 0;
while (true) {
if (j >= cmpLinks.size()) {
break;
} else if (linksAreSame(cmpLinks.get(j), outLinks.get(j))) {
j++;
} else {
message = String.format("Different links on page %d.\n%s\n%s", Integer.valueOf(i + 1), cmpLinks.get(j).toString(), outLinks.get(j).toString());
break;
}
}
i++;
}
outReader.close();
cmpReader.close();
return message;
}
public String compareTagStructures(String outPdf, String cmpPdf) throws IOException, ParserConfigurationException, SAXException {
System.out.println("Comparing tag structures...");
String outXml = outPdf.replace(".pdf", ".xml");
String cmpXml = outPdf.replace(".pdf", ".cmp.xml");
String error = null;
PdfReader reader = new PdfReader(outPdf);
FileOutputStream xmlOut1 = new FileOutputStream(outXml);
new CmpTaggedPdfReaderTool().convertToXml(reader, xmlOut1);
reader.close();
PdfReader reader2 = new PdfReader(cmpPdf);
FileOutputStream xmlOut2 = new FileOutputStream(cmpXml);
new CmpTaggedPdfReaderTool().convertToXml(reader2, xmlOut2);
reader2.close();
if (!compareXmls(outXml, cmpXml)) {
error = "The tag structures are different.";
}
xmlOut1.close();
xmlOut2.close();
return error;
}
private String[] convertInfo(HashMap<String, String> info) {
String[] convertedInfo = {PdfObject.NOTHING, PdfObject.NOTHING, PdfObject.NOTHING, PdfObject.NOTHING};
for (Map.Entry<String, String> entry : info.entrySet()) {
if ("title".equalsIgnoreCase(entry.getKey())) {
convertedInfo[0] = entry.getValue();
} else if (Meta.AUTHOR.equalsIgnoreCase(entry.getKey())) {
convertedInfo[1] = entry.getValue();
} else if ("subject".equalsIgnoreCase(entry.getKey())) {
convertedInfo[2] = entry.getValue();
} else if (Meta.KEYWORDS.equalsIgnoreCase(entry.getKey())) {
convertedInfo[3] = entry.getValue();
}
}
return convertedInfo;
}
public boolean compareXmls(String xml1, String xml2) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setCoalescing(true);
dbf.setIgnoringElementContentWhitespace(true);
dbf.setIgnoringComments(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc1 = db.parse(new File(xml1));
doc1.normalizeDocument();
Document doc2 = db.parse(new File(xml2));
doc2.normalizeDocument();
return doc2.isEqualNode(doc1);
}
private void init(String outPdf, String cmpPdf) {
this.outPdf = outPdf;
this.cmpPdf = cmpPdf;
this.outPdfName = new File(outPdf).getName();
this.cmpPdfName = new File(cmpPdf).getName();
this.outImage = this.outPdfName + "-%03d.png";
if (!this.cmpPdfName.startsWith("cmp_")) {
this.cmpImage = "cmp_" + this.cmpPdfName + "-%03d.png";
} else {
this.cmpImage = this.cmpPdfName + "-%03d.png";
}
}
private boolean compareStreams(InputStream is1, InputStream is2) throws IOException {
int len1;
byte[] buffer1 = new byte[65536];
byte[] buffer2 = new byte[65536];
do {
len1 = is1.read(buffer1);
int len2 = is2.read(buffer2);
if (len1 != len2 || !Arrays.equals(buffer1, buffer2)) {
return false;
}
} while (len1 != -1);
return true;
}
public class PngFileFilter implements FileFilter {
PngFileFilter() {
}
@Override
public boolean accept(File pathname) {
String ap = pathname.getAbsolutePath();
boolean b1 = ap.endsWith(".png");
boolean b2 = ap.contains("cmp_");
return b1 && !b2 && ap.contains(CompareTool.this.outPdfName);
}
}
public class CmpPngFileFilter implements FileFilter {
CmpPngFileFilter() {
}
@Override
public boolean accept(File pathname) {
String ap = pathname.getAbsolutePath();
boolean b1 = ap.endsWith(".png");
boolean b2 = ap.contains("cmp_");
return b1 && b2 && ap.contains(CompareTool.this.cmpPdfName);
}
}
public class ImageNameComparator implements Comparator<File> {
ImageNameComparator() {
}
@Override
public int compare(File f1, File f2) {
String f1Name = f1.getAbsolutePath();
String f2Name = f2.getAbsolutePath();
return f1Name.compareTo(f2Name);
}
}
class CmpTaggedPdfReaderTool extends TaggedPdfReaderTool {
Map<PdfDictionary, Map<Integer, String>> parsedTags = new HashMap();
CmpTaggedPdfReaderTool() {
}
@Override
public void parseTag(String tag, PdfObject object, PdfDictionary page) throws IOException {
if (object instanceof PdfNumber) {
if (!this.parsedTags.containsKey(page)) {
CmpMarkedContentRenderFilter listener = new CmpMarkedContentRenderFilter();
PdfContentStreamProcessor processor = new PdfContentStreamProcessor(listener);
processor.processContent(PdfReader.getPageContent(page), page.getAsDict(PdfName.RESOURCES));
this.parsedTags.put(page, listener.getParsedTagContent());
}
String tagContent = PdfObject.NOTHING;
if (this.parsedTags.get(page).containsKey(Integer.valueOf(((PdfNumber) object).intValue()))) {
String tagContent2 = this.parsedTags.get(page).get(Integer.valueOf(((PdfNumber) object).intValue()));
tagContent = tagContent2;
}
this.out.print(XMLUtil.escapeXML(tagContent, true));
return;
}
super.parseTag(tag, object, page);
}
@Override
public void inspectChildDictionary(PdfDictionary k) throws IOException {
inspectChildDictionary(k, true);
}
}
class CmpMarkedContentRenderFilter implements RenderListener {
Map<Integer, TextExtractionStrategy> tagsByMcid = new HashMap();
CmpMarkedContentRenderFilter() {
}
public Map<Integer, String> getParsedTagContent() {
Map<Integer, String> content = new HashMap<>();
for (Integer num : this.tagsByMcid.keySet()) {
int id = num.intValue();
content.put(Integer.valueOf(id), this.tagsByMcid.get(Integer.valueOf(id)).getResultantText());
}
return content;
}
@Override
public void beginTextBlock() {
for (Integer num : this.tagsByMcid.keySet()) {
int id = num.intValue();
this.tagsByMcid.get(Integer.valueOf(id)).beginTextBlock();
}
}
@Override
public void renderText(TextRenderInfo renderInfo) {
Integer mcid = renderInfo.getMcid();
if (mcid != null && this.tagsByMcid.containsKey(mcid)) {
this.tagsByMcid.get(mcid).renderText(renderInfo);
} else if (mcid != null) {
this.tagsByMcid.put(mcid, new SimpleTextExtractionStrategy());
this.tagsByMcid.get(mcid).renderText(renderInfo);
}
}
@Override
public void endTextBlock() {
for (Integer num : this.tagsByMcid.keySet()) {
int id = num.intValue();
this.tagsByMcid.get(Integer.valueOf(id)).endTextBlock();
}
}
@Override
public void renderImage(ImageRenderInfo renderInfo) {
}
}
}