Apache FOP 2.0の新機能(AES256bit暗号、OpenTypeなど)   Leave a comment

1.Apache FOP2.0の新機能
2012/10/20 FOP1.1がリリースされて、約2年6ヶ月後の2015/06/03日に、2.0がリリースされました。
OpenTypeフォントの対応は、要望が多かったと思います。OpenTypeのみのフォントの場合、重宝しそうです。
個人的には、前々から希望していた、AES256bitの暗号化対応が、されていて、とても良かったです。これで、セキュリティがより高まったと思います。
その他の機能の詳細は、右記サイトで確認できます。 https://xmlgraphics.apache.org/fop/2.0/releaseNotes_2.0.html
JDKでAES256bitを使用する場合は、「Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy」が必要です。
下記のORACLEのURLからダウンロードできます。

JDK 7用JCE http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JDK 8用JCE http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

図 1. EncryptPDF.javaでは、46行目で高強度のAES 256bitを使用するようにしています。「Apache™ FOP: PDF encryption.」にて、レンダラのオプションで設定できる項目が記載されています。「fop.xconf」の設定ファイル及び、プログラム内部でパスワード等の設定ができます。文書を開くパスワードで、PDFを開いた場合と、権限パスワードで、PDFを開いた場合で、PDFの文書プロパティの「PDFの文書に関する制限の概要」に違いがあります。巷には、PDFのセキュリティを解除するソフトや、オンラインのサービスが展開されていますので、PDFのパスワードの管理はしっかりしたいところです。パスワードの長さは、8桁では数時間で解析できる環境があるので、注意が必要です。

2.フォントファミリ名設定の確認方法
フォントファミリ名を指定してあるけで、思ったとおりにフォントが出力されない場合は、初回実行時に、下記場所に、フォントキャッシュが作成されるので、%UserProfile%\.fop\fop-fonts.cache
fop-fonts.cacheをテキストエディタで開き、フォントファイル名で検索する。その後、その付近にあるフォント名を確認する。
フォントキャッシュは、削除すると自動で再作成されます。フォントのインストールした場合は、削除して再作成する必要があります。

(SyntaxHighlighterを使用して、プログラムを掲載しています。ダブルクリックで全選択されます。注意点として、「さらに記事を読み込む」のリンクで、この記事を読み込んだ場合に、SyntaxHighlighterによる表示が不正になる場合がありますので、恐れ入りますが、タイトルをクリックして再表示して下さい。)

図 1. EncryptPDF.java

package com.wordpress.okulejp.encryptpdf;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopConfParser;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.FopFactoryBuilder;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.pdf.PDFEncryptionParams;

public class EncryptPDF {
	public static void main(String[] args) throws TransformerException, TransformerConfigurationException, FileNotFoundException, IOException {
		OutputStream out = null;
		try {
			FopConfParser fopConfParser = new FopConfParser(new File("fop.xconf"));
			FopFactoryBuilder fopFactoryBuilder = fopConfParser.getFopFactoryBuilder();
			FopFactory fopFactory = fopFactoryBuilder.build();
			FOUserAgent foUserAgent = fopFactory.newFOUserAgent();			
			
			out = new FileOutputStream("blog/encryptPDF.pdf");
			out = new BufferedOutputStream(out);
			
			//セキュリティ設定
			PDFEncryptionParams params = new PDFEncryptionParams(); 
			params.setOwnerPassword("owner");
			params.setUserPassword("user");
			params.setAllowCopyContent(false); 
			params.setAllowEditContent(false);
			params.setAllowEditAnnotations(false);
			//暗号鍵の鍵長の指定
			params.setEncryptionLengthInBits(256);
			foUserAgent.getRendererOptions().put("encryption-params", params);
			
			Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);
			String fo = "blog/encryptPDF.fo";
			
			Result result = new SAXResult(fop.getDefaultHandler());
			Source src = new StreamSource(new File(fo));

			TransformerFactory factory = TransformerFactory.newInstance();
			Transformer transformer = factory.newTransformer();
			//PDF出力
			transformer.transform(src, result);
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			out.close();
		}
	}
}

図 2. encryptPDF.fo

<?xml version="1.0" encoding="UTF-8" ?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xml:lang="ja">
  <fo:layout-master-set>
    <fo:simple-page-master page-width="210mm" page-height="297mm" margin-top="0mm" margin-left="0mm" margin-right="0mm" margin-bottom="0mm" master-name="PageMaster">
      <fo:region-body margin-top="0mm" margin-left="0mm" margin-right="0mm" margin-bottom="0mm"/>
      <fo:region-before extent="0mm" />
      <fo:region-after extent="0mm" />
      <fo:region-start extent="0mm" />
      <fo:region-end extent="0mm" />
    </fo:simple-page-master>
  </fo:layout-master-set>
  <fo:page-sequence master-reference="PageMaster">
    <fo:flow flow-name="xsl-region-body">
      <fo:block>
        <fo:instream-foreign-object content-width="210mm" content-height="297mm">
          <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"
               width="210mm" height="297mm" font-size="20" stroke-width="0.1mm">
            <text x="4.9mm" y="10.5mm" fill="black">AES256bit暗号化PDF</text>
          </svg>
        </fo:instream-foreign-object>
      </fo:block>
    </fo:flow>
  </fo:page-sequence>
</fo:root>

図 3. 暗号化したPDF(クリックするとPDFを表示します。権限パスワードは、「owner」です。文書を開くパスワードは、「user」です。)
(このサンプルでは、encryptPDF.foの18行目に、font-family=”aoyagireisyo2″と追記して、OpenTypeフォントの「青柳隷書しも」を使用しております。)

2.最後に
このブログ記事が、実際のシステム開発に役立った方は、ぜひいいねボタンを押してください。またコメントもよろしくお願いいたします。(コメントするのに電子メールアドレス、名前、ウェブサイトは必須ではありません。入力なしで匿名でコメント可能です。)

©中條勝徳 and okulejp.com, 2012.

広告

okule による FOP, SVG, XML への投稿 (FOP, SVG, XML)

DB2 Express-C 10.5 FP1(10.5.1)がリリースされました。   Leave a comment

DB2 Express-C 10.5 FP1(10.5.1)がリリースされました。

DB2 Express-C 10.5がリリースされた当初、Text Searchの機能が利用できなかったので、あきらめていましたが、今回のリリースで、Text Searchの機能を利用できるようになったので良かったです。Text Searchがインストールできない件を日本語のサイトで検索しても、検索できなかったことに対して残念に思っていました。全文検索機能のText Searchは、非常に便利なのにもかかわらず、注目されていないようで、すごくがっかりです。XMLのデータに対しても、全文検索機能を利用できます。

下記フォーラムは、Text Searchがインストールできない件での質疑応答があります。(英語サイトです。)
DB2 Express-C 10.5: Text Search component is not installed

参照
DB2 for LUW V10.5 FP1 公開のお知らせ(DM-13-024)

okule による DB2 への投稿 (DB2)

Apache FOP、Barcode4j および ZXing を使用して、QRコード付きPDFファイルを生成する方法(日本語可能)   Leave a comment

1.説明
Apache FOP、Barcode4j および ZXing で、QRコードをPDFに出力する方法を説明します。
Barcode4jで、QRコードを生成する場合には、CVSサーバから、ソースファイルをダウンロードしてコンパイルする必要があります。注意事項として、ZXing で日本語を出力するために、Barcode4jの ECIUtil.java を修正する必要があります。修正箇所は下記に示してあります。QRコードに設定できるオプションは、Barcode4j QR Codeに説明があります。
Apache FOP と Barcode4j の連携は、バーコード付きPDFの作成のブログ記事を参考にして下さい。

CVSの設定 Barcode4J CVS
Host: barcode4j.cvs.sourceforge.net
Repository path: /cvsroot/barcode4j
User: anonymous
Password: パスワードはありません。
CVSサーバからダウンロードした、zxing-core-1.7.jarをクラスパスに追加して使用してください。

※最新バージョン2.1のZXingのライブラリィを使用する場合
Encoder クラスにおいてメソッドの引数と返却値が変わったため、Barcode4jのjavaプログラムの修正が必要です。
com.google.zxing.qrcode.encoder.Encoder
バージョン 1.7
    void encode(String, ErrorCorrectionLevel, Hashtable, QRCode)
バージョン 2.1
    QRCode encode(String, ErrorCorrectionLevel, Map)

※Barcode4jのjavaプログラムの修正クラス
org.krysalis.barcode4j.impl.qr.QRCodeBean
    calcDimensions()
org.krysalis.barcode4j.impl.qr.QRLogicImpl
    generateBarcodeLogic()
修正内容は、ソースをみればすごく簡単です。
 
 
2.出力結果
液晶ディスプレイ自体の解像度が、紙の印刷物に比較して低いため、PDF表示を150%で表示して下さい。スマートフォンにインストールされている、バーコードリーダで読み取ることが確認できると思います。
図 1. Apache FOPで出力したPDF(クリックするPDFが表示されます。)

図 2. qr_code.fo
32行目で、ZXingで使用するエンコード名「shift_jis」を明示的に指定しています。また33行目で、誤り訂正能力を「H」に指定しています。デフォルトは、「L」です。

<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="ja">
  <fo:layout-master-set>
    <fo:simple-page-master page-width="210mm" page-height="297mm" margin-top="0mm" margin-left="0mm"
      margin-right="0mm" margin-bottom="0mm" master-name="PageMaster">
      <fo:region-body margin-top="15mm" margin-left="15mm" margin-right="15mm" margin-bottom="15mm" />
      <fo:region-before extent="15mm" />
      <fo:region-after extent="15mm" />
      <fo:region-start extent="15mm" />
      <fo:region-end extent="15mm" />
    </fo:simple-page-master>
  </fo:layout-master-set>
  <fo:page-sequence master-reference="PageMaster">
    <fo:flow flow-name="xsl-region-body">
      <fo:block font-size="xx-large" font-family="MS 明朝">初めてのQRコード</fo:block>
        <fo:block-container absolute-position="absolute" top="15mm" left="0mm" width="125mm" height="117.3mm">
        <fo:block font-family="MS 明朝">QRコード内容は、「http://okulejp.com」です。</fo:block>
        <fo:block>
          <fo:instream-foreign-object>
            <barcode xmlns="http://barcode4j.krysalis.org/ns" message="http://okulejp.com">
              <qr/>
            </barcode>
        </fo:instream-foreign-object>
        </fo:block>
        </fo:block-container>
      <fo:block-container absolute-position="absolute" top="35mm" left="0mm" width="125mm" height="117.3mm">
        <fo:block font-family="MS 明朝">QRコード内容は、「日本語テスト」です。</fo:block>
        <fo:block>
          <fo:instream-foreign-object>
            <barcode xmlns="http://barcode4j.krysalis.org/ns" message="日本語テスト">
              <qr>
                <encoding>shift_jis</encoding>
                <ec-level>H</ec-level>
              </qr>
            </barcode>
        </fo:instream-foreign-object>
        </fo:block>
      </fo:block-container>
      <fo:block-container absolute-position="absolute" top="270mm" left="0mm" width="125mm" height="117.3mm">
        <fo:block font-size="small" font-family="MS 明朝">*QRコード® は、株式会社デンソーウェーブの登録商標です。</fo:block>
      </fo:block-container>
    </fo:flow>
  </fo:page-sequence>
</fo:root>

図 3. ECIUtil.javaの修正例。
53行目で、ZXingで使用するエンコード名「shift_jis」を使用できるように追加します。

/*
 * Copyright 2012 Jeremias Maerki, Switzerland
 *
 * Licensed 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: ECIUtil.java,v 1.1 2012/01/27 14:36:35 jmaerki Exp $ */

package org.krysalis.barcode4j.tools;

import java.util.Map;

/**
 * Utilities around ECI (extended channel interpretation).
 *
 * @version $Id: ECIUtil.java,v 1.1 2012/01/27 14:36:35 jmaerki Exp $
 */
public class ECIUtil {

    /** ECI code for 8-bit binary data */
    public static final int ECI_BINARY = 899;

    private static final Map encodingToECI = new java.util.HashMap();

    static {
        mapEncoding("Cp437", 2);
        mapEncoding("ISO-8859-1", 3);
        mapEncoding("ISO-8859-2", 4);
        mapEncoding("ISO-8859-3", 5);
        mapEncoding("ISO-8859-4", 6);
        mapEncoding("ISO-8859-5", 7);
        mapEncoding("ISO-8859-6", 8);
        mapEncoding("ISO-8859-7", 9);
        mapEncoding("ISO-8859-8", 10);
        mapEncoding("ISO-8859-9", 11);
        mapEncoding("ISO-8859-10", 12);
        mapEncoding("ISO-8859-11", 13);
        mapEncoding("ISO-8859-13", 15);
        mapEncoding("ISO-8859-14", 16);
        mapEncoding("ISO-8859-15", 17);
        mapEncoding("ISO-8859-16", 18);
        mapEncoding("SJIS", 20);
        mapEncoding("shift_jis", 30);
        mapEncoding("Cp1250", 21);
        mapEncoding("Cp1251", 22);
        mapEncoding("Cp1252", 23);
        mapEncoding("Cp1256", 24);
        mapEncoding("UnicodeBigUnmarked", 25);
        mapEncoding("UTF-8", 26);
        mapEncoding("US-ASCII", 27);
        mapEncoding("Big5", 28);
        mapEncoding("GB18030", 29);
    }

    private static void mapEncoding(String encoding, int eci) {
        encodingToECI.put(encoding, new Integer(eci));
    }

    /**
     * Returns the ECI code for a given encoding.
     * @param encoding the encoding
     * @return the corresponding ECI code
     */
    public static int getECIForEncoding(String encoding) {
        Integer code = (Integer)encodingToECI.get(encoding);
        if (code != null) {
            return code.intValue();
        } else {
            return -1; //undefined
        }
    }

}

3.システムの応用例
QRコードには、全角文字が、最大1,817文字を保存できます。スキャナーで、CSV形式のデータを格納したQRコードの内容を読み込んで、入力画面に自動的に読み込むことができます。そうすることで、入力する際の間違えをなくしたり、入力する手間を省いたりすることができます。また暗号データを格納したQRコードを使用して、会員カードによるログイン認証にも応用できます。もちろん商品などの在庫管理にも応用できます。

4.参考及び注意事項
QRコードドットコム-QRコードの特長のご紹介。
攻略! ツール・ド・プログラミング34回 ZXingとは
QRコード® は、株式会社デンソーウェーブの登録商標です。

©中條勝徳 and okulejp.com, 2012.

okule による Barcode4J, FOP, XML への投稿 (Barcode4J, FOP, XML)

タグ: , , ,