CLOVER🍀

That was when it all began.

JasperReportsで、PDFのプロパティをいろいろ設定する

1年半くらい前にJasperReportsを触って、それっきりだったのですが、最近また触る機会があって、PDFの設定に関する内容を調べたのでメモっておきます。

何を調べたかって、PDFのパスワードを設定するとか作成者を設定するとか、バージョンを指定するとか、その辺りです。

いつの間にか、JasperReportsもバージョン5を越えてますねー。

見るべきクラスは、
JRPDFExporter
http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/export/JRPdfExporter.html

JRPdfExporterParameter
http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/export/JRPdfExporterParameter.html
ですね。

これ以降のコードでは、変数exporterは

JRExporter exporter = new JRPdfExporter();

を指すものとします。

ここで、

exporter.setParameter(..., ...);

という感じで設定していきます。

PDFのバージョンを指定する。

JRPdfExporterParameter.PDF_VERSIONとJRPdfExporterParameter.PDF_VERSION_X_Xで指定します。

exporter.setParameter(JRPdfExporterParameter.PDF_VERSION, JRPdfExporterParameter.PDF_VERSION_1_5);

何も指定しないと、1.4(Acrobat 5.x)になりましたよ。

PDFのパスワードを設定する

PDFにはユーザーパスワードとオーナーパスワードがありますが、両方とも設定できます。

まずは、ユーザーパスワード。

exporter.setParameter(JRPdfExporterParameter.IS_ENCRYPTED, true); // パスワードを設定する場合は、必須
exporter.setParameter(JRPdfExporterParameter.USER_PASSWORD, "userpassword");

JRPdfExporterParameter.USER_PASSWORDのペアになるのが、PDFを開く時に聞かれるパスワードです。

続いて、オーナーパスワード。

exporter.setParameter(JRPdfExporterParameter.IS_ENCRYPTED, true); 
exporter.setParameter(JRPdfExporterParameter.OWNER_PASSWORD, "ownerpassword");

ちなみに、一緒に入っている

exporter.setParameter(JRPdfExporterParameter.IS_ENCRYPTED, true); 

ですが、パスワードを設定する際には必須になります。

タイトル、作成者、サブジェクト、キーワード、作成したアプリケーションを指定する

一気にまとめて書きます。

exporter.setParameter(JRPdfExporterParameter.METADATA_AUTHOR, "作成者");
exporter.setParameter(JRPdfExporterParameter.METADATA_CREATOR, "JasperReportsで作りました");
exporter.setParameter(JRPdfExporterParameter.METADATA_KEYWORDS, "キーワード");
exporter.setParameter(JRPdfExporterParameter.METADATA_TITLE, "タイトル");
exporter.setParameter(JRPdfExporterParameter.METADATA_SUBJECT, "主題");

暗号化キーを128ビットにする

exporter.setParameter(JRPdfExporterParameter.IS_ENCRYPTED, true); 
exporter.setParameter(JRPdfExporterParameter.IS_128_BIT_KEY, true);

パーミッションを設定する

これも

exporter.setParameter(JRPdfExporterParameter.IS_ENCRYPTED, true); 

で暗号化した時に一緒に使うと思います。これを設定した時には、ほとんどのパーミッションは落とされてしまうようなので、必要なものについては設定していきます。

パラメータは、JRPdfExporterParameter.PERMISSIONSを使用します。

exporter.setParameter(JRPdfExporterParameter.PERMISSIONS, XXXX);

「XXX」の部分には、iTextのPdfWriterのstatic finalなフィールドを、ビットフラグを使って指定します。
PdfWriter
http://ymasory.github.io/iText-4.2.0/com/lowagie/text/pdf/PdfWriter.html
*JasperReportsが依存しているiTextは、5系よりも前みたいなので…

例えば、こんな感じ。

exporter.setParameter(JRPdfExporterParameter.PERMISSIONS,
                              PdfWriter.ALLOW_COPY | PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_MODIFY_CONTENTS);

まあ、許可したパーミッションに共連れて有効になるものもあるっぽいですけど…。

ここまで出てきたPDFのセキュリティ関連の設定については、ここが参考になりました。
http://www.antenna.co.jp/pdf/reference/SecurityEncryption.html

他のパラメータは、やっぱりここを眺めましょう。
JRPdfExporterParameter
http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/export/JRPdfExporterParameter.html

では、このあたりをまとめて使ったサンプルを。
pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>littlewings</groupId>
  <artifactId>pdf-author-password</artifactId>
  <packaging>jar</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>pdf-author-password</name>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>net.sf.jasperreports</groupId>
      <artifactId>jasperreports</artifactId>
      <version>5.0.4</version>
    </dependency>
    <dependency>
      <groupId>com.lowagie</groupId>
      <artifactId>itext</artifactId>
      <version>4.2.0</version>
    </dependency>
  </dependencies>

</project>

src/main/java/PdfGenerator.java

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.data.JRMapCollectionDataSource;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRPdfExporterParameter;

import com.lowagie.text.pdf.PdfWriter;

public class PdfGenerator {
    public static void main(String[] args) throws Exception {
        ClassLoader classLoader = PdfGenerator.class.getClassLoader();
        
        JasperReport jasperReport
            = JasperCompileManager.compileReport(
                classLoader.getResourceAsStream("report1.jrxml"));

        JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport,
                                                         createParam(),
                                                         new JRMapCollectionDataSource(createDetails()));
        JRExporter exporter = new JRPdfExporter();

        // デフォルトはVersion 1.4(Acrobat 5.x)
        exporter.setParameter(JRPdfExporterParameter.PDF_VERSION, JRPdfExporterParameter.PDF_VERSION_1_5);

        exporter.setParameter(JRPdfExporterParameter.IS_ENCRYPTED, true); // パスワードを設定する場合は、必須
        exporter.setParameter(JRPdfExporterParameter.USER_PASSWORD, "userpassword");
        exporter.setParameter(JRPdfExporterParameter.OWNER_PASSWORD, "ownerpassword");

        exporter.setParameter(JRPdfExporterParameter.METADATA_AUTHOR, "作成者");
        exporter.setParameter(JRPdfExporterParameter.METADATA_CREATOR, "JasperReportsで作りました");
        exporter.setParameter(JRPdfExporterParameter.METADATA_KEYWORDS, "キーワード");
        exporter.setParameter(JRPdfExporterParameter.METADATA_TITLE, "タイトル");
        exporter.setParameter(JRPdfExporterParameter.METADATA_SUBJECT, "主題");

        exporter.setParameter(JRPdfExporterParameter.IS_128_BIT_KEY, true);
        exporter.setParameter(JRPdfExporterParameter.PERMISSIONS,
                              PdfWriter.ALLOW_COPY | PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_MODIFY_CONTENTS);

        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_FILE, new File("report1.pdf"));

        exporter.exportReport();
    }

    private static Map<String, Object> createParam() {
        // 省略
    }

    private static Collection<Map<String, ?>> createDetails() {
        // 省略
    }

}

テンプレートファイルは、

src/main/resources/report1.jrxml

に置いていましたが、省略。

これで、実行します。

$ mvn compile exec:java -Dexec.mainClass=PdfGenerator

そして、できあがったPDFを開いてみます。

まず、パスワードの入力を求められます。指定したパスワードは、「userpassword」なので、これを入力すると開けます。

続いて、「ファイル」→「プロパティ」を選びます。
「Description」タブを見ると

タイトルとか作成者が設定されています。PDFのバージョンは、1.5になっていますね。

それから、「Security」タブを選びます。
パーミッションで設定した内容が現れます。

それから、「Show Details」を見ると

パスワードの設定をしたことや、128ビット鍵を使ったことがわかります。