Define New Processor — 処理器の定義

OverView — 概要

以下の2つのクラスのサブクラスを作成しなければいけません.

  • AbstractProcessor: クラスファイルの変換処理を行う処理器の実装のため.
  • AbstractProcessorService: 処理器のメタ情報を管理するクラス.SPI (Service Provider Interface).

AbstractProcessorでは,実際の変換処理を行い, 指定された場所へ変換後のクラスファイルを出力します. なお,変換の前に前処理用のメソッドが呼び出され, 変換が全て終わったあと,後処理用のメソッドが呼び出されます.

AbstractProcessorServiceでは,処理器のメタ情報を定義します. 処理器の作成者,作成者の所属団体,また,処理器がどのようなパラメータを受け取るのか, そのパラメータの初期値を適切に返すように実装します.

AbstractProcessorクラスとAbstractProcessorServiceクラスは1対1の対応関係を持ちます. 一方,AbstractProcessorオブジェクトはAbstractProcessorServiceオブジェクトに対して複数存在できます. AbstractProcessorオブジェクトがいくつ存在しようと,対応するAbstractProcessorServiceは1つです. もちろん,別の処理(処理B)を行う処理器の場合は,別のAbstractProcessorServiceオブジェクトが存在します.

Create Subclass of AbstractProcessorAbstractProcessorクラスのサブクラスの作成

以下の3つのメソッドを実装しなければいけません. また,処理結果をSummaryオブジェクトにまとめて返します.

Override required method list of AbstractProcessor class
メソッド名返り値の型説明
preparevoidProcessorの初期化処理のため,呼び出されます.
performvoidProcessorの処理を行います.
summarizevoidProcessorの後処理のため,呼び出されます.

以下,それぞれのメソッドが行うこと,処理結果の出力方法について説明します.

prepare_methodprepareメソッド

初期化処理を行います.このメソッドにはArgumentsが渡されます. 渡されたArgumentsに沿って処理を行うよう初期化しなければいけません.

perform methodperformメソッド

実際に変換を行うメソッドです.このメソッドは2つの引数を受け取ります. TargetSourceDestinationです.

TargetSourceは入力の集合を表します.zipやjar, ディレクトリ内のクラスファイルの集合を抽象化するクラスです. 処理器が入力元を意識しなくても良いようになっています. TargetSourceは複数のProcessTargetを持ちます. ProcessTargetの列挙はTargetSourceiteratorメソッドで得られます.

ProcessTargetは1つのファイルを表します. ファイルの種類はProcessTargetgetTypeメソッドで判定できます. また,ファイルの内容はgetSourceメソッドが返すInputStreamから読み取れます.

Destinationは出力先を抽象化します.zipファイル,jarファイル, ディレクトリを区別せず出力できます. outputメソッドにクラス名もしくはファイル名を渡せば,それに対応した OutputStreamが返されます. 返されたOutputStreamにクラスファイルを出力すれば,適切に処理されます.

summarize methodsummarizeメソッド

処理中に確保したメモリの解放などの終了処理を行います.

Print Processing Result — 処理結果の出力

処理結果はSummaryオブジェクトにまとめられ出力されます. Summaryオブジェクトは自動的に作成されるため,エントリを追加することで処理結果をまとめます. エントリはキーと値のペアで表されます.キーも値も文字列型で表されます. キーは階層構造としても表せ,階層は「.(ドット)」で区切ります.

Define Meta Information of Processor処理器のメタ情報の定義

AbstractProcessorServiceクラスを継承したクラスを作成します. 継承したクラスでは以下のメソッドを実装し,適切なオブジェクトを返さなくてはいけません.

Override required method list of AbstractProcessorService class
メソッド名返り値の型説明
getProcessorNameStringこの処理器の名前を文字列で返します.
getDescriptionStringこの処理器の説明を文字列で返します.
createProcessorProcessor対応する処理器オブジェクトを生成して返します.
createProviderProviderこの処理器の著者情報を返します.
createDefaultArgumentsArgumentsこの処理器のパラメータの初期値を返します.

Create Service Descriptor — サービスデスクリプタの作成

適当な場所にrydeen.spi.ProcessorServiceという名前のファイルを作成します. 内容は上で作成したAbstractProcessorServiceを継承したクラスの完全修飾名 (パッケージ名を含むクラス名.最後に.classは必要ありません)を書きます. 1行に1クラスとしてください.

Create Jar File — Jarファイルの作成

作成した処理器, SPIとその関連クラスを全て含むjarファイルを作成します. 上で作成したサービスデスクリプタはMETA-INF/services/に置いてください. その後,作成したjarファイルをクラスパスに含めてRydeenを実行すれば自動的に作成したクラスが認識されます.

Example — 実装例

ここでは,サンプルとして,何も処理しないNopProcessorをサンプルとして作成します. パッケージはrydeen.plugins.nopとします.

NopProcessorNopProcessorの作成

処理器のクラスを作成します.このクラスはAbstractProcessorを継承し, AbstractProcessorクラスのサブクラスの作成 で記したメソッドを実装します.

NopProcessorでは何も処理を行わないので,prepareメソッド,summarizeメソッドは何も行いません.

package rydeen.plugins.nop;

import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;

import rydeen.AbstractProcessor;
import rydeen.Arguments;
import rydeen.Destination;
import rydeen.ProcessorException;
import rydeen.ProcessTarget;
import rydeen.TargetSource;

public class NopProcessor extends AbstractProcessor{
    public NopProcessor(NopProcessorService service){
        super(service);
    }

    @Override
    public void prepare(Arguments args){
        // do nothing....
    }

    @Override
    public void perform(TargetSource source, Destination dest) throws ProcessorException{
        for(ProcessTarget target: source){
            try{
                InputStream in = target.getSource();
                OutputStream out = dest.output(target.getName());
                putEntry("target", target.getName());

                int data;
                while((data = in.read()) != -1){
                    out.write(data);
                }
                in.close();
                out.close();
            } catch(IOException e){
                throw new ProcessorException(e);
            }
        }
    }

    @Override
    public void summarize(){
        // do nothing....
    }
}

NopProcessorServiceNopProcessorServiceの作成

AbstractProcessorServiceクラスを継承してProcessorServiceの実装クラスを作成します. 実装しなければならないメソッドは上で記した5つのメソッドです.

getProcessorNameメソッドはASCII文字列で返してください. getDescriptionは今のところ,Localeは無視できます. getProviderメソッドで,作成者情報を隠しておきたい場合はProvider.UNKNOWNを返すことができます.

createProcessorメソッドは処理器が必要になったときに呼び出されます. このメソッドでは毎回新たなオブジェクトを作成してください. なぜなら,1セッションの間に同じ処理器が実行される場合があり, 同じ処理器でも与えるパラメータが異なる場合があります. それらは同一のオブジェクトでは区別できないため,新たなオブジェクトを必要とするためです.

createDefaultArgumentsは最初の1度だけ呼び出されるメソッドです. このサービスクラスが提供する処理器のパラメータとその初期値を表すオブジェクト Argumentsを作成し,返してください.受け取るパラメータが何もなければ, このサンプルのように単純にArgumentsオブジェクトを作成し,返してください.

package rydeen.plugins.nop;

import java.net.URL;
import java.net.MalformedURLException;

import rydeen.Arguments;
import rydeen.Processor;
import rydeen.spi.AbstractProcessorService;
import rydeen.utils.Author;
import rydeen.utils.Organization;
import rydeen.utils.Provider;

public class NopProcessorService extends AbstractProcessorService{
    @Override
    public String getProcessorName(){
        return "nop";
    }

    @Override
    public String getDescription(){
        return "何も処理を行わない処理器";
    }

    @Override
    public Processor createProcessor(){
        return new NopProcessor(this);
    }

    @Override
    public Provider createProvider(){
        return Provider.RYDEEN_PROVIDER;
    }

    @Override
    public Arguments createDefaultArguments(){
        return new Arguments();
    }
}

Create Service Descriptor for NopProcessor — サービスデスクリプタの作成

rydeen.spi.ProcessorServiceファイルに以下の内容を書きます.

rydeen.plugins.nop.NopProcessorService

Create Jar File of NopProcessor — Jarファイルにまとめる.

以下の構成でjarファイルを作成します.

root -+- rydeen ---- plugins ---- nop -+- NopProcessor.class
      |                                  |
      |                                  +- NopProcessorService.class
      +- META-INF -+- MANIFEST.MF
                   |
                   +- services --- rydeen.spi.ProcessorService

Deploy — デプロイ

作成したjarファイルをRydeenのlibディレクトリに置くと起動時に読み込みます. 以下のコマンドを入力し,最後にnopが表示されればデプロイできています.

$ rydeen.sh --help