iTextを利用した、PDFのセキュリティ付与

iTexthttp://www.lowagie.com/iText/
iTextのいいところ:JavaのみでPDFの作成操作ができる。
○PDFとHTMLとRTFなどのファイルを扱うライブラリを備えていて、交互に変換できる(?)

                                                                                                                  • -

import java.io.*;
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;

public class Sample {
 public static void main(String args) {
  try {
   //PdfReaderを使用し、既存のPDF(Sample.pdf)を開く。
   PdfReader reader = new PdfReader("Sample.pdf");

   //PdfEncryptorを使用し、暗号化やパスワード設定/制御をかけ、新しいPDFを作成する(Sample2.pdf)
   PdfEncryptor.encrypt(reader,
     new FileOutputStream("Sample2.pdf"),
     null, //パスワード設定しない。する場合はbyte
     null, //パスワード設定しない。する場合はbyte[]
     0,   //印刷・コピー・編集等すべて禁止。
        //一部許可する必要がある場合、「|」で繋げる。
        //AllowAssembly   :?
        //AllowCopy    :選択→コピー可能
        //AllowDegradedPrinting :低解像度印刷許可
        //AllowFillIn    :フルスクリーン
        //AllowModifyAnnotations:注釈変更許可
        //AllowModifyContents  :コンテンツ変更許可
        //AllowPrinting   :印刷変更許可
        //AllowScreenReaders :?
        //
        //例:コピー可+低解像度印刷可能なら、
        //「PdfEncryptor.AllowCopy | PdfEncryptor.AllowDegradedPrinting」
     true);  //true:128bit暗号、false:40bit暗号
  } catch (Exception e) {
   System.out.println(e);
  }
 }
}

JNIを通じてJavaからCOMを実行する。-JCom(Java-COMブリッジ)の利用

JCom(Java-COM Bridge):http://sourceforge.net/projects/jcom

何が良いか。
JavaからCOMを使用する際、JavaとDLLの間を取り持つラッパーDLLを作成する必要が無くなる。
 C++とかヘッダがどう、とか意識しないでできる。

                                                                                                                                                          • -

//Import宣言
import jp.ne.so_net.ga2.no_ji.jcom.*;

//この二行は呪文として記述。
//IDispatchの引数は「ReleaseManager」と「HKEY_CLASSES_ROOT」に登録されているCOM/DLLの名前。
//たとえば、Excel.Sheetなど。
ReleaseManager rm = new ReleaseManager();
IDispatch dllcom = new IDispatch(rm, "Excel.Sheet");

//COM/DLL内の関数の引数を配列で設定する。
Object param = new Object{"XXXXXXXX"};

//DLL内の関数MethodNameを呼ぶ。引数はparam
Object retcode = dllcom.method( "MethodName", param );

//DLL内のプロパティ値を取得する。
retcode = dllcom.get( "PropertyName");

JNIを通じて、JavaからDLLを呼ぶ方法の概念。

・実現に必要なもの
 Javaクラス
 Javaクラスから自動で作成されたC++用ヘッダファイル(javah -jni ClassName.java)
 Javaクラスと使用したいDLLをつなぐラッパーDLL用C++ファイル
 使用したいDLL

多くのサイトが使用したいDLLを見に行くサンプルソースを書いておらず、
ラッパーDLL用C++ファイルの中のソースは単にC++の関数を呼んでいるだけ。
Java開発者=C++を知ってるではないので(その一人)、結局分からずじまいでした。
あまり参考にならないのが残念、というかこれに気づくのに三時間...

Java Mailと『最新』RFC準拠について。

当然のことですが、最新のJava Mailの方が、最新のRFCに準拠してる可能性が高いです。
某システムで、Java Mail(恐らく)1.2を使っていましたが、
先ごろ変更したUnixベースのSendMailからは蹴られました。
恐らく、HELOだったりEHLOするものの実装が不完全で、Java Mail1.3の最新(最後の?)バージョンにしたところ、うまく動きました。
各種配布ライブラリ等も「利用しているアプリに非が無い場合」、Javaが実行する範囲内でバージョンを上げてみるのもいいかもしれません。

ResultSetMetaDataとDatabaseMetaData

ResultSetMetaData
ResultSetより取得可能。
・結果セットのカラム名
・結果セットのカラムの型名
・結果セットのカラム数


Connection conn=DriverManager.getConnection("url","user","pass");
Statement stmt=conn.createStatemet();
ResultSet rs=stmt.executeQuery("SQL文");

ResultSetMetaData meta=rs.getMetaData();
int columnCount=meta.getColumnCount();

//iは1から。
for(int i=1;i<=columnCount;i++){
 System.out.println("結果セットのカラム名("+i+")"+meta.getColumnName(i));
 System.out.println("結果セットのカラム型名("+i+")"+meta.getColumnTypeName(i));
}
rs.close();
stmt.close();
conn.close();


DatabaseMetaData
Connectionより取得可能
DatabaseMetaData#getTables()
スキーマ
・テーブル名
・タイプ(Table/Viewなど)


Connection conn=DriverManager.getConnection("url","user","pass");
DatabaseMetaData meta=conn.getMetaData();

ResultSet rs=meta.getTables(null,"schema","テーブルパターン",null);
while(rs.next()){
 System.out.println("スキーマ名("+i+")"+rs.getString("TABLE_SCHEM"));
 System.out.println("テーブル名("+i+")"+rs.getString("TABLE_NAME"));
 System.out.println("テーブルタイプ名("+i+")"+rs.getString("TABLE_TYPE"));
}
rs.close();
stmt.close();
conn.close();


DatabaseMetaData#getColumns()
スキーマ
・テーブル名
カラム名
・カラムタイプ
・サイズ
・デフォルト値
・Nullが挿入できるか


Connection conn=DriverManager.getConnection("url","user","pass");
DatabaseMetaData meta=conn.getMetaData();

int i=1;
ResultSet rs=meta.getColumns(null,"schema","テーブルパターン","カラムパターン");
while(rs.next()){
 System.out.println("スキーマ名("+i+")"+rs.getString("TABLE_SCHEM"));
 System.out.println("テーブル名("+i+")"+rs.getString("TABLE_NAME"));
 System.out.println("カラム名("+i+")"+rs.getString("COLUMN_NAME"));
 System.out.println("カラム型名("+i+")"+rs.getString("TYPE_NAME"));
 System.out.println("カラムサイズ("+i+")"+rs.getString("COLUMN_SIZE"));
 System.out.println("デフォルト値("+i+")"+rs.getString("COLUMN_DEF"));
 System.out.println("Nullが可能か("+i+")"+rs.getString("IS_NULLABLE"));
 i++;
}
rs.close();
stmt.close();
conn.close();

JTextPane or JEditorPaneで行折り返しの制御を行う方法。
キモとなるのは、JTextPane#getScrollableTracksViewportWidth()のboolean値。
ソースを見ても良く分からないが、JEditorPane/JTextPaneはHTMLをサポートしている影響か、
明示的に「改行」しないと折り返してくれるらしい。
JTextAreaでやるような、
JScrollBar#setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
をやっても無理なので、JEditorPaneを継承したクラスを作りました。


package com.xiaon.editor;

import javax.swing.JTextPane;
public class CustomTextPane extends JTextPane {
  //属性として値を持ってしまう。
  private boolean scrollableTracksViewportWidth;
  
  //JEditorPane#getScrollableTracksViewportWidth()のオーバーライド
  public boolean getScrollableTracksViewportWidth(){
    return this.scrollableTracksViewportWidth;
  }
  //セッターも作りました。
  public void setScrollableTracksViewportWidth(boolean scrollableTracksViewportWidth){
    this.scrollableTracksViewportWidth=scrollableTracksViewportWidth;
  }
}

これを用いて、下みたいにやると、折り返しを制御できるように。


CustomTextPane text=new CustomTextPane();
text.setScrollableTracksViewportWidth(false);
//text.setScrollableTracksViewportWidth(true);
JScrollBar bar=new JScrollBar();
bar.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
bar.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
getContentPane().add(bar);

Java5でjavadocを実行すると、警告コメントが表示。
内容
・「javadoc: 警告 - パッケージ "foo.hoge" に複数のパッケージコメントのソースが検出されました。」
対応
javadoc用に作成しているpackageコメントが複数あるので削除する。
 ソースディレクトリ/クラスディレクトリ/jarファイルの中に、
 pakage.htmlが複数あったらアウト。
 Eclipseを使っている場合は、ビルドパスの設定から除外パターンを設定する。
 例)xjcl/pakage.html ->除外パターン「xjcl/package.html」
   xjcl/io/package.html->除外パターン「xjcl/*/package.html」
 ※除外パターンを設定したら一旦全クラスファイルの削除と生成するjarの削除を行い、
  再ビルド→再jar作成を行う。