正規表現で文字列を抜き出す

Javaで正規表現を使って文字列を抜き出すには、次のようなプログラムを用意すればいい。正規表現についての詳しい説明は省略。便利と言えば便利。ただ、ネストした構造とか場合分けが多い構造の文章に対して適用するのは結構大変ので、そういった場合は独自にParserを実装した方がいい。Interpreterパターンとか使えばバグも少なく実装できるはず。ただ、言語定義ができない人には難しいので、コンパイラ技術とか勉強することになるはず。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class App {
  private String regexp1 = "<div class=target>(.*)<div class=target2>(.*)</div></div>";
  private String regexp2 = "href=\"(.+?)\"";
  private String target1 = "<div class=target>abc<div class=target2>def</div></div>";
  private String target2 = "<a href=\"index.html\">トップへ</a><a href=\"index1.html\">トップ1へ</a>";

  public void sample() {
    Pattern pattern = Pattern.compile(regexp1);
    Matcher matcher = pattern.matcher(target1);
    while (matcher.find()) {
      System.out.println("一致: " + matcher.group(2));
    }
    // URL抜き出し
    pattern = Pattern.compile(regexp2);
    matcher = pattern.matcher(target2);
    while (matcher.find()) {
      System.out.println(matcher.group(1));
    }
  }

  public static void main(String[] args) {
    App app = new App();
    app.sample();
  }
}

実行結果は次の通り

一致: def
index.html
index1.html

Tomcat

久しぶりにApache Tomcat用プログラムを作成した。単純な処理をするプログラムなのだが、ついつい凝ったつくりにしてしまっていけない。一応テストしやすいクラス構成にしたつもりなのだが…

カテゴリー: Java

「エンティティとはデータベース上のテーブルとマッピングされたJavaBeansのことです」という説明

あるJavaの本をちらっと読んで見たところ、気になる表現がありました。「エンティティとはデータベース上のテーブルとマッピングされたJavaBeansのことです」という説明でした。なんというのか、違和感があります。エンティティは一般用語であるので、「データベース上のテーブルとマッピングされたJavaBeans」というのは間違いではないでしょうか。まだ、「EntityBeanは、… JavaBeansのことです」という表現なら、主語と述語の関係は成立するので意味がわかります。

しかし、問題はそれだけではありません。ここでRDBのテーブルがでてくることがよくわかりません。Entityの情報を永続化するためにはRDBなどを使うことが必要で、O/Rマッパを使えばたしかにRDBのテーブルへのマッピングはされますが、OODBなどを使う場合はちがうはずです。RDBをしっている人に対して、イメージしやすいように説明する場合には、前提にそういう説明をして、「ここでは、…と思えばよいでしょう」といった表現であればわかるのですが、最初の表現では誤解を与えそうです。ということで、気になりました。

ちなみに、「エンティティとは 【entity】 – 意味/解説/説明/定義 : IT用語辞典」とか、「「エンティティ」とは:ITpro」とかにエンティティの用語解説があります。

Processクラスを使ったプログラミング

久しぶりにJavaでプログラミングをしています。Processを使ったものなのですが、最近はProcessBuilderというものがあるのですね。

前から、子プロセスの標準入出力と標準エラー出力をきちんと使うようなプログラムにしたいと思っていたので、今回結構調べてみたのですが、結構大変そうです。やはりシェルのようなものをJavaで実装するのは厳しそうな感じがしました。できるだけ汎用的に作るためには、ストリームはバイト列で扱うような形にするとよさそうでしたが、BufferedReaderとかを使った方があきらかにプログラミングの方は楽なので、用途ごとに使い分けることにして、今回必要だと思われる機能だけに絞り込むことにしました。

注意点として、子プロセスの標準入出力と標準エラー出力は親プロセスからの参照がなくなっても残る、といったことがAPIに載っていたので、とりあえず、プロセスの実行結果 exitValue() を取得した後に、それらを close() するようにしてみました。動かしてみても、特に例外は発生してこないので、きちんと動いていると考えてよさそうです。

今回用意しているプログラムは、root権限で実行しないといけないコマンドをリモートからキックしたい、ということで用意しています。最初、root権限で実行すればいいかな、と思ったのですが、sudoコマンドをうまく使えば、ネットワークで待機するプログラム自体はroot権限で実行しなくても良さそうです。結局のところセキュリティを確保するためにSELinuxを導入しているので、面倒なことが多くなっているのですが、こうやって穴となる部分を最低限に絞り込むためには仕方がありません。どこで穴を開けて、その穴をどれだけ防御しておくか、というのがポイントになってくるので、適切な設計と設定をしたいところです。

ネットワーク経由で使いやすくするために、すごく簡単なWebインタフェースもつけてみました。1日に数回程度のアクセスしか想定していないので、Jettyを使っています。こういう軽量コンテナはやっぱり便利ですね。もちろんServerSocketとかを使って実装することもできるのですが、手間や安定性を考えると、あるものをそのまま使った方が、断然楽です。

ということで、それなりに時間もかかりましたが、いろいろなところで使えそうなソフトウェアができあがりました。これにアクセスする側のプログラムを次に作ろうと思うのですが、PHPで実装するか、Javaで実装するか、ちょっと悩んでいます。PHPを使って簡単に実装すればいいのですが、DBを使いたいとも思っていて、そうするとJavaの方が何かといいかな、と思うわけです。PHPではDBアクセスの方法がバージョンによっても違うのが気になっています。稼動させるプラットフォームとして考えているOSや環境はこれ、と決まっているわけではないので、できるだけ運用時には設定変更だけで対応できるようなつくりとしておきたいのです。そうすると、やっぱりJavaかなぁ。

ま、結局なれたものを使うということになる、というだけの話かもしれません。ちょっと休んでから、作業を再開するか。