ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Virtual Assembly Builderアプリケーションおよびイントロスペクション・プラグインの開発
12c (12.1.2)
E47992-01
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次

前
 
次
 

6 イントロスぺクション・プラグインの開発

この章では、Oracle Virtual Assembly Builderイントロスペクタ・プラグインの開発用の一連のコード・チュートリアルを介してOracle Virtual Assembly BuilderイントロスぺクションAPIの使用方法を説明します。この章の構成は、次のとおりです。

6.1 概要

このドキュメントの目的は、プラグインを構築するための手順を追ったチュートリアルを提供することです。この説明書に記載されている例のチュートリアル・ソースは'tutorials'ディレクトリ内のSDKで入手できます。このドキュメントは特定の開発環境向けに記述されたものではなく、ご使用の開発環境で所定のステップを実行する方法を理解していることを前提にしています。

6.2 チュートリアル1: Oracle Virtual Assembly Builderの統合

このチュートリアルの目的は、最も単純なプラグインを作成することです。このチュートリアルの目的はOracle Virtual Assembly Builderアーキテクチャにプラグインを登録する方法を示すことです。このチュートリアルはこれ以降のすべてのチュートリアルの基本となります。

このチュートリアルで取り上げる内容:

6.2.1 プロジェクトの作成

開始するには、'SamplePlugin'と呼ばれる空のJavaプロジェクトを作成します。Oracle Virtual Assembly BuilderはJavaの早期バージョンとの互換性がないため、これらのチュートリアルではJDK 1.6を使用する必要があります。

次のjarファイルをSDKからプロジェクトに追加します。

  • jlib/oracle.as.assemblybuilder.spif_0.1.0.jar

  • jlib/introspector/oracle.as.assemblybuilder.introspector.plugin.api_0.1.0.jar

  • jlib/core/oracle.as.assemblybuilder.external.common_0.1.0.jar

6.2.2 IntrospectorPluginの作成

プラグインを作成します。'oracle.as.assemblybuilder.introspector.plugin.IntrospectorPlugin'インタフェースがプラグインを定義します。イントロスペクタ・プラグイン・インタフェースを実装する'sample.plugin.internal.SamplePlugin'クラスを作成します。この場合、内部とはここにあるクラスは他では使用されないことを意味しています。

これでクラスは次のメソッドを保持しているはずです: getName()getJobParameters()initialize()getDehydrator()およびgetRehydrator()。これで後は、getName()の戻り値を'SamplePlugin'に変更し、空のリストを戻すgetJobParameters()を作成するのみです。プラグイン実装の残りの変更は以降のチュートリアルで取り上げます。クラスは次のように表示されます。

package sample.plugin.internal;
 
import java.util.ArrayList;
import java.util.List;
 
import oracle.as.assemblybuilder.introspector.job.JobParameter;
import oracle.as.assemblybuilder.introspector.job.JobParameterBuilder;
import oracle.as.assemblybuilder.introspector.plugin.IntrospectorPlugin;
import oracle.as.assemblybuilder.introspector.plugin.dehydrate.Dehydrator;
import oracle.as.assemblybuilder.introspector.plugin.rehydrate.Rehydrator;
 
public class SamplePlugin implements IntrospectorPlugin {
 
  @Override
  public Dehydrator createDehydrator() {
    // TODO Auto-generated method stub
    return null;
  }
 
  @Override
  public Rehydrator createRehydrator() {
    // TODO Auto-generated method stub
    return null;
  }
 
  @Override
  public List<JobParameter> getJobParameters() {
    List<JobParameter> jobParameters = new ArrayList<JobParameter>();
                
    return jobParameters;
  }
 
  @Override
  public String getName() {
    return "SamplePlugin_Tutorial1";
  }
 
  @Override
  public void initialize(JobParameterBuilder jobParameterBuilder){
    // TODO Auto-generated method stub
  }
}

6.2.3 SPIFサービスのアクティブ化

Oracle Virtual Assembly Builderフレームワークがプラグインを認識できるようにするために、サービス・アクティベータの作成から始めます。サービス・アクティベータはSPIFフレームワークの一部です。まだそうしていない場合は、第5章「Oracle Virtual Assembly BuilderプラグインSDKを使用して開発するための準備」のSPIFに関する説明に目を通してください。

'oracle.as.assemblybuilder.spif.ServiceActivator'を実装する新しいクラスの'sample.plugin.internal.spif.PluginActivator'を作成します。

サービス・アクティベータを呼び出すには、それを登録する必要があります。ルート・プロジェクト・ディレクトリ内に'resources/jar/META-INF/services'と呼ばれるフォルダを作成します。そのフォルダ内で、'oracle.as.assemblybuilder.spif.ServiceActivator'と呼ばれるテキスト・ファイルを作成します。そのファイル内にサービス・アクティベータ実装の名前を示す単一のテキスト行を配置し、必ず行末に改行を入れます。この場合、行は'sample.plugin.internal.spif.PluginActivator'になります。このファイルが'META-INF/services'ディレクトリ内の作成したjarファイルに追加されていることを確認する必要もあります。これが実行されると、Oracle Virtual Assembly Builderユーザー・インタフェースのいずれかが起動するとサービス・アクティベータのstartメソッドが呼び出され、それらがシャットダウンされるとstopメソッドが呼び出されます。

この時点で、サービス・アクティベータは呼び出されていますが、サービス・アクティベータはまだサンプル・プラグインをイントロスペクタ・プラグインとして登録していません。アクティブ化を完了するには、PluginActivatorを次のように変更します。

package sample.plugin.internal.spif;
 
import oracle.as.assemblybuilder.introspector.plugin.IntrospectorPlugin;
import oracle.as.assemblybuilder.spif.ServiceActivator;
import oracle.as.assemblybuilder.spif.ServiceContext;
import oracle.as.assemblybuilder.spif.ServiceRegistration;
import sample.plugin.internal.SamplePlugin;
 
public class PluginActivator implements ServiceActivator {
  private ServiceRegistration registration = null;
        
  @Override
  public void start(ServiceContext serviceContext) throws Exception {
    IntrospectorPlugin plugin = new SamplePlugin();
 
    this.registration = serviceContext.registerService(
      IntrospectorPlugin.class.getCanonicalName(),
      plugin);
  }
 
  @Override
  public void stop(ServiceContext serviceContext) throws Exception {
    if (this.registration != null) {
      this.registration.unregister();
    }
  }
}

startメソッドで、プラグインのインスタンスを作成し、それをIntrospectorPluginとして登録します。registerServiceの呼出し後、インスペクタ・マネージャに新しいプラグインが存在することが通知され、その後、Oracle Virtual Assembly Builderユーザー・インタフェースからのプラグインの呼出しが可能になります。もちろん、この時点では、ジョブ・パラメータ、デハイドレータ、リハイドレータも実装されていないため、興味深いことは何も発生していません。

stopメソッドでは、登録したサービスを必ず登録解除します。

6.2.4 チュートリアルの作成

プラグインをインストールし使用する前に、プラグイン・クラス用のjarファイルを作成する必要があります。大半の開発環境ではプロジェクトをJARファイルにエクスポートする手段が提供されています。META-INF/services/oracle.as.assemblybuilder.spif.ServiceActivatorファイルがJavaクラスとともにこのJARに追加されていることを確認します。

また、antを使用してOracle Virtual Assembly Builder SDKで提供されているチュートリアルとサンプル・プラグインを作成することもできます。チュートリアルまたはサンプル・ディレクトリに移動して'ant dist'と入力します。このコマンドは、クラスと適切なServiceActivatorファイルを含むjarを作成し、それを検出およびインストールに必要なディレクトリ構造に配置します。

6.2.5 プラグインのインストール

jarファイルが整ったら、plugin.configファイルとともにモックORACLE_HOMEディレクトリ構造を作成する必要があります。

Oracle Virtual Assembly Builderでは、'installPlugins'コマンドを使用してプラグインをインストールする必要があります。このコマンドを動作させるために、モックORACLE_HOMEを作成する必要があるため、'plugins/ovab/introspector/<plugin-name>'ディレクトリで'ab_home'を呼び出します。ここで、<plugin-name>はプラグインの'getName()'メソッドから戻される値で置き換えます。この場合、ディレクトリは'ab_home/plugins/ovab/introspector/SamplePlugin_Tutorial1'になります。

そのディレクトリ内に、プラグインJARファイルを'plugin.config'ファイルとともに配置する必要があります。'plugin.config'ファイルには次のコンテンツが必要です。

plugin.name=SamplePlugin
plugin.version=1.0.0
product.version.min=1.0.0
product.version.max=2.0.0
plugin.description=My sample plugin.
ovabsdk.version=3.0 

jarおよびplugin.configファイルが配置され、これでプラグインをOracle Virtual Assembly Builderインストールにインストールする準備が整いました。これは、'installPlugins' abctlコマンドを使用して実行されます。次に例を示します。

./abctl installPlugins -productRoot /path/to/ab_home

6.2.6 イントロスペクタ・プラグインの実行

abctlまたはStudioを使用してイントロスペクタ・プラグインを実行する方法を説明します。

6.2.6.1 abctlコマンドライン・ユーザー・インタフェース

プラグインをインストールすると、CLIはコマンドをプラグイン名という名前で自動的に登録します。たとえば、'SamplePlugin'と呼ばれるプラグインがある場合、'abctl help'の実行時に表示されるコマンドは'introspectSamplePlugin'となります。

インストール後は、そのプラグインに対してイントロスぺクションを実行できます。

AB_INSTANCE/binディレクトリに変更して、'./abctl help introspection'を実行できます。結果は次のような出力になります。

> ./abctl help introspection
 
Usage: abctl command [options]
 
Command                 Description                                           
------------------------------------------------------------------------------
captureFileSets         Creates file sets for specified appliance or assembly.
describePlugins         Lists the installed plugins.
disablePlugin           Disables a plugin or extension.
enablePlugin            Enables a plugin or extension.
findPlugins             Finds plugins to install.
installPlugins          Installs 1 or more plugins.
introspectCoherenceWeb  Alias for command "introspectWLS".
introspectGenericProd   Examines GenericProd configuration and captures
                        metadata.
introspectOHS           Examines OHS configuration and captures metadata.
introspectSamplePlugin  Examines SamplePlugin configuration and captures 
                        metadata
introspectWLS           Examines WLS configuration and captures metadata.
removePlugin            Removes a plugin or extension.
 
Try "abctl help name" for detailed help of a specific command.

プラグインは、プラグインとして登録するのみで、専用のイントロスペクト・コマンドを自動的に取得します。それは前の例で太字で示されています。'./abctl help introspectSamplePlugin'と入力すると、このプラグインがサポートするすべてパラメータに関するヘルプが取得されます。JobParametersを定義していない場合でもパラメータ数はリストされます。プラグインを起動するCLIコマンドには専用のパラメータがあり、すべてのプラグインが同様にこれらを保持しています。プラグインに追加したJobParametersはこのリストに追加されます。また、'./abctl introspectSamplePlugin'と入力してデハイドレーション・ジョブを初期化することもできます。ただし、getDehydrator()はnullを戻し、次のエラーが表示されます。

Launching introspection of component 'SamplePlugin' ...
Task is done: DehydrateJob failed with error: null
Error: OAB-7105: Introspection failed

6.2.6.2 Oracle Virtual Assembly Builder Studio

インストール済のプラグインはグラフィカル・ユーザー・インタフェースに追加のプラグインとして自動的に表示されます。他のプラグインと同様にそれを実行できます。詳細は、Oracle Virtual Assembly Builderの使用を参照してください。

6.2.7 まとめ

このチュートリアルは完了です。プラグインの空の実装を作成し、プラグインをOracle Virtual Assembly Builderに登録して、プラグインをインストールし、abctl CLIユーザー・インタフェースで表示されることを確認しました。

6.3 チュートリアル2: デハイドレーション

現在プラグインが作成されインストールされています。それを有効に活用する必要があります。まずはデハイドレーションを取り上げます。デハイドレーションは、後からリハイドレーションできるようにコンポーネントのメタデータを収集するプロセスです。

チュートリアル1からプロジェクトを開始します。デハイドレーション実装の作成を開始する前に、進捗モジュールをプロジェクトに追加する必要があります。SDK jlib/coreディレクトリからoracle.as.assemblybuilder.progress.api_0.1.0.jarファイルをプロジェクトのビルド・パスに追加します。

次に、'sample.plugin.internal.DehydratorImpl'と呼ばれるoracle.as.assemblybuilder.introspector.Dehydratorインタフェースを作成します。このインタフェースにはinitialize()およびdehydrate()の2つのメソッドのみがあります。dehydrate()メソッドは、CLIのintrospect<name>コマンドまたはGUIのいずれかを介してデハイドレーション・ジョブが開始されると呼び出されます。プライベートなinitializeAppliance()メソッドは、正常なデハイドレート・ジョブを実行するために必要な最小量のメタデータを設定するために使用されます。

DehydratorImplクラスは次のように表示されます。

package sample.plugin.internal;
 
import java.util.ArrayList;
import java.util.Collection;
 
import oracle.as.assemblybuilder.introspector.metadata.appliance.Appliance;
import oracle.as.assemblybuilder.introspector.plugin.dehydrate.DehydrateContext;
import oracle.as.assemblybuilder.introspector.plugin.dehydrate.Dehydrator;
import oracle.as.assemblybuilder.progress.ProgressManagerFactory;
 
public class DehydratorImpl implements Dehydrator {
  
  DehydratorImpl() {
  }
  
  @Override
  public void initialize(ProgressManagerFactory progressManagerFactory) {
    // TODO Auto-generated method stub
  }
  
  @Override
  public void dehydrate(DehydrateContext context) throws Exception {
    Appliance appliance = context.getOrCreateRootAppliance();
 
      // initialize the appliance
    initializeAppliance(appliance);
    
    //TODO: This is where you will make the changes to the Appliance
  }
  
  /**
   * Set the minimum amount needed to be a valid appliance.
   * 
   * @param appliance the appliance to update
   */
  private void initializeAppliance(Appliance appliance) {
    appliance.setVersion(1, 0, 0);
    appliance.setScalabilityInfo(1, 1, 99, 200);
    builder.addResourceRequirement(ResourceEnum.MEMORY_MB, 256);
    builder.addResourceRequirement(ResourceEnum.NUMBER_CPUS, 1);
  }
}

createDehydrator()メソッドにこのクラスの新しいインスタンスを戻すためプラグインを更新します。同時デハイドレート・ジョブの処理が大幅に簡易化されるため、必ず新しいインスタンスを戻します。また、インスタンス固有のものを保持するために静的変数を使用するのは避けてください。そうすると、同時実行において診断な困難な問題が生じることがあります。

これで、プラグイン・クラスは次のように表示されます。

package sample.plugin.internal;
 
import java.util.ArrayList;
import java.util.List;
 
import oracle.as.assemblybuilder.introspector.job.JobParameter;
import oracle.as.assemblybuilder.introspector.job.JobParameterBuilder;
import oracle.as.assemblybuilder.introspector.plugin.IntrospectorPlugin;
import oracle.as.assemblybuilder.introspector.plugin.dehydrate.Dehydrator;
import oracle.as.assemblybuilder.introspector.plugin.rehydrate.Rehydrator;
 
public class SamplePlugin implements IntrospectorPlugin {
  
  @Override
  public Dehydrator createDehydrator() {
    return new DehydratorImpl();
  }
 
  @Override
  public Rehydrator createRehydrator() {
    // TODO Auto-generated method stub
    return null;
  }
 
  @Override
  public List<JobParameter> getJobParameters() {
    List<JobParameter> jobParameters = new ArrayList<JobParameter>();
 
    return jobParameters;
  }
 
  @Override
  public String getName() {
    return "SamplePlugin_Tutorial2";
  }
 
  @Override
  public void initialize(JobParameterBuilder jobParameterBuilder) {
  }
}

この例では、アセンブリではなくアプライアンスを使用していますが、アプライアンスではなくアセンブリを作成するにはgetOrCreateRootAppliance()を呼び出している単一の行をgetOrCreateRootAssembly()に変更します。

プラグインJAR,を作成したら、6.2項「チュートリアル1: Oracle Virtual Assembly Builderの統合」の説明に従いプラグインをインストールする必要があります。

6.4 チュートリアル3: リハイドレート

リハイドレータ実装を追加するには、リハイドレータ・インタフェースを実装し、createRehydrator()が呼び出されたときにプラグインが新しいインスタンスを作成するように指定します。

sample.plugin.internalパッケージ内でRehydratorImplと呼ばれるクラスを作成します。

package sample.plugin.internal;
 
import oracle.as.assemblybuilder.introspector.plugin.rehydrate.RehydrateContext;
import oracle.as.assemblybuilder.introspector.plugin.rehydrate.Rehydrator;
import oracle.as.assemblybuilder.progress.ProgressManagerFactory;
 
public class RehydratorImpl implements Rehydrator {
 
  @Override
  public void initialize(ProgressManagerFactory progressManagerFactory) {
    // TODO Auto-generated method stub
  }
 
  @Override
  public boolean ping(RehydrateContext rehydrateContext) throws Exception {
    // TODO Auto-generated method stub
    return false;
  }
 
  @Override
  public void rehydrate(RehydrateContext rehydrateContext) throws Exception {
    // TODO Auto-generated method stub
  }
 
  @Override
  public void start(RehydrateContext rehydrateContext) throws Exception {
    // TODO Auto-generated method stub
  }
 
  @Override
  public void stop(RehydrateContext rehydrateContext) throws Exception {
    // TODO Auto-generated method stub
  }
}

RehydrateContextはデハイドレータ実装内で作成したようにメタデータへのアクセスを提供し、Oracle Virtual Assembly Builderエディタまたはデプロイメント・プランのいずれかを介してユーザーがデータに加えた変更を反映します。必要に応じて構成を変更するために実装を追加する必要があります。

RehydrateContextは、リハイドレータのstop()メソッドが呼び出されたときに実行する停止の種類を決定するためのメソッドも提供しています。プラグインは、これが通常の停止、スケール・ダウン操作(コンポーネントではある種のクラスタ化が伴うことを意味します)の一部としての停止、またはアンデプロイ操作の一部としての停止かどうかに応じて異なるアクションを実行できます。

パッケージ定義に追加されたファイルは、すでにrehydrate()メソッドが呼び出される前に配置されています。

6.5 チュートリアル4: 進捗

デハイドレーション時に、デハイドレーションの完了を待機しているユーザーがそれがまだ実行中であることを理解できるように進捗を実装することが重要です。進捗には構造化と非定型の2つのタイプがあります。

構造化進捗は、処理中に常に発生することがわかっているステップを記述するために使用されます。構造化進捗の値によって、ユーザーはデハイドレート・ジョブの実行中に発生するすべてのステップと、現在どのステップが実行されているかを把握できます。短所は、デハイドレート対象のインスタンスに関連するメッセージに固有の情報を含めることができない点です。構造化進捗はツリーに似た構造です。トップ・レベルの進捗イベントは子を保持できます。必要なレベルの深さまでネストできます。

非定型進捗は実行時までメッセージ・コンテンツがわからない場合に使用される進捗です。非定型進捗は常に構造化進捗イベントに関連しています。非定型進捗は子を保持できません。

2つの異なるタイプを理解できるように例を作成してみましょう。サンプル・プラグインに、OUIの処理、OPMNの処理、configの解析、configの処理の4つのトップ・レベルのステップがあるとします。OUIの処理とOPMNの処理は個別のイベントですが、configの解析とconfigの処理にはサブイベントがあります。configの処理は数が不明なファイルの処理で構成され、ファイルが見つかるたびに進捗メッセージを送信するものとします。これを実行するには非定型進捗が必要です。ただし、configの処理は4つの個別のプロセッサで構成されています。そのため、configの処理に構造化進捗を使用できます。

この例では、2つの個別のProgressResourceBundlesを作成する必要があります。1つはトップ・レベル・リスト用で、これをTopLevelProgressBundleと呼びます。もう1つはconfig処理リスト用で、これをConfigProcessingProgressBundleと呼びます。これらの構造化進捗リストでは、順序を維持しており順序が重要となるため、ProgressResourceBundleクラスを拡張する必要があります。バンドル内でイベントをリストする順序がイベントの送信が予定される順序です。省略されたイベントはその後のイベントを送信すると自動的に終了として設定されます。

Configパーサー内で非定型イベントを処理するには、標準のListResourceBundleを拡張する必要があります。

package sample.plugin.resources;
 
import oracle.as.assemblybuilder.progress.ProgressResourceBundle;
 
public static class TopLevelProgressBundle extends ProgressResourceBundle {
  private static final long serialVersionUID = -2753027497921148834L;
 
  static public final String PROGRESS_START = "SPI-001";
  static public final String OUI_PROCESSING = "SPI-002";
  static public final String OPMN_PROCESSING = "SPI-003";
  static public final String CONFIG_PARSING = "SPI-004";
  static public final String CONFIG_PROCESSING = "SPI-005";
  static public final String PROGRESS_COMPLETE = "SPI-006";
 
  /**
   * Contents of key/value progress messages
   */
  static final Object[][] contents =
      { { PROGRESS_START, "dehydration starting" },
        { OUI_PROCESSING, "OUI processing completed" },
        { OPMN_PROCESSING, "OPMN processing completed" },
        { CONFIG_PARSING, "config parsing completed" },
        { CONFIG_PROCESSING, "config processing completed" },
        { PROGRESS_COMPLETE, "dehydration complete" } };
    
  @Override
  protected Object[][] getContents() {
    return contents;
  }
}
 
 
package sample.plugin.resources;
 
import oracle.as.assemblybuilder.progress.ProgressResourceBundle;
 
public static class ConfigProcessingProgressBundle extends ProgressResourceBundle {
  private static final long serialVersionUID = -2105678590437947371L;
    
  static public final String PROCESS_STEP_1 = "SPI-101";
  static public final String PROCESS_STEP_2 = "SPI-102";
  static public final String PROCESS_STEP_3 = "SPI-103";
  static public final String PROCESS_STEP_4 = "SPI-104";
 
  /**
   * Contents of key/value progress messages
   */
  static final Object[][] contents =
      { { PROCESS_STEP_1, "step 1 completed" },
        { PROCESS_STEP_2, "step 2 completed" },
        { PROCESS_STEP_3, "step 3 completed" },
        { PROCESS_STEP_4, "step 4 completed" } };
    
  @Override
  protected Object[][] getContents() {
    return contents;
  }
}
 
package sample.plugin.resources;
 
import java.util.ListResourceBundle;
 
public static class ConfigParsingAdHocProgressBundle extends ListResourceBundle {
 
  static public final String PROCESSING_FILE = "SPI-201";
    
  /**
   * Contents of key/value progress messages
   */
  static final Object[][] contents =
      { { PROCESSING_FILE, "processing file {0}" } };
    
  @Override
  protected Object[][] getContents() {
    return contents;
  }
}

残りの作業は以前の作成したDehydratorImplクラス内で実行されます。initialize()メソッドで、progressManagerFactoryへの参照をインスタンス変数に保存します。

次の例では、initializeProgress()メソッドに特に注意してください。例の後にメソッドについて説明します。

package sample.plugin.internal;
 
import java.util.ArrayList;
import java.util.Collection;
 
import oracle.as.assemblybuilder.introspector.metadata.appliance.Appliance;
import
  oracle.as.assemblybuilder.introspector.metadata.attributes.ResourceRequirement.ResourceEnum;
import oracle.as.assemblybuilder.introspector.plugin.dehydrate.DehydrateContext;
import oracle.as.assemblybuilder.introspector.plugin.dehydrate.Dehydrator;
import oracle.as.assemblybuilder.progress.AdHocMarker;
import oracle.as.assemblybuilder.progress.ProgressListener;
import oracle.as.assemblybuilder.progress.ProgressManager;
import oracle.as.assemblybuilder.progress.ProgressManagerFactory;
import oracle.as.assemblybuilder.progress.ProgressProxy;
import sample.plugin.resources.Resources;
 
public class DehydratorImpl implements Dehydrator {
  private ProgressManagerFactory progressManagerFactory = null;
  private AdHocMarker configParsingAdHocMarker = null;
  
  DehydratorImpl() {
  }
  
  @Override
  public void initialize(ProgressManagerFactory progressManagerFactory) {
    this.progressManagerFactory = progressManagerFactory;
  }
  
  @Override
  public DehydrateResult dehydrate(DehydrateContext context) throws Exception {
    Appliance appliance = context.getOrCreateRootAppliance();
    
    //configure all the progress proxies
    ProgressProxy progress = initializeProgress(context.getProgressListener());
    
    progress.onProgress(Resources.TopLevelProgressBundle.PROGRESS_START);
    
    //initialize the appliance
    initializeAppliance(appliance);
    
    //TODO: Do OUI stuff
    progress.onProgress(Resources.TopLevelProgressBundle.OUI_PROCESSING);
    
    //TODO: Do OPMN stuff
    progress.onProgress(Resources.TopLevelProgressBundle.OPMN_PROCESSING);
    
    //Just for fun, create a list of files to parse
    String[] files = { "file.1", "file.2", "file.3", "file.4" };
    
    for (String file : files) {
      //TODO: do something with the files
      
      //generate ad-hoc messages
      progress.onProgress(this.configParsingAdHocMarker,
          Resources.ConfigParsingAdHocProgressBundle.PROCESSING_FILE, file);
    }
    
    //Now send the processing events
    progress.onProgress(Resources.ConfigProcessingProgressBundle.PROCESS_STEP_1);
    progress.onProgress(Resources.ConfigProcessingProgressBundle.PROCESS_STEP_2);
    progress.onProgress(Resources.ConfigProcessingProgressBundle.PROCESS_STEP_3);
    progress.onProgress(Resources.ConfigProcessingProgressBundle.PROCESS_STEP_4);
    
    //all done
    progress.onProgress(Resources.TopLevelProgressBundle.PROGRESS_COMPLETE);
  }
  
  private ProgressProxy initializeProgress(ProgressListener progressListener) {
    ProgressManager progressManager =
      this.progressManagerFactory.createManager(progressListener);
    
    //assign the top level events to this manager
    progressManager.registerBundle(new Resources.TopLevelProgressBundle());
    
    ProgressManager childProgressManager = null;
    
    //create a child progress manager for the config parsing event
    // and make it ad-hoc,  we need to save the adHocMarker when
    // sending ad-hoc progress events
    childProgressManager = progressManager.createChildManager(
                   Resources.TopLevelProgressBundle.CONFIG_PARSING);
    this.configParsingAdHocMarker = childProgressManager.registerAdHoc(
                   new Resources.ConfigParsingAdHocProgressBundle());
    
    //create the child-progress events for the config processing event
    ProgressManager configProcessingProgressManager = progressManager.createChildManager(
                   Resources.TopLevelProgressBundle.CONFIG_PROCESSING);
    configProcessingProgressManager.registerBundle(
                   new Resources.ConfigProcessingProgressBundle());
    
    //at this point, the progress tree is configured
    //now we generate the proxy that is used to send events
    
    return progressManager.generateProxy();
  }
  
  /**
   * Set the minimum amount needed to be a valid appliance.
   * 
   * @param appliance the appliance to update
   */
  private void initializeApplianceBuilder(Appliance appliance) {
    appliance.setScalabilityInfo(1, 1, 99, Integer.MAX_VALUE);
    appliance.addResourceRequirement(ResourceEnum.MEMORY_MB, 256);
    appliance.addResourceRequirement(ResourceEnum.NUMBER_CPUS, 1);
  }
}

進捗の興味深い部分はinitializeProgress()メソッドです。前述のとおり、それには進捗ツリーを作成するためのすべてのロジックが含まれています。進捗のトップ・レベルを表すProgressManagerインスタンスの作成から開始します。その後、トップ・レベル進捗イベント用のイベント・リストを含むProgressResourceBundleを設定します。

次のステップは、トップ・レベルProgressResourceBundleからのキーを使用した、Configの解析ツリー用の子ProgressManagerの作成です。これにより、この子ProgressManagerをトップ・レベル進捗イベントにアタッチします。Configの解析の子ProgressManagerは非定型進捗イベントを処理するため、registerAdHoc()メッセージを呼び出し、それを送信する進捗イベントを含むListResourceBundleに渡します。これは、後で非定型進捗イベントをトリガーするときに使用されるAdHocMarkerも戻します。

次に、Configの処理ツリー用の子ProgressManagerを作成します。この子ProgressManagerは構造化ProgressManagerであるため、registerBundle()を呼び出し、registerAdHoc()は呼び出しません。進捗ツリーのすべてのレベルのキーが一値であることを確認する必要があります。重複していると予期せぬ結果を招くことがあります。

プロセスの最終ステップは、進捗ツリー全体を構成した後のProgressProxyの生成です。その後、ProgressProxyは構造化と非定型の両方の進捗イベントをトリガーするために使用されます。ただし、非定型の場合は、ProgressProxyがイベントをツリー内のどこに追加する必要があるかわかるように、AdHocMarkerインスタンスを渡す必要があります。

プロジェクトをエクスポートし、それをORACLE_HOMEにデプロイします。その後'./abctl introspectSamplePlugin'を実行します。結果は、次のように表示されます。

> ./abctl introspectSamplePlugin
Launching introspection of component 'SamplePlugin' ...
  Step 1 of 6: dehydration starting
  Step 2 of 6: OUI processing completed
  Step 3 of 6: OPMN processing completed
    Step 1: processing file file.1
    Step 2: processing file file.2
    Step 3: processing file file.3
    Step 4: processing file file.4
    Step 1 of 4: step 1 completed
    Step 2 of 4: step 2 completed
    Step 3 of 4: step 3 completed
    Step 4 of 4: step 4 completed
  Step 6 of 6: dehydration complete
Task is done: DehydrateJob completed
Introspection complete
Storing result in catalog: '/Users/cooluser/Documents/Perforce/my-depot/drm/src/dist/ab_home/catalog' ...
Introspection stored as 'SamplePlugin-1276728646099' in the catalog

進捗のチュートリアルは完了です。このチュートリアルでは、構造化および非定型の両方の進捗、子ProgressManagerおよびProgressMessagesのトリガーを使用した進捗ツリーの初期化を取り上げました。プラグインのユーザーには、プラグインの実行が予想通り進行していることを把握するために必要な情報が提供されます。

6.6 チュートリアル5: ジョブ・パラメータ

イントロスペクタ・プラグインは、abctlコマンド・ラインで指定されたパラメータまたはStudio内のテキスト・フィールド・エントリを介して、呼出し時にユーザーからの追加情報を収集することがあります。イントロスペクタ・プラグインは、自身を登録するとジョブ・パラメータのリストをフレームワークに提供できます。フレームワークはそれをキューとして使用し、ユーザーからの指定された情報を収集します。

この例のサンプル・プラグインでは、1つは汎用文字列、もう1つはパスワードの2つのジョブ・パラメータを構成しています。

 @Override
  public List<JobParameter> getJobParameters() {
    JobParameter jobParameter;
    List<JobParameter> jobParameters = new ArrayList<JobParameter>();
    
    jobParameter = jobParameterBuilder.setName(Resources.STRING_PARAM_NAME)
        .setValueType(ValueType.NAME).setRequired(false)
        .setDefaultValue(Resources.STRING_PARAM_DESC).build();
    jobParameters.add(jobParameter);
    
    jobParameter = jobParameterBuilder.setName(Resources.PASSWORD_PARAM_NAME)
        .setValueType(ValueType.PASSWORD).setRequired(false)
        .setDescription(Resources.PASSWORD_PARAM_DESC).build();
    jobParameters.add(jobParameter);
 
    return jobParameters;
  }

前出の例で、このメソッドが空のジョブ・パラメータ・リストを戻していた点に注意してください。リソース・クラスは、パラメータ名と説明用にここで使用されている文字列を含むように作成されています。

package sample.plugin.resources;
 
public class Resources {
 
  public static final String STRING_PARAM_NAME = "stringParam";
  public static final String STRING_PARAM_DESC = "just a generic string parameter";
 
  public static final String PASSWORD_PARAM_NAME = "samplePassword";
  // This ends up being the password prompt:
  public static final String PASSWORD_PARAM_DESC = "Administrator password";
}

これらのパラメータはユーザーによってabctlコマンド・ラインで指定される場合があります(必須としてマークされている場合は指定する必要があります)。それらは説明とともに自動的にプラグインのabctlヘルプに表示されます。Oracle Virtual Assembly Builder Studioでは、イントロスぺクション・ウィザードによってテキスト入力ボックスにパラメータ値を入力する機会が与えられ、すべての必須パラメータに値が入力された後にのみイントロスぺクション・ウィザードの次のステップに進めます。

Oracle Virtual Assembly Builderフレームワークはabctlで使用するためにパラメータ名の略語を生成します。たとえば、"samplePassword"という名前のパラメータは"abctl introspectSamplePlugin -samplePassword"または"abctl introspectSamplePlugin -sp"のいずれかで指定できます。フレームワークは、camelCaseパラメータ詳細名を調べてパラメータの略語を選択し、重複する略語がある場合は報告します。

パスワードタイプのジョブ・パラメータはセキュリティ上の考慮事項があるため他のタイプのパラメータとは異なり、パスワードはコマンド・ライン引数として入力できません。(それらがコマンドラインでプレーンテキストで入力されると、Unix "ps"コマンドを使用して表示可能となってしまいます。)かわりに、フレームワークはデハイドレーションを開始する前にパスワードの入力を求めます。短い説明がパスワード・プロンプトとして使用されます。また、セキュリティ上の配慮から、パスワードは文字列としてではなく文字配列として保持されます。それらは文字列に変換してはならず、パスワードがそれ以降不要になった場合には文字配列は消去する必要があります。

次のように、デハイドレーション時にユーザー指定のパスワード値を取得できます。

Map<String, JobParameter> jobParameterMap = context.getJobParameterMap();
JobParameter stringParameter = jobParameterMap.get(Resources.STRING_PARAM_NAME);
String stringParameterValue = stringParameter.getValue();

フレームワークは、パスワード用にいくつかのデータ型(NAME、ADDRESS、PATH、NUMERIC、BOOLEAN、PASSWORD)を提供していますが、例外のPASSWORDを除き、パラメータ値はプラグインに文字列として指定されるため、たとえば、BOOLEANパラメータの場合には、プラグインが文字列"true"および"false"を実際のブール値に変換する必要があります。

BOOLEANパラメータは2つの顕著な一意の側面を持つため、abctlコマンドでは、フラグが指定されている場合にパラメータ値が"true"といったように、これらをオプション・フラグとして作成します。そのため、BOOLEANパラメータを必須としても意味がなく、デフォルト値を指定する必要はありません。デフォルト値は常に"false"です。

6.7 サンプル・プラグイン

サンプル・プラグインはチュートリアルとともに含まれています。このサンプルはチュートリアルで網羅されていない多数のSDK機能の例を示しています。チュートリアルと同様に作成しインストールでき、イントロスぺクション用に使用する場合はデプロイ可能なアプライアンスが生成されます。

6.8 サンプル・プラグイン拡張機能

サンプル・プラグイン拡張機能も参考として提供されています。このサンプルはサンプル・プラグイン全体を拡張しています。このサンプルは、中でも特に、すでにベース・プラグインによって作成されたアプライアンスにアクセスする方法と、ベース・プラグインによって作成されたファイル・セット定義を更新する方法を示しています。