/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* $Id$ */ package org.apache.fop.pdf; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Random; /** * A class to generate the File Identifier of a PDF document (the ID entry of the file * trailer dictionary). */ abstract class FileIDGenerator { abstract byte[] getOriginalFileID(); abstract byte[] getUpdatedFileID(); private static final class RandomFileIDGenerator extends FileIDGenerator { private byte[] fileID; private RandomFileIDGenerator() { Random random = new Random(); fileID = new byte[16]; random.nextBytes(fileID); } @Override byte[] getOriginalFileID() { return fileID; } @Override byte[] getUpdatedFileID() { return fileID; } } private static final class DigestFileIDGenerator extends FileIDGenerator { private byte[] fileID; private final PDFDocument document; private final MessageDigest digest; DigestFileIDGenerator(PDFDocument document) throws NoSuchAlgorithmException { this.document = document; this.digest = MessageDigest.getInstance("MD5"); } @Override byte[] getOriginalFileID() { if (fileID == null) { generateFileID(); } return fileID; } @Override byte[] getUpdatedFileID() { return getOriginalFileID(); } private void generateFileID() { DateFormat df = new SimpleDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS"); digest.update(PDFDocument.encode(df.format(new Date()))); // Ignoring the filename here for simplicity even though it's recommended // by the PDF spec digest.update(PDFDocument.encode(String.valueOf(document.getCurrentFileSize()))); digest.update(document.getInfo().toPDF()); fileID = digest.digest(); } } /** * Use this method when the file ID is needed before the document is finalized. The * digest method recommended by the PDF Reference is based, among other things, on the * file size. * * @return an instance that generates a random sequence of bytes for the File * Identifier */ static FileIDGenerator getRandomFileIDGenerator() { return new RandomFileIDGenerator(); } /** * Returns an instance that generates a file ID using the digest method recommended by * the PDF Reference. To properly follow the Reference, the size of the document must * no longer change after this method is called. * * @param document the document whose File Identifier must be generated * @return the generator * @throws NoSuchAlgorithmException if the MD5 Digest algorithm is not available */ static FileIDGenerator getDigestFileIDGenerator(PDFDocument document) throws NoSuchAlgorithmException { return new DigestFileIDGenerator(document); } }