/*
 * SamplePDFTimeStampGenerator.java
 *
 * Copyright(C) 2005-2006 AMANO Corporation. All Rights Reserved.
 *
 * PDF Lib-J API - サンプルプログラム
 *
 * 指定された PDF ファイルに対して PDF タイムスタンプを埋め込むコンソールプログラムです。
 *
 * セキュリティ無しの文書の場合
 * Usage: java SamplePDFTimeStampGenerator PDFPDFFilePath LicenseFilePath Password
 *
 *    PDFFilePath       - PDF タイムスタンプを埋め込む PDF ファイルパス
 *    LicenseFilePath   - ライセンスファイルパス
 *    Password          - ライセンスパスワード
 *
 * PDF 標準セキュリティ有りの文書の場合
 * Usage: java SamplePDFTimeStampGenerator PDFFilePath UserPassword OwnerPassword LicenseFilePath Password
 *
 *    PDFFilePath       - PDF タイムスタンプを埋め込む PDF ファイルパス
 *    UserPassword      - ユーザーパスワード
 *    OwnerPassword     - オーナーパスワード
 *    LicenseFilePath   - ライセンスファイルパス
 *    Password          - ライセンスパスワード
 */

import java.io.*;
import java.util.*;
import java.security.cert.*;
import jp.co.amano.etiming.apl3161.*;

public class SamplePDFTimeStampGenerator {

	// アマノタイムスタンプ局の URL
    public static final String TIMESTAMP_SERVER = "http://tss3161.e-timing.ne.jp/astdtssvr/TSRequest";

	public static void main(String[] args) throws Exception {

		String pdfFilePath = null;
		char[] ownerPassword = null;
		char[] userPassword = null;
		String licenseFilePath = null;
		char[] password = null;

		// 引数チェック
		if (args.length == 3) {
			pdfFilePath = args[0];
			licenseFilePath = args[1];
			password = args[2].toCharArray();
		} else if (args.length == 5) {
			pdfFilePath = args[0];
			userPassword = args[1].toCharArray();
			ownerPassword = args[2].toCharArray();
			licenseFilePath = args[3];
			password = args[4].toCharArray();
		} else {
			System.out.println("usage : java SamplePDFTimeStampGenerator <PDFFilePath> <LicenseFilePath> <Password>");
			System.out.println("      : java SamplePDFTimeStampGenerator <PDFFilePath> <UserPassword> <OwnerPassword> <LicenseFilePath> <Password>");
			System.out.println();
			System.out.println("      PDFFilePath       - PDF タイムスタンプを埋め込む PDF ファイルパス");
			System.out.println("      UserPassword      - PDF のユーザーパスワード");
			System.out.println("      OwnerPassword     - PDF のオーナーパスワード");
			System.out.println("      LicenseFilePath   - ライセンスファイルパス");
			System.out.println("      Password          - パスワード");
			System.exit(1);
		}

		try {
			// タイムスタンプトークンを取得する際に使用するタイムスタンププロトコル
			// オブジェクトを生成する
			AmanoTimeStampProtocol protocol =
				new AmanoTimeStampProtocol(TIMESTAMP_SERVER, readFile(licenseFilePath), password);

			// PDF タイムスタンプ生成オブジェクトを生成する
			PDFTimeStampGenerator generator = new PDFTimeStampGenerator(protocol);

			// タイムゾーン設定
			generator.setTimeZone(DefinedTimeZone.JST);

			// タイムスタンプトークン検証オブジェクトの生成
			NoTSACertValidationTSTValidator validator = new NoTSACertValidationTSTValidator();
			generator.setTSTValidator(validator);

			// 印影なし
			generator.setImprintPasting(null);

			// 印影あり
			// 印影のある PDF タイムスタンプを生成するには次のコメントアウトを外す
			//ImprintPastingParameters params = makeImprintPastingParameters();
			//generator.setImprintPasting(params);

			// PDF ファイルのオープン
			RandomAccessFile pdfDocument = new RandomAccessFile(pdfFilePath, "r");

			// PDF タイムスタンプを生成する
			InputStream stamped = null;
			if (ownerPassword == null && userPassword == null) {
				stamped = generator.generate(pdfDocument);
			} else {
				stamped = generator.generate(pdfDocument, userPassword, ownerPassword);
			}
			pdfDocument.close();

			// PDF タイムスタンプを埋め込んだ PDF ファイルの保存
			writeFile(stamped, pdfFilePath);

			// タイムスタンプ済みデータ入力ストリームを閉じる
			stamped.close();

		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}


	/**
	 * デフォルト設定で PDFTimeStampGenerator のインスタンスを作成する
	 */
	static PDFTimeStampGenerator makeAmanoInstance(String licenseFilePath,
												   char[] password,
												   String certPath)
	throws Exception {

		// 証明書ファクトリの作成
		CertificateFactory factory = CertificateFactory.getInstance("X.509");

		// 証明書ファイルを読み込んでリストに追加する
		ArrayList certList = new ArrayList();
		X509Certificate cert = (X509Certificate)factory.generateCertificate(new FileInputStream(certPath));
		certList.add((X509Certificate)cert);

		// PDF タイムスタンプ生成オブジェクトを生成する
		return PDFTimeStampGenerator.getAmanoInstance(readFile(licenseFilePath),
													  password,
													  DefinedTimeZone.JST,
													  certList,
													  null);
	}


	/**
	 * 可視印影の情報を設定する
	 */
	static ImprintPastingParameters makeImprintPastingParameters() {
		ImprintPastingParameters params = new ImprintPastingParameters();

		// 出力ページの設定
		//   ページ数は 0 からカウントする
		params.setPage(0);

		// ページを数える方向をセットする
		//      ImprintPastingParameters.FIRST_PAGE   最初のページ
		//      ImprintPastingParameters.LAST_PAGE    最後のページ
		params.setPageOrigin(ImprintPastingParameters.FIRST_PAGE);

		// 印影の時刻表示方法の設定
		//   日付の表示形式  1 から 15 までの整数で指定
		//   時刻の表示形式  1 から 4 までの整数で指定
		TimeFaceFormat timeFormat = new TimeFaceFormat(1, 1);

		// 印影情報の設定
		// shape
		//		Imprint.CIRCULAR     丸型
		//		Imprint.RECTANGULAR  角形
		// background
		//		Imprint.OPAQUE                  不透明
		//		Imprint.TRANSPARENT             透過
		//		Imprint.TRANSLUCENT_FOREGROUND  前景半透明
		// linkableAttached
		//      true    リンカブル有り
		//      false   リンカブル無し
		Imprint imprint = new Imprint(Imprint.CIRCULAR, Imprint.OPAQUE, timeFormat, true);
		params.setImprint(imprint);

		// 表示座標の設定
		// origin
		//     APLPosition.UPPER_LEFT_ORIGIN  原点左上
		//     APLPosition.LOWER_LEFT_ORIGIN  原点左下
		// unit
		//     APLPosition.MM     ミリメートル単位
		//     APLPosition.INCH   インチ単位
		//     APLPosition.POINT  ポイント単位
		APLPosition position = new APLPosition(APLPosition.UPPER_LEFT_ORIGIN,
											   APLPosition.MM,
											   2.0,
											   2.0);
		params.setPosition(position);

		return params;
	}

	static byte[] readFile(String filePath) throws Exception {
		InputStream in = new BufferedInputStream(new FileInputStream(filePath));
		try {
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			byte[] buf = new byte[4096];
			while (true) {
				int i = in.read(buf);
				if (i <= 0) {
					break;
				}
				out.write(buf, 0, i);
			}
			return out.toByteArray();
		} finally {
			in.close();
		}
	}

	static void writeFile(InputStream in, String filePath) throws Exception {
		FileOutputStream out = new FileOutputStream(filePath + ".new.pdf");
		try {
			byte[] buf = new byte[4096];
			while (true) {
				int i = in.read(buf);
				if (i <= 0) {
					break;
				}
				out.write(buf, 0, i);
			}
		} finally {
			out.close();
		}
	}
}
