BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ アーティクル eXo Platformの概要

eXo Platformの概要

ブックマーク

eXo Platformは、新たなPortlet Container 2.0とPortal 2.1のリリースをお知らせ致します。eXoはコンシューマとプロバイダへのJava Portlet 2.0 API (JSR 286)と Web Service Remote Portlet 2.0 (WSRP)フルサポートを備えた、最初のポータルです。このニュースを、eXo Portal、Portle-Containerおよびエンタープライズ・コンテント・マネジメント(ECM)が提供する新機能を見てみる良い機会としましょう。

eXo Platformアーキテクチャの概要

eXo Platformが備えるPortal、Portlet Container、ECMコンポーネントの詳細を述べる前に、そのプラットフォーム・アーキテクチャの概要を説明することが大切でしょう。

eXo Platformのまさしく最初のバージョンから、Pico Containerという名のInversion of Control(IoC、制御の反転)コンテナがサービス間の依存性の疎結合を提供するのに使用されていました。その役割はコンポーネントの実装を行い、それを従属コンポーネントに挿入するものです。

eXo Platformの全てのコンポーネントは、このIoCコンテナを使用してプラグインとして開発され関係づけられています。次の図では、下位レベルから上位レベルまでのeXoプラットフォーム・スタックにおける各々のコンポーネントが示されています。

 

Web 2.0 Portal

eXo Portalの新しいバージョンは前のバージョンに導入されたものの上に構築され、AJAXに代表されるWeb 2.0テクノロジーにより拡張可能モデルがもたらしたユーザの複雑性を取り除くことができました。

実際にeXoは、他のポータルの大半が静的レイアウトを使用していた時に動的レイアウトのコンセプトを導入した初めてのものです。主な違いは、動的レイアウトではポートレットがリーフにあたる、ネスト化したコンテナのツリーを取り扱っているようになることです。次の図に見られるように、コンテナはちょうどSwing UIオブジェクトを取り扱うときのように、その子のレイアウトに関与します。自由に使えるコンテナ・レンダラが行、列、またはタブに子を表示します。

その結果、1つのロケーションから別のロケーションへコンテナを移動させることは、単なるデータ構造サイドでのツリー操作になるのです。クライアント・サイドでは、JavaScriptコードを用いてそのツリー操作を容易にするドラッグ・アンド・ドロップ・ライブラリを作成しました。そのため、次のスクリーンショットにあるように、コンテナやポートレットをページの内側にドラッグ・アンド・ドロップするだけでなく、ある種のコンテナやポートレットをドラッグしてページの中に引き込むことも可能です。

それぞれのポートレットは、ポータルがページにレンダリングできるようにする一連のメタデータを備えています。このメタデータには(次のスクリーンショットにあるように)タイトル、サイズ、アイコン、縁取りの外観などだけでなく、その縁取りやアイコンを表示するかどうかも(ポートレットを最小化または最大化するため)含まれています。

これらの情報を入力すると、Portalが実際は異なる型のページをレンダリングできるようになります。ユーザがログインすると、(次のスクリーンショットにあるように)各々の型はユーザ・メニューに集められます。ページの型には以下のようなものがあります。

  • どのユーザも閲覧するポータル・ページ。一部のページにおいては、エクストラネットや私達のウェブサイト(リンク)などのインターネット・サイトの基盤となっている匿名ユーザも見ることができます。 
  • 一連のダッシュボードとして見ることができる、(企業のポリシーがそれを許可する場合だけですが)ユーザが新しいページやコンテンツを追加できるユーザ・ページ。

     

  • マーケティンググループ、セールスグループといったユーザが所属しているグループのページをユーザ・メニューに追加するグループ・ページ。

また上のスクリーンショットでは、ユーザがログインした際に現れる左側の折りたたみカラムもあります。ここには、ページ間をナビゲートする手段やいくつかのアドミニストレーション・メニューのほか、ユーザが好きなように設定できるウィジェット群があります。以前に述べた通り、ウィジェットはRESTプロトコルを使用してサーバと通信する、フルJavaScriptコンポーネントです。この先のバージョンでは、Google OpenSocialスタンダードをベースとするでしょう。

eXo PortalもフルAJAXポータルです。つまりあるページから別のページに移動すると画面の一部のみが更新されるということです。そうするために私達は、ページが変更されたり、ページ中の1つあるいは複数ポートレットのコンテンツに手を加えなければいけなかったりするごとにサーバを非同期的にコールするためJavaScript XMLHttpRequestオブジェクトを利用しています(あるポートレットが別のポートレットにJSR 286標準コールを使用してメッセージを送信する場合と同じように)。イベントが送信される場合を除いて1つのrender()のみが必要なので、当然ながらこのことはサーバ・コールを大幅に改良しています。

それぞれのリクエストで、ポータルはページにアップデートされるべき様々なHTMLフラグメントを包括したXMLファイルを返します。そのXMLファイルの構造は次のようになっています。

 * {PortalResponse}
  *      |
  *      |--->{PortletResponse}
  *      |
  *      |--->{PortletResponse}
  *      |          |-->{portletId}
  *      |          |-->{portletTitle}
  *      |          |-->{portletMode}
  *      |          |-->{portletState}
  *      |          |
  *      |          |-->{PortletResponseData}
  *      |                 |
  *      |                 |--->{BlockToUpdate}
  *      |                 |         |-->{BlockToUpdateId}
  *      |                 |         |-->{BlockToUpdateData}
  *      |                 |
  *      |                 |--->{BlockToUpdate}
  *      |
  *      |--->{PortalResponseData}
  *      |      |
  *      |      |--->{BlockToUpdate}
  *      |      |         |-->{BlockToUpdateId}
  *      |      |         |-->{BlockToUpdateData}
  *      |      |
  *      |      |--->{BlockToUpdate}
  *      |
  *      |--->{PortalResponseScript}

サーバのレスポンスには3つのタイプのXMLが入っています。

  • タグに含まれているポータル・コンポーネント・フラグメントに対するもの。これは更新するIDのコンポーネントも含んでいる。 
  • アップデートするそれぞれのポートレット・フラグメントに対するもの。これはウィンドウ・ステートや更新するポートレット・モードといったポートレット情報も含んでいます。eXo Portal 2.x AJAXの機能を認識するポートレットはまた、ポータルに対してフル・ポートレット・リフレッシュ(これは完全に準拠したJSR 286ポートレットにとって必須です)を避けるのに直接更新するHTMLタグがどれかを伝えます。
  • 新しく作成されるページで利用できるように動的評価をするJavaScriptコード

中のリターンされたJavaScriptは、ポータルかJavaScriptを処理するeXoポータルを認識するポートレットによって生成されます。さらに、リターンされたJavaScriptはeval()メソッドの間に動的にページに追加されるよう、グローバルJavaScript関数を(function()シンタックスを用いて)定義する必要があります。繰り返して申し上げますが、ポートレットが純粋なJSR 286のものであれば、この使い勝手のよい方法を用いることはできません。その場合、ポータルは を解析しblockToUpdateがセットアップされていないことを確認します。従って、ページに追加できるよう、全てのスクリプトを見つけるために全ポートレット・フラグメントを解析します。SpagoBI のポートレットなどJavaScriptを含むサード・パーティJSR 168ポートレットのいくつかがテストされてきています。

新しいeXo Portalにおける別の大きな改良点は、全てのポータル・コンフィグレーション・ファイル(グループ、ユーザおよびポータルそれぞれのページ、またウィジェットやポートレット・プリファレンスなど)が今や標準リポジトリに保管されているということです。次のスクリーンショットでは、ルート・ユーザ・ページが/exo:registry/exo:users/root/UserPortalData:の場所にXMLファイルで保管されているのがわかります。

JCRレイヤーの使用はストレージ・パフォーマンスやクラスタ性能にとって都合がよいだけでなく、RESTサービスを通じたネイティブ・エクスプロージャなどJCRが提供する高度なサービスについても便利です。

eXo Portlet Container: JSR 286およびWSRP 2

eXo Portlet Container 2.0はJavaおよびWebサービス・ポータル・ワールドの2つの主要な新仕様を実装しています。

  • Portlet API 2.0
  • WSRP 2

ポータルの一部として、ポートレット・コンテナはマルチ・ウィンドウ環境で明るみに出るアプリケーションの管理に関わりを持っています。

この新バージョンのため、私達は内部のアーキテクチャを大幅に改良しました。特に以前に導入されたプラグインのメカニズムを活用し、ポートレット・コンテナに拡張ポイントをもたらしました。

Portlet API 2.0 (JSR 286)

Portlet API 2.0は2008年6月13日にリリースされ、eXoはこれに準拠し、このポートレットを取り入れるようポートレット・コンテナおよびポータル双方を備えた最初の実装です。その仕様はJSR 168の拡張で、専門家グループはJSR 168ポートレットがJSR 286コンテナで動くことを保証するのに特に焦点を当ててきました。

Portlet 2.0 APIは以下のような新機能を導入しました。

  • イベントやパラメータを他のポートレット(同じWARにある必要はありません)へ送信可能にするポートレット間通信(IPC, Inter-Portlet Communication)
  • servletフィルタの働きを模倣するポートレット・フィルタ
  • レンダリング段階でレンダリング・パラメータを全てのポートレットと共有するためのパブリック・パラメータ
  • JSR 168では極めて制限のあった部分である、高度なキャッシュ機能
  • (servlet経由に代わり)より優れたイメージ挿入を行うための新しいserverResource()メソッド
  • URLが呼び出される際にハンドラをトリガするためのURLリスナー・メカニズム

ポートレット間通信の説明

JSR 268仕様の全ての新機能を説明することはしませんが、主要なもの、つまり(IPCとしても知られる)ポートレット間通信の詳細について述べます。

IPCプロセスの詳細に入る前に、JSR 168ポートレット・リクエストのコンテクストにおけるプロセスを見てみましょう。JSR 168においては、リクエストは2つのフェーズに分けられます。

  1. processAction() : JavaBeanのようなビジネス・オブジェクトのステートを変えるために単一ポートレットをターゲットとします
  2. render() : ページのポートレットごとに呼び出され、HTMLフラグメントのレンダリングに関与します。

レンダリングされたHTMLフラグメントは変更されたJavaBeanオブジェクトに依存し得るので、processAction() メソッドはどのrender() 呼び出しにも先立って発生しなければいけないという理由から、フェーズ2のリクエストは必須であるということに気をつけるのは大切です。

このことから、JSR 168は、単一ポートレットのコンテクストにおいてユーザ・インターフェイスのレンダリングを定義するに過ぎないということがわかります。JSR 168は、複合アプリケーションを構築する際のキーポイントであるポートレット間の通信に関する標準的方法を何も定義しません。

とは言え、開発者はこれまでよく、HTTPセッションを使っているマルチ・ポートレット間でJavaBeanオブジェクトを共有できる事柄を利用してきました。しかし、この種のセッション・ベースの共有は、同一WARでデプロイされたポートレットに限られるため、この方法は限定的です。

現実のシナリオでは、ポートレットは様々な提供元からもたらされ、異なるWARにまとめられている可能性があります。それでも私達は、ポータル・ユーザが高性能な複合アプリケーションを作成できる、ポートレット間インタラクションを提供したいと考えています。例えば、住所などユーザの詳細を表示するアドレス・ブックのポートレットを構築し、地図に所在地を表示するためにGoogle Mapサービスを使うサード・パーティのポートレットをアップデートしたい、ということがあるかもしれません。

次のシーケンス・ダイアグラム(仕様テキストから抜粋)に見られるように、それがJSR 286がprocessEvent() フェーズ、つまりprocessAction() フェーズの終わりにイベントを引き起こすものを導入した理由です。

イベントはprocessAction() アクション・メソッドをActionResponseオブジェクト(PortletResponseを拡張するもの)につけることでprocessAction() アクション・メソッドから実行されます。そしてポートレット・コンテナはイベントを、そのイベントはどのポートレット・インスタンスをターゲットにすべきかの識別を行うポータル層に伝えます。

イベント・ディスパッチは指定のスコープ外なのですが、ポータル・レベルでの1つの解決法は、同一ページにあり、かつイベントを処理できる全てのポートレット・インスタンスをターゲットにすることです。processEvent() メソッドは、新しいイベントをトリガすることもできることに注意してください。無限循環の呼び出しを避けるのはポータルの役割です。

IPCコンフィグレーション

ポートレットのIPC コンフィグレーションはportlet.xml ファイルでなされます。

<portlet>
     <description xml:lang="EN">TestProcessEvent</description>
     <portlet-name>TestProcessEvent</portlet-name>
     <display-name xml:lang="EN">Test ProcessEvent</display-name>
     <portlet-class>
       org.exoplatform.services.portletcontainer.test.portlet2.TestProcessEvent
     </portlet-class>
     <expiration-cache>0</expiration-cache>
     <cache-scope>PRIVATE</cache-scope>
     <supports>
       <mime-type>text/html</mime-type>
       <portlet-mode>view</portlet-mode>
       <portlet-mode>edit</portlet-mode>
       <portlet-mode>help</portlet-mode>
     </supports>
     <supported-locale>EN</supported-locale>
     <portlet-info>
       <title>TestProcessEvent</title>
       <short-title>TestProcessEvent</short-title>
     </portlet-info>
     <supported-processing-event><name>MyEventPub</name></supported-processing-event>
     <supported-publishing-event><name>MyEventPub</name></supported-publishing-event>
   </portlet>

   [...]

   <event-definition>
     <name>MyEventPub</name>
     <value-type>
       org.exoplatform.services.portletcontainer.test.portlet2.MyEventPub
     </value-type>
   </event-definition> 

この例では、同じポートレットがイベントを発行・処理しています。確かに、実際の例では2つの異なるポートレットとなるでしょう。イベント・エイリアスが用いられ、関連するイベント・クラスはXMLファイルで1回だけ定義されるということに注意してください。

IPCの使用

ポートレットは一般的にGenericPortlet クラスを拡張し、これ自身はprocessEvent() メソッドを定義するEventPortletインターフェイスを実装します。

下にあるのはコードのサンプルで、イベント・オブジェクトをprocessAction() メソッドに登録する方法とprocessEvent() メソッドで読み出す方法を示しています。

  public void processAction(ActionRequest actionRequest, ActionResponse actionResponse)
       throws PortletException, IOException {
     MyEventPub sampleAddress = new MyEventPub();
     sampleAddress.setStreet("myStreet");
     sampleAddress.setCity("myCity");
     actionResponse.setEvent(new QName("MyEventPub"), sampleAddress);
   }

   public void processEvent(EventRequest req, EventResponse resp)
       throws PortletException, IOException {
     System.out.println("In processEvent method of EventDemo... !!!!!!!!!!!!!");
     Event event = req.getEvent();
     System.out.println("  -- name: " + event.getName());
     System.out.println("  -- value: " + event.getValue());
     MyEventPub sampleAddress = new MyEventPub();
     sampleAddress = (MyEventPub) event.getValue();
     resp.setPortletMode(PortletMode.EDIT);
   }

WSRP 2の仕様もprocessEvent() フェーズをサポートしているためイベントを別のサーバ上でコンシューマからプロデューサに伝えることができ、イベントがJAXBを使ってシリアライズ可能かということを確認すればよいということに開発者は留意してください。

スタンドアロン・ポートレット・コンテナ

eXo Portlet Container 2.0は独立したアプリケーションとしてダウンロードが可能で、サード・パーティのアプリケーション内への組み込みを容易にしています。これには、下のスクリーンショットにあるような、使用者のJSR 286ポートレットとの互換性を列挙する容量の小さいアドミニストレーション・ポータルが備わっています。WARにデプロイされた1つあるいは複数のポートレットを選択し、それを確認することができます。

下のスクリーンショットでは、serverResource() メソッドおよびAJAXの呼出し後にリターンされたマークアップを用いて画像を表示するResourceDemoポートレットを選択しました。

組み込みポートレット・コンテナ

標準的なポートレットなので、portlets2.war をeXo エンタープライズPortalまたはWebOSにデプロイして、テストをしたり新規格について学んだりすることもできます。

Application Registryを開く必要があるでしょう。この管理ポートレットにより、カテゴリごとに編成されたポートレットを閲覧できます。デプロイされた全てのポートレット・アプリケーションWARを素早くインポートするためのボタンがあります。

このスクリーンショットには、portlets2.warのデプロイおよびインポート後に取得すべき「portlets2」カテゴリがあります。右にはTestPublicParam2TestProcessEvent1といったJSR 286ポートレットのデモがあります。

適切に設定されると(パーミッションが適用される)、ドックバーの左側に「+」アイコンを用いてデスクトップ・ページにポートレットを追加できます。

ここでは多数のポートレットがドックに追加されましたが、私達はそのうち3つを表示させました。TestPublicParam1TestPublicParam2そしてTestPublicParam3です。これらのポートレットは新しいJSR 286のPublic Parameterをデモンストレーションします。

この特性により、processAction() フェーズにレンダリング・パラメータを設けることができます。そしてこれらのパラメータは全ポートレットの全てのrender() メソッドにおいてアクセス可能となります。JSR 168では、関連ポートレットのみがレンダリング・パラメータを認識できました。

前の画面では、ポートレット1または2の「set public param」オプションをクリックすると、ポートレット3でパブリック・パラメータが利用できるようになるのが確認できます。3番目のポートレットでそのリンクをクリックすると、ポートレット1と2のパブリック・パラメータが3番目のポートレットのパラメータによって上書きされます。

WSRP 2

Java Portlet APIに加え、Web Services Remote Portlet 2.0 (WSRP)もこれまで説明してきた新機能をサポートするためにアップデートされてきました。

現在、外部のコンポーネントを真のポートレットであるかのようにポータル層に拡張するプラグイン実装を備えることが可能です。そのようなプラグインの実例は、次の図にあるように、JSR 286プラグインがローカル・ポートレットを拡張するのと全く同じ方法でリモート・ポートレットをポータルに拡張するWSRP 2コンシューマ・プラグインです。

このメリットはポータルUIが同じようにローカル・ポートレットおよびリモート・ポートレットを処理するという点です。つまりJSR 168あるいは286のプロキシ・ポートレットはこれ以上必要ありません。ユーザはポートレット・プリファレンスのWSDLファイルのリモート・アドレスといったものを設定しなくてはいけなかったので、プロキシ・ポートレットは煩わしいものでした。このタスクは今、コンシューマ・プラグインの設定をする際にアドミニストレータが行います。

WSRPプロデューサ・アーキテクチャはあまり変更がありませんが、コードは全面的に書き改められました。私達は2008年の間、他のプロデューサおよびコンシューマがテストするために利用できるようになり次第、他の競合と私達のコンシューマおよびプロデューサとの相互運用性についてチェックしていきます。

The WebOS:ポータル・レイアウト

厳密に言うと、WebOSはPortal 2.0リリースのカスタム・レイアウトに過ぎません。これは、そのポートレットがコンテナ内にある必要はないということです。ですので、ポートレットやウィジェットは互いに重なり合うことができるドラッグ可能なウィンドウとして表示されます。それはちょうど読者のデスクトップにある標準的なオペレーティング・システムのようですが、全てブラウザの境界線内にあります。ページがマルチ・ウィンドウ環境として表示されるため、普通のポータルと全く同じように、いくつかのデスクトップ(ポータル、グループ、あるいはユーザ・デスクトップ)を設けることが可能です。例えば、1つのデスクトップが(次のスクリーンショットのように)Mail、CalendarまたはContentに代表されるコラボレーション・アプリケーションを擁し、その一方で別のデスクトップにERPバックエンドにアクセスするポートレットを備えることができるでしょう。

WebOSの目標は、ブラウザの内部で最適な人間工学的パターンを再現することです。それが、私達が独自の環境の中に数種の既存オペレーティング・システムからフィーチャーやスキンを混合させた理由です。最も注目すべきものは以下のものです。

  • WebOSパージのポートレットを含んでいるドック。1つのアイコン上で右クリックすると、そっくからポートレットを取り除くことができます。以下2つのスクリーンショットには、2つの異なるスキンで表示されたドックがあります。「+」ボタンにより新しいポートレットをドックやユーザが使用する権限のあるページを追加できます。

  • 左の列にある「スタート・メニュー」により、新しいページ作成のウィザードといった発行・管理機能にアクセスできます。これはまた、使われているロケートを変更する手段や選択スキンの変更方法などをもたらします。前に指摘したように、これによりユーザは、全てのページで利用できるが、WebOSの内部に追加されたものはそこでのみ有効であるようなウィジェットのセットを定義できます。

eXo Application Registryで入手できるどのPortletやWidgetも、WebOSレイアウトで利用できます。

eXo Java Content RepositoryとECM

新ポータルに加え、eXo Platformは、ちょうどポータルにあるようにJCRを基盤としたECM(Enterprise Content Management)ソリューションの新バージョンをリリースしました。

Java Content Repository:ファイル・システム

eXo JCR(eXo Java Content Repository)は、私達が行ったJSR 170の実装です。ここではコンテントを集中型リポジトリに保管する一方で、その構造化、バージョン化、ロック、そしてサーチ方法を標準化しています。eXo Platformのほかのコンポーネントと類似して、この製品には次のスキーマにあるように多くのオプティマイゼーションと拡張機能を備えています。これらは全て、OW2 forgeでダウンロードできる単独の配布製品にて利用可能です。

JCRのスキーマは3つの分野に分けられます。

  • 仕様実装といくつかのAPI拡張およびeXoのストレージ部分の管理方法であるコア・パート
  • FTP、CIFS、WebDAV、DeltaV、DASLといったプロトコル・コネクタ
  • Microsoft OfficeやOpen Officeプラグインといったアプリケーションおよびプラグイン

これら3つのパートのさらなる詳細を検討しましょう。

JCRコア

eXo JCR実装は、JSR 170のマルチ・リポジトリかつマルチ・ワークスペースな実装です。JCRバックエンドのエントリ・ポイントはリポジトリ・オブジェクトですが、この仕様において複数のリポジトリを準備することは必須ではありません。とは言うものの、このことが極めて都合がいいという場合もあります。

リポジトリにより、1つあるいは複数のワークスペースへのアクセスができます。繰り返して申し上げますが、この仕様はワークスペースのサポートを強制しているわけではないのですが、私達はその便利な機能のためこれを実装しました。

ワークスペースではノード・ツリーをブラウズでき、それは標準的なファイル・システム・フォルダの拡張版のように表示されます。ツリーのリーフはDateやBinaryといったいくつかのタイプのPropertyオブジェクトです。File Systemのアナロジーを用いれば、バイナリのプロパティをファイルとして確認できます。これについては、次のダイアグラムに描写されています。

eXoの実装において各ワークスペースは、ファイルのパスやプロパティ(Dublin Coreメタデータなど)といったメタデータ情報が保存されている様々なデータベースをそれぞれ示すことができます。パフォーマンス上の理由で、ファイルそのものは1つのファイル・システム(NAS、SANなど)に保存されます。ワークスペースはそれぞれ、高度なキャッシング、バッファリング、スワッピング、インデクシング、あるいはセキュリティ・ポリシーを設定できます。スケータビリティが必要な際はリポジトリのクラスタリングも可能です。

次のXMLフラグメントは、JCR環境を設定するのに使われるカスタム・コンフィグレーション・ファイルを示しています。ここで全てのリポジトリ設定を定義できますが、1つのワークスペース設定を詳細に説明するのにとどめておきましょう(このXMLフラグメントのコメントをチェックしてください)。

<repository-service default-repository="repository">
   <repositories>

     <!-- ############################################################ -->
     <!-- Every repository needs a system workspace to store the JCR   -->
     <!-- configuration info as well as the version history. The       -->
     <!-- default workspace is the one that would be returned by the   -->
     <!-- login method when no workspace is specified                  -->
     <!-- ############################################################ -->
     <repository name="repository" system-workspace="system" 
                                   default-workspace="collaboration">

      <!-- ########################################################################## -->
      <!-- The first step is to define the workspace security such as the JAAS domain -->
      <!-- it applies to. It is also possible to plug a custom policy manager there   -->
      <!-- ########################################################################## -->
      <security-domain>exo-domain</security-domain>
      <access-control>optional</access-control>
      <authentication-policy>org.[..].PortalAuthenticationPolicy</authentication-policy>

      <workspaces>
        <!-- ######################################################################### -->
        <!-- Each repository can contains several workspaces, each one with a Root     -->
        <!-- Node that can have its own structure and permission configuration         -->
        <!-- ######################################################################### -->
        <workspace name="system" auto-init-root-nodetype="nt:unstructured" 
                   auto-init-permissions="*:/platform/administrators read;
                                          *:/platform/administrators add_node;
                                          *:/platform/administrators set_property;
                                          *:/platform/administrators remove" >

           <!-- ####################################################################### -->
           <!-- Each workspace can have its own way to store content but the most usual -->
           <!-- one is to use a database for the metadata information and a File System -->
           <!-- for the binary documents. Here we use a simple file system but with a   -->
           <!-- storage algorithm that store the content in a tree to split the number  -->
           <!-- of files per folder. The Swap directory is used when we upload files    -->
           <!-- ####################################################################### -->
           <container class="org.exoplatform.services.jcr.[..].JDBCWorkspaceDataContainer">
             <properties>
               <property name="sourceName" value="jdbcexo"/>
               <property name="dialect" value="hsqldb"/>
               <property name="multi-db" value="false"/>
               <property name="update-storage" value="true"/>
               <property name="max-buffer-size" value="204800"/>
               <property name="swap-directory" value="../temp/swap/system"/>
             </properties>
             <value-storages>
               <value-storage id="system" class="org.[..].TreeFileValueStorage">
                 <properties>
                   <property name="path" value="../temp/values/system"/>
                 </properties>
                 <filters>
                   <filter property-type="Binary"/>
                 </filters>
               </value-storage>
             </value-storages>
           </container>

          <!-- ###################################### -->
          <!-- Caching, Indexing and locking are then -->
          <!-- configured                             -->
          <!-- ###################################### -->
          <cache enabled="true">
           <properties>
             <property name="maxSize" value="20000"/>
             <property name="liveTime" value="30000"/>
           </properties>
          </cache>
          <query-handler class="org.exoplatform.services.jcr.[..].SearchIndex">
           <properties>
             <property name="indexDir" value="../temp/jcrlucenedb/index"/>
           </properties>
          </query-handler>
          <lock-manager>
            <time-out>900000</time-out><!-- 15min -->
 	   <persister class="org.exoplatform.services.jcr.[..].FileSystemLockPersister">
              <properties>
                <property name="path" value="../temp/lock"/>
              </properties>
            </persister>
          </lock-manager>
        </workspace>

この仕様の大切なポイントは、NodeTypeと呼ばれる、コンテントの構造を定義する能力にあります。例えば、ある企業で、どの記事もタイトル、執筆者、要約、サムネイル画像、そして記事全文の掲載を必要とするウェブで公表されるとしましょう。NodeTypeはそれぞれのフィールド、そのタイプ(Date、Stringなど)、そのほかタイトルが必須かどうかといったいくつかの情報を決定するのに使用されます。作成された記事はそれぞれ、このNodeType基準を満たす必要があります。

eXo JCRの有用な特性は、JavaインターフライスAPIを通して新しいNodeTypeを動的に追加できるという点です。eXo JCRの上に構築されるどのようなタイプのアプリケーションであっても、開発にこのAPIを使用できます。これが、eXo ECMが実装されてきた経緯です。

そのほかいくつかの特徴がスペックに追加され、サード・パーティのアプリケーションがJCRの上に革新的なサービスを構築するのに役立っています。

  • Word、PDF、あるいはOpen OfficeドキュメントとしてJCRに追加された全てのオフィスドキュメントに対するDublin Coreのネイティブ・サポートは、そのプロパティがJCR Nodeに抽出・添付されます
  • JCR Nodeにオーディット能力が追加され、1つのコンテント上の各アクションのログが取られます
  • セキュリティが強化され、独自のセキュリティ・マネージャーにプラグインできます。これはドキュメント・アクセスに高度なプロファイリングを与えるのに都合がよくなっています。
  • 標準的な監視機能に加え、ワークスペースに継続的な変更がなされる際のディスパッチ・イベントも考慮する追加的なイベント通知。eXo JCRは一時セッションのレベル変更にそれぞれ応じてイベントをディスパッチおよび起動する拡張機能も用意しています。これは例えばDublin Coreのネイティブ・サポートに利用されます。

最終的に、私達は、私達のJCRリポジトリのSoftware as a Service (SaaS)バージョンを提供するカスタム・ストレージおよび認証メカニズムも開発しました。このために、Amazon Web Services EC2とS3 Servicesを活用しました。S3はインターネットを介したストレージ・システムであるのですが、EC2によって仮想マシンのインスタンスを動的に作成できます。従って、EC2とS3のアカウントがあれば、eXo JCRのカスタム版で設定されたAmazon Machine Instance (AMI)を立ち上げることができます。これは、ファイルを保存するのにS3を用い、データベースやJCRサーバのホストにEC2を用います。私達がリリースした最初のAMIには、Linux OSが定義したユーザを活用するPluggable Authentication Module (PAM)も備わっています。

JCRプロトコル

このプラットフォーム開発の最初期から、私達は標準のリレーショナル・データベースの上に応用サービスを適合させるよう、ストレージ戦略の中心にJCRを置くことを決めていました。そのため、私達が開発し、私達の製品ラインに入っているどのアプリケーションも、そのコンテントをJCRに保管しています。このことは、大半の企業データについて有用な集中化をもたらします。

従って、サード・パーティ・アプリケーションからの情報アクセスは直接的なものでなくてはいけません。その相互運用性を容易にするため、多くのプロトコルが通信可能なJCRリポジトリを作成してきました。

  • WebDAVは、WindowsやMac OSといった大半のオペレーティング・システムがネイティブ・サポートするため、おそらく最も知られているものでしょう。これにより、ファイル・システムのローカル・パーティションとしてリモート・サーバをマウントできます。そのため通常のファイル・システム・インターフェイスを介してリモート・フォルダや文書を閲覧できます。
  •  
  • DeltaVDASLはWebDAVプロトコルの2つの拡張機能です。2つはそれぞれ、デフォルトのプロトコルにバージョニングと検索機能を追加します。これらは。次章で紹介するMicrosoft OfficeプラグインのようなeXoプラグインに広く使用されています。
  • CIFSはMicrosoftのプロトコルで、ネットワーク上でドライブを共有します。eXoはどのJCRリポジトリでもCIFS/Sambaサーバとして認識されるよう、アブストラクト・レイヤーを実装しました。
  • RMIは、Javaオブジェクトを異なるJVMで動く他のJavaアプリケーションに間接的に公開するJavaプロトコルです。私達は、全JCR APIを間接的に公開できるRMIスタブを実装しました。
  • FTPは大容量のファイル交換に最適化されたプロトコルです。eXoはJCR上にFTPサーバを実装しました。下のスクリーンショットにあるようなシンプルなクライアントを使用して6ギガバイトのファイルを転送できます。

WebDAVについてのさらなる詳細

WebDAVプロトコルは、PUT、GET、そしてDELETEを利用したHTTPプロトコルの拡張に過ぎません。これまで見てきたように、JCRの仕様により構造化コンテンツを管理できますが、これは標準的なファイル・システムに関する場合ではなく、JCRセマンティクスのサブセットのみがプロトコルを通じて公開されます。ドキュメント管理システム(DMS、Document Management Systems)を扱う際は、通常はこれで十分です。私達のRESTフレームワークを活用してWebDAVサーバを一から構築したことに注目するのは関心を引くことでしょう。

次のスクリーンショットには、Mac OSファイル・システムにおいてcollaborationと名付けられフォルダとしてマウントされたJCRワークスペースがあります。

最終的に、サード・パーティの開発者たちの仕事をシンプルにするため、私達はJavaとC#でいくつかのクライアントAPIを作成し、WebDAV HTTPリクエスト作成のオブジェクト指向な方法の雛形としました。JavaでのシンプルなWebDAVコピー・メソッドはこのようになるでしょう。

DavContext context = new DavContext("localhost", 8080, "/jcr-webdav/repository");
 CopyCommand copy = new CopyCommand(context);
 copy.setResourcePath(srcName);
 copy.setDestinationPath(destName);
 int status = copy.execute();

JCRに保管されているコンテンツを異なるプロトコルを介して公開することにより、サード・パーティのベンダやインテグレータは、このプラットフォームと交信を行うカスタム・アプリケーションを開発できます。

Word処理やスキャンのような機能といった一部のアプリケーションは極めて一般的であるため、私達も独自のプラグインを既存製品にそのままコード化しました。

これはMicrosoft Office 2003スイートの例で、私達はC#プラグインをこれに対応するよう開発しました。JavaベースのOpenOfficeプラグインも開発しました。両方のケースで、WebDAV、DeltaV、そしてDASLプロトコルが使われています。2つのプラグインの特徴はほぼ同じで、「Remote Documents」という新メニューが作成されました。これにより、以下のことが可能になります。

  • 現在編集しているドキュメントをいくつかの異なるフォーマットでリモートeXo JCRサーバに直接保存できます。例えばWordテンプレート文書(.dot拡張子がついたファイル)をサポートしています。

  • 文書のバージョニングをサポートできます。つまり、どのようなドキュメント変更をしても、新バージョンを作成します。

  • ビルト・インされているMicrosoft Word差分ツールを使って、JCRサーバに保存されている2つのバージョンのドキュメントを比較することもできます。

  • フル・テキスト検索を利用し、既にサーバに保存されているドキュメントを探すことができます。検索はドキュメント・テキストと関連するメタデータの両方を探します。下のスクリーンショットはOpenOfficeのインターフェイスです。

JCRストレージへのアクセス用にサポートされている多様なプロトコルがあるため、eXoコンテント・リポジトリに接続するよう既存アプリケーションを拡張することはいたってシンプルです。別の興味深い(WebDAVプロトコルをベースとしC#でコード化されている)プラグインは、KofaxによるAscent Captureアプリケーション用に作成されたもので、これはスキャンおよび光学文字認識(OCR、Optical Character Recognition)ツールです。このプラグインにより、受信する印刷文字を動的にJCRに保存できます。また、検出された情報をJCRのドキュメント・メタデータに挿入します。

エンタープライズ・コンテント・マネジメント

eXoエンタープライズ・コンテント・マネジメント(ECM)はWeb Content, DocumentおよびRecord Managementツールを備えるポートレットのセットです。これはeXo JCR上に構築され、私達がここまでに紹介してきた機能やコネクタを利用しています。

ECM製品にはまた、ECMコンテンツやドキュメントを自社内で簡単に共有・普及できるようカスタマイズできる、予め設定されたワークフローがいくつか備わっています。独自のワークフローの追加や、それを多様な方法で作り出すこともできます。ワークフロー・エンジンの実装自体はプラグ可能で、私達は2つの実装(jBPMおよびBonita)を容易していますが、ユーザ独自のものも記述できます。

eXoポータルの実装は、すぐ使用できるプレゼンテーション・ポートレットにより進められており、このポートレットはイントラネット又はインターネット・エクストラネット用途のためユーザのコンテンツをポータル内に表示する多くの手段を用意しています。

このように、eXo ECMはエンタープライズ・コンテンツの取得、作成、管理、公開、および記録に対し強力なサポートを提供します。これらは全て高いカスタマイズ性をもつやり方で実行されます。しかしまた、製品の主な原動力となっているのは、ファイル・エクスプローラといった実際のオペレーティング・システムの既存アプリケーションとよく似た、簡単に使えるインターフェイスで高度な機能が提供されているという点です。

ECM File Explorer

eXo ECMの中心的なコンポーネントの1つがFile Explorerアプリケーションです。このポートレットはECMへのユーザ・フレンドリーなバック・オフィスのエントリ・ポイントを備えています。

ドライブ:

File Explorerのホームは、私達が「ドライブ」と呼ぶマネージド・リポジトリへのショートカットを表示します。3種類の異なるタイプのドライブがあります。:

  • パーソナル・ドライブは各ユーザに対して確保されています。そこにある文書はプライベートに保たれるか、他と共有されます
  • グループ・ドライブは、特定のユーザグループに制限された定義エリアです
  • ジェネラル・ドライブはリポジトリの他のエリアへのショートカットです

ユーザがその認証設定に関連付けられたドライブのみ見られるよう、ドライブに認証の指定がなされます。ドライブは、ワークスペースでのロケーションパスやエクスプローラ内に適用されるビュー(サムネイル、リスト等)といった、その他多くの設定も行います。下のスクリーンショットは、ECMアドミニストレーション・ポートレットおよびいくつかの事前に設定されたドライブを示しています。:

File Exploring

ECM File Exploringユーザ・インターフェイスは、ユーザのローカル・コンピュータのファイル管理と同程度の簡便さとなるよう設計されました。左側には、ファミリー・ツリー図がフォルダを表示しています。上部にはアドレス・バーが現在のフォルダのパスを表示しています。右側には、フォルダ内のファイルが作業領域に表示されています。ツールバーによりユーザはコンテンツを操作できます。ツールバーのアクションはテーマごとにグループ化され(例えばジェネラル、コラボレーション、サーチなど)、ユーザ・インターフェイスはWindowsのファイル・エクスプローラのようになじみある見た目と感覚を持つように調整されました。

ユーザの承認により、あるドキュメントで利用できるアクションの数は変更されます。一部のWeb 2.0機能、例えばあるドキュメントにおけるタグ付け、投票、コメント付けといったものは全てのRecords Managementドキュメントに対しては無効にできますが、ウェブ上で公開されるコンテンツに対しては有効にできます。

そのほかにもアクションがあります。ドキュメントのバージョン管理といった一般的なものから、ドキュメントの構造のチェック(例えば、どのような種類のメタデータが関連付けられているかなど)といったより複雑なものまであります。

このポートレットはDocument ManagementおよびRecords Managementのプロセスのほか、Web Content Managementのプロセスの基礎となります。

File Explorerによって、File PlanにDocumentを簡単に追加できます。File Planは切断される前にしばらくの間システム内に留まるレコードとなります。eXo ECMはDOD 5015.2 Records Managementの仕様を実装しています。あるPDFがアップロードされると、そのPDFのプロパティが抽出されJCR内のドキュメントに結び付けられます。そしてメタデータ上で高度な検索を行うことが可能となり、また例えば、「サブジェクト」プロパティにDublin Core「Article」値を持つ全てのドキュメントを探すといったこともできます。下のスクリーンショットでは、PDFドキュメントがアップロードされAdvanced Search(高度な検索)が実行されています。このフォームで、検索したいDublin Coreプロパティを選択できます。そしてポップアップが表示されプロパティが保有する全ての値から選ぶことができます。スクリーンショットではプロパティの値リストで「Article」という独特のエントリがあります。プロパティの制約を組み合わせてさらに高度な検索をすることもできます。

eXo ECMでは、JCR NodeTypeの特徴を利用してドキュメントの構造を特定することができます。これはアドミニストレーション・ポートレット(「Type of content」セクションの中)を通して行われます。コンテンツ構造が作成されると、次のステップでは、そのコンテンツのインスタンスを作成できるようなフォームを作成します。eXo ECMではそのようなフォームはダイアログと呼ばれeXo JCRに保存されるGroovyテンプレートとして記述されます(従ってバージョン変更可能です)。次のスクリーンショットでは、いくつかのフィールド(Name、Title、Summaryなど)を伴ったフォームが示されています。このフォームはレンダリングされたダイアログ・テンプレートで、各フィールドはいくつかのタイプ(例えばリッチ・テキスト・エディタ、日付、アップロード・フィールドなど)のうち1つを備えることができます。WYSIWYGエディタによってJCRリポジトリから、あるいはJCRリポジトリに画像をインポート・アップロードできます。作成されると、構造化されたコンテンツはビュー・テンプレートと呼ばれる別のGroovyテンプレートによってレンダリングされます。ビュー・テンプレートとはコンテンツ・インスタンス・フィールドをいくつかのHTMLコードで装飾したものです。これでコンテンツはワークフロー・プロセス内で有効となり、ウェブで公開される用意が整いました。

 

アクション

eXo ECMの主要な特徴は、フォルダを含むどのようなノードにもアクションを添付できることです。アクションとは、新しいワークフローを始めたりカスタムGroovyスクリプトを実行したりできるノード・ライフサイクル(追加、アップデート、削除など)に対するフックです。

次のスクリーンショットは、ドキュメントが「Validation Request」フォルダにコピーされるとすぐ有効になる、デフォルトのドキュメント・バリデーション・ワークフローです。ドキュメントが認証されると、ドキュメントは「Pending」フォルダにコピーされ、そこで公開日を待ちます。公開日になると、ジョブはドキュメントを「Live」フォルダに移動し、そこで公開日が終わるまで留まります。

ドキュメントがLiveフォルダにあるとき、最後に公開されたドキュメントを抽出するクエリを作成したり表示用の優れたHTMLテンプレートを適用したりするのに、サード・パーディのアプリケーションやコンテンツ・パブリッシング・ポートレットはこのフォルダをポイントすればよくなっています。

アクションはGroovyスクリプトを立ち上げることもできます。そこで作成者や作成日といったドキュメント・メタデータ・プロパティをコンソールに表示させるためDocumentReaderServiceを用いた簡単なスクリプトでこの機能を例示してみましょう。実際には、アクション・スクリプトはeXoレジスタ・サービスの呼び出しを簡単にするIoCも用いています。

public class DisplayDocumentProperties implements CmsScript {

   private DocumentReaderService readerService;
   private RepositoryService repositoryService;

   // Constructor injection of needed eXo services
   public DisplayProperties(RepositoryService repositoryService, 
       DocumentReaderService readerService) {  
     this.repositoryService = repositoryService ;
     this.readerService = readerService;
   }

   public void execute(Object context) {

     // load node from JCR
     String workspace = context["srcWorkspace"];
     String path = context["srcPath"];
     Node document = (Node) repositoryService.getRepository()
       .getSystemSession(workspace).getItem(path);

     // extract document properties
     String mime = document.getProperty("jcr:mimeType").getString();
     InputStream data = document.getNode("jcr:content")
       .getProperty("jcr:data").getStream();
     Set properties = readerService.getDocumentReader(mime)
       .getProperties(data).entrySet();

     // display properties
     propreties.each() { print " ${it.key} ${it.value}" };
   } 

スクリプトはアドミニストレーション・ユーザ・インターフェイスを介して追加され、アクションそしてJCRノードに結び付けられます。例えば、公開プロセスについては、最近発行されたニュースの大部分に基づきRSSフィードを動的に作成することもできるでしょう(このアクションはeXo ECMにネイティブに存在します)。

ビジネス・モデル

eXoプラットフォームSASビジネス・モデルは、Red HatやMySQLによく似た、従来型のOpen Sourceのモデルです。eXoはエンド・ユーザおよび企業に2つのバージョンを提供します。

CommunityエディションはOW2 forgeから自由にダウンロードできます。このエディションは2、3週間ごとにリリースされ、最新のコードとコミットが備わっています。ベーシックなQAプロセスが適用されています。テストは3つのOpen Sourceアプリケーション・サーバ(Tomcat、JOnAS および JBoss)で実行されます。このバージョンのソース・コードはパブリックSVNサーバで入手でき、本稿で説明されたそれぞれのモジュールの主要部分にあります。

EnterpriceエディションはCommunityエディションを安定化させたものです。SVNサーバ上の自身のブランチに存在し、購入および年間契約した人だけが利用できます。6ヶ月から9ヶ月ごとにそれぞれのプロダクトについてリリースされ、その際ソース・コードはSVNサーバ内でタグ付けされます。この製品のQAプロセスは1500を超える統合テストおよびストレス・テストを伴った広範囲なものです。これはまた、BEA WebLogic、Oracle Application Server、IBM Webspereといった専売のアプリケーション・サーバおよび専売のデータベースで評価されています。管理およびユーザマニュアルがパッケージに含まれています。またアドオンで保証や補償もこの製品には適用されます。

eXo Platform SASはそのほか2つの市場をターゲットとしています。

  • 独立系のソフトウェア・ベンダー(ISV、Independent Software Vendors)がそのアプリケーションでeXoをバンドルすると考えられる、OEM市場。顧客のニーズに従って、専用ライセンスおよびロイヤルティ・モデルが使用されます
  • eXoアプリケーションを一定期間レンタルできるSaas(Software as a Service)市場。厳密に言うと、このモデルはAmazon EC2(仮想マシンを割り当てる)とS3(データをクラウドに保存できる)を利用します

原文はこちらです:http://www.infoq.com/articles/exo-platform
(このArticleは2008年7月23日に原文が掲載されました)

この記事に星をつける

おすすめ度
スタイル

BT