添付文書をファイルに保管する (Java Agent)

メールなどで送られてきた添付文書を取り出して、ファイルに保管する、というような処理がよくあります。

こうした例を Java でどうやって書くかについて、ドミノのヘルプには以下のような例が載っています。(原文はこちら)
が、これをサーバーで稼動させてみると、確かに /extracts/ ディレクトリに 添付文書と同じ名前のファイルができはしますが、いろいろと不具合が出てきてしまいます。(ちなみに「添付文書の削除」もそもそもうまくいかないことがあります...これに関しては今回は no-touch ということで)

import lotus.domino.*;
import java.util.Vector;
import java.util.Enumeration;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
// (Your code goes here)
Database db = agentContext.getCurrentDatabase();
DocumentCollection dc = db.getAllDocuments();
Document doc = dc.getFirstDocument();
boolean saveFlag = false;
while (doc != null) {
RichTextItem body = (RichTextItem)doc.getFirstItem("Body");
System.out.println(doc.getItemValueString("Subject"));
Vector v = body.getEmbeddedObjects();
Enumeration e = v.elements();
while (e.hasMoreElements()) {
EmbeddedObject eo = (EmbeddedObject)e.nextElement();
if (eo.getType() == EmbeddedObject.EMBED_ATTACHMENT) {
eo.extractFile("/extracts/" + eo.getSource());
eo.remove();
saveFlag = true;
}
}
if (saveFlag) {
doc.save(true, true);

その不具合の中で一番大きいのが、ファイルの中身と属性が不一致になってしまう、ということです。
この extractFile メソッドはファイルの中身はバイナリーで書き出すらしく、書き出された iSeries上のファイルの内容は ASCII のままなのです。
一方、iSeries はどんなファイルの書き出し時にも内容に応じてコードページの値を自動的にラベルする、という機能があり、これによって1台のマシンで Multi-Language 環境を実現しているのですが、ここではファイルの内容は知らされていない(= ドミノがやってしまうので自分でコード変換を行える立場にない)が、テキストファイルであるということは知らされている(= テキストファイルとして書き出すよという報告をドミノから受けている)という状態になってしまい、属性としてドミノが稼動している iSeries ネイティブの文字コードである 5035 という値がついてしまい、中身と不一致になってしまう、ということです。

中身が不一致だとどうなるか、と言えば、結局はもともと PC で作られた文書ですから、943 という値がついていないと読み出すときに正しく読み出せず、いろんなところでエラーになります。

対処方法としては、Java のクラスを使用して、Java の機能で Unicode への変換を含めて全部やってもらう、というやり方があります。このようにすれば、PCサーバー上のドミノでもノーツクライアントでも、UNIX版のドミノでも同じように動くはずです。

上の例を、そこだけ変更して全文載せたのが下のものです。変更された部分は太字の部分で、extractFile の置き換えになっています。(若干デバッグ用の println がありますが)

こちらを使って作成されたファイルは 943 という値のCCSIDがつけられます。

import lotus.domino.*;
import java.util.Vector;
import java.util.Enumeration;
import java.io.*;

public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
// (Your code goes here)
Database db = agentContext.getCurrentDatabase();
DocumentCollection dc = db.getAllDocuments();
Document doc = dc.getFirstDocument();
boolean saveFlag = false;
while (doc != null) {
RichTextItem body = (RichTextItem)doc.getFirstItem("Body");
System.out.println(doc.getItemValueString("Subject"));
Vector v = body.getEmbeddedObjects();
Enumeration e = v.elements();
while (e.hasMoreElements()) {
System.out.println("Going to get eo");
EmbeddedObject eo = (EmbeddedObject)e.nextElement();
if (eo.getType() == EmbeddedObject.EMBED_ATTACHMENT) {
System.out.println("eo is EMBED_ATTACHMENT");

if (eo != null) try{
BufferedReader reader = new BufferedReader(eo.getReader());
String filename = "/extracts/" + eo.getSource();
System.out.println(filename);
PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(filename)));
String line;
while((line = reader.readLine()) != null) {
writer.println(line);
}
reader.close();
writer.close();
}
catch (IOException ie) {
ie.printStackTrace();
}
eo.remove();
saveFlag = true;
}
}
if (saveFlag) {
doc.save(true, true);
saveFlag = false;
}
doc = dc.getNextDocument();
}
} catch(NotesException e) {
System.out.println(e.id + " " + e.text);
e.printStackTrace();
}
}
}

「オブジェクト」を見ると /Extracts/ の下に添付されて送られてきたファイルが保管されているのがわかるかと思います。

また、この「属性の表示」画面で「コード化文字セットID」が 943 になっているのが確認できると思います。

内容もちゃんと変換されています。OS/400 のEDTF コマンドでも正しく変換された内容が表示されます。

こんな風にメソッドとしてまとめた方が読みやすいかもしれません。

import lotus.domino.*;
import java.util.Vector;
import java.util.Enumeration;
import java.io.*;

public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
// (Your code goes here)
Database db = agentContext.getCurrentDatabase();
DocumentCollection dc = db.getAllDocuments();
Document doc = dc.getFirstDocument();
boolean saveFlag = false;
while (doc != null) {
RichTextItem body = (RichTextItem)doc.getFirstItem("Body");
System.out.println(doc.getItemValueString("Subject"));
Vector v = body.getEmbeddedObjects();
Enumeration e = v.elements();
while (e.hasMoreElements()) {
System.out.println("Going to get eo");
EmbeddedObject eo = (EmbeddedObject)e.nextElement();
if (eo.getType() == EmbeddedObject.EMBED_ATTACHMENT) {
System.out.println("eo is EMBED_ATTACHMENT");
String filename = "/extracts/" + eo.getSource();
extract(eo, filename);

eo.remove();
saveFlag = true;
}
}
if (saveFlag) {
doc.save(true, true);
saveFlag = false;
}
doc = dc.getNextDocument();
}
} catch(NotesException e) {
System.out.println(e.id + " " + e.text);
e.printStackTrace();
}
}

private void extract(EmbeddedObject eo, String filename) {
if (eo != null) try{
BufferedReader reader = new BufferedReader(eo.getReader());
System.out.println(filename);
PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(filename)));
String line;
while((line = reader.readLine()) != null) {
writer.println(line);
}
reader.close();
writer.close();
} catch(NotesException e) {
System.out.println(e.id + " " + e.text);
e.printStackTrace();
}
catch(IOException ie) {
ie.printStackTrace();
}
}

}

もともとのドミノのヘルプに載っている例(この記事の一番上の例)からしてそうなのですが、添付文書が暗号化されている場合は処理されませんのでご注意ください。

[Top Pageに戻る]

Ads by TOK2