Toolbarを表示したい その3

Urumaが自動生成するplugin.xmlとEclipsePDEが自動生成するplugin.xmlの見比べ

Urumaでメニューを作成するとこんな感じ。

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
 <extension point="org.eclipse.ui.contexts" >
  <context id="org.seasar.uruma.example.rss.context" name="Uruma allication local context" />
 </extension>
 <extension point="org.eclipse.ui.commands" >
  <category id="org.seasar.uruma.example.rss.command.category" name="org.seasar.uruma.example.rss" />
  <command id="org.seasar.uruma.example.rss.command.fileDelete" name="削除(D)" categoryId="org.seasar.uruma.example.rss.command.category" />
 </extension>
 <extension point="org.eclipse.ui.handlers" >
 </extension>
 <extension point="org.eclipse.ui.bindings" >
  <scheme id="org.seasar.uruma.keyConfiguration" name="UrumaApplication" />
  <key sequence="DELETE" schemeId="org.seasar.uruma.keyConfiguration" commandId="org.seasar.uruma.example.rss.command.fileDelete" />
 </extension>
 <extension point="org.eclipse.ui.menus" >
  <menuContribution locationURI="menu:org.eclipse.ui.main.menu?after=additions" >
   <menu mnemonic="E" label="編集(E)" >
    <command commandId="org.seasar.uruma.example.rss.command.fileDelete" mnemonic="D" icon="target/main-classes/images/rss.png" >
    </command>
   </menu>
  </menuContribution>
 </extension>
 <extension point="org.eclipse.ui.views" >
  <view id="org.seasar.uruma.example.rss.urumaDebugView" name="デバッグ・ビュー" class="org.seasar.uruma.rcp.ui.GenericViewPart" allowMultiple="false" />
  <view id="org.seasar.uruma.example.rss.urumaBundleManagerView" name="バンドルマネージャ・ビュー" class="org.seasar.uruma.rcp.ui.GenericViewPart" allowMultiple="false" />
  <view id="org.seasar.uruma.example.rss.feedTreeView" name="フィードツリー・ビュー" class="org.seasar.uruma.rcp.ui.GenericViewPart" allowMultiple="false" />
  <view id="org.seasar.uruma.example.rss.feedListView" name="フィード・ビュー" class="org.seasar.uruma.rcp.ui.GenericViewPart" allowMultiple="false" />
  <view id="org.seasar.uruma.example.rss.feedBrowserView" name="ブラウザ・ビュー" class="org.seasar.uruma.rcp.ui.GenericViewPart" allowMultiple="false" />
 </extension>
 <extension point="org.eclipse.ui.perspectives" >
  <perspective id="org.seasar.uruma.example.rss.defaultPerspective" name="RSS" class="org.seasar.uruma.rcp.ui.GenericPerspectiveFactory" icon="uruma" fixed="false" />
 </extension>
</plugin>

EclipsePDEでアクション(メニューとツールバーボタン)を作るとこんな感じ。

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
   <extension point="org.eclipse.ui.actionSets">
      <actionSet
           id="org.eclipse.contribution.hello.actionSet"
           label="Sample Action Set"
           visible="true">
        <menu
              id="sampleMenu"
              label="Sample &amp;Menu">
           <separator
                 name="sampleGroup">
           </separator>
        </menu>
        <action
              class="org.eclipse.contribution.hello.actions.SampleAction"
              icon="icons/sample.gif"
              id="org.eclipse.contribution.hello.actions.SampleAction"
              label="&amp;Sample Action"
              menubarPath="sampleMenu/sampleGroup"
              toolbarPath="sampleGroup"
              tooltip="Hello, Eclipse world">
        </action>
     </actionSet>
   </extension>
</plugin>


メニューの部分を比べてみると構造が全然違うなぁ。

PDEでは、メニューもツールバーボタンも区別はなくて、actionがmenubarPathとtoolbarPathをもっているだけ。

うーむ。
Urumaのツールバーボタンは、XML

ツールバーボタンとして内部で扱えばよいかな。

あとは、Urumaの生成するplugin.xmlの方言に合わせたツールバーボタンの記載ができれうまく作れそうだけど、方言がさっぱりわかんないww


extension point="org.eclipse.ui.menus" ← plugin.xmlの書き方のため、ここから追いかけてみる。
まず、EclipseCSVリポジトリからorg.eclipse.uiのPJをcheckout。

plugin.xmlを見てみると、

<extension-point id="menus" name="%ExtPoint.menus" schema="schema/menus.exsd"/>

で、さらにmenus.exsdを見てみると、サンプルがあった。

<p>
A basic extension looks like this.
</p>
<pre>
   <extension
         id="add.item"
         point="org.eclipse.ui.menus">
      <menuContribution
         locationURI="menu:someorg.somemenu.id?after=additions">
         <command
               commandId="someorg.someid.someCommand"
               icon="icons/anything.gif"
               id="someorg.someid.BasicCmdItem"
               label="Simple Item"
               mnemonic="S">
         </command>
      </menuContribution>
   </extension>
</pre>
<p>
This is the simplest example; adding a command contribution after an existing menu's additions group.
</p>

Urumaのplugin.xmlに記載しているメニューと似ている。

<p>
This extension point allows the plug-in developer to add (contribute) a variety of custom additions to the eclipse framework:
<ul>
  <li>Main Menu</li>
  <li>Main Toolbars</li>
  <li>View Menus/Toolbars:
  <ul>
    <li>View Dropdown Menu</li>
    <li>View Toolbar</li>
    <li>Context Menu(s)</li>
  </ul>
  </li>
  <li>Trim</li>
</ul>
</p>
<p>
It provides a common implementation for and acts as a replacement of the following (legacy) eclipse extension points:
<ul>
<li>org.eclipse.ui.ActionSets</li>
<li>org.eclipse.ui.EditorActions</li>
<li>org.eclipse.ui.popupMenus (including 'objectContributions')</li>
<li>org.eclipse.ui.viewActions</li>
</ul>
</p>

Extenstionがreplacementされている。
しかも、since 3.3 って明記があって道理でNETで調べても情報がすくないわけだ。
っていうか、APIころころ変わりすぎ>Eclipse。 ついていけんw。
手元のEclipsePlugin本も全滅だー。

まとめ

  • ツールバーのためにUrumaがplugin.xmlに出力すべき構文がわかった。
  • ツールバー用にXMLスキーマはいじらないで、の情報を元にする。
  • 次はUrumaがplugin.xmlをどうやって出力しているか調査する。

id:y-komoriさんはよく調査したなぁー。

Toolbarを表示したい その2

Urumaにはすでに、ToolBarComponentとToolItemComponentのUIComponentが用意されていました。スキーマ(uruma.xsd)にもToolbarのアトリビュートがあるので、設定値は読み込めそうです。


UrumaのサンプルPJ(RSS)のworkbench.xmlに「toolBar」を追加します。

<?xml version="1.0" encoding="UTF-8"?>
<template xmlns="http://uruma.sandbox.seasar.org">
  <workbench title="Uruma Example - RSS Reader" initWidth="1024"
    initialPerspectiveId="defaultPerspective" initHeight="800"
    image="uruma" statusLine="true"
    saveAndRestore="true" menuBar="true" 
    coolBar="true" fastViewBars="true"
    perspectiveBar="true" progressIndicator="true" >

    <toolBar>
      <toolItem text="選択時Enable" enablesDependingId="table"
        enablesFor="SELECTION" />
      <toolItem text="非選択時Enable" enablesDependingId="table"
        enablesFor="NONE" />
      <toolItem text="1つだけ選択時Enable" enablesDependingId="table"
        enablesFor="SINGLE" />
      <toolItem text="2つだけ選択時Enable" enablesDependingId="table"
        enablesFor="PAIR" />
      <toolItem text="2つ以上選択時Enable" enablesDependingId="table"
        enablesFor="MULTI" />
    </toolBar>
    
    <perspective id="defaultPerspective" name="RSS" fixed="false"
      icon="uruma">
      <part ref="feedTreeView" ratio="30" position="LEFT" />
      <part ref="feedListView" ratio="70" position="TOP" />
      <part ref="feedBrowserView" ratio="50" position="BOTTOM" />
    </perspective>

  </workbench>
</template>


実行するとエラーが。RCPだとToolBarのスキーマがうまく使えないようです。スタンドアロンならうまく読めてます。

スタンドアロンに影響がでるので、ヘタにスキーマに手が出せないですね。。。

SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'perspective'. One of '{"http://uruma.sandbox.seasar.org":compositeChild}' is expected.

まとめ

手詰まりw アプローチを変えてみよう。

Toolbarを表示したい その1

UrumaでToolbarを表示させたいけど、XMLスキーマ(uruma.xsd)には特にそれらしきものがないのでまだ対応してないみたい。

追記:すいません。スキーマにありました。

ということで、Toolbarを表示するためには、どうしたら良いかUrumaをHackしてみる。


まず、UrumaがXMLを解析してオブジェクトグラフを作成する仕組みを理解する。

  • TemplateManagerがXMLをロードする
  • TemplateManagerはComponentTreeBuilderによってXMLからTemplateオブジェクトを生成する
  • ComponentTreeBuilderはSAXでXMLを解析
  • TemplateオブジェクトはXMLの各ノードをUIComponent(抽象)として保持する
  • UIComponentはXMLアトリビュートと対応した変数名がありXMLの値を保持する
  • UIComponentは再帰構造でUIComponentを保持する
  • UIComponentはWindowComponentやToolbarComponentなど各実装がある


WindowComponentの中身抜粋。

/**
 * {@link Window} のコンポーネント情報を保持するためのクラスです。<br />
 * 
 * @author y-komori
 */
@ComponentElement
public class WindowComponent extends CompositeComponent {
    @RenderingPolicy(targetType = TargetType.NONE)
    @ComponentAttribute
    @FieldDescription("ウィンドウタイトル")
    public String title;

    @RenderingPolicy(targetType = TargetType.NONE)
    @ComponentAttribute
    @FieldDescription("最小幅")
    public String minimumWidth;

    @RenderingPolicy(targetType = TargetType.NONE)
    @ComponentAttribute
    @FieldDescription("最小高さ")
    public String minimumHeight;

    @RenderingPolicy(targetType = TargetType.NONE)
    @ComponentAttribute
    @FieldDescription("幅")
    public String width;
    
    ・・・


ふむふむ。
XMLに設定項目を追加したい場合は、uruma.xsdにエレメントやアトリビュートを追加して、対応するUIComponentを用意してあげれば、XMLの内容をオブジェクトで扱える。

まとめ

XMLの内容にアクセスしたい場合は、TemplateManager#getTemplage#getRootComponent でComponentを取得する。

Seasar Conference 2008

Seasar Conference 2008
http://lh3.ggpht.com/dumyaddress/SDbufzHRzPI/AAAAAAAAAHE/QtdNs4-QLUc/image%5B5%5D.png


Seasar Conference 2008のUrumaセクションで少し講演をさせて頂く事になりました。

現在開発中のアプリ「株専」のデモを行います。

事前資料はこちら。

前夜は緊張しますね(><)

[株専][Java][JRuby] JRubyのERBをJavaからテンプレートエンジンとして利用する

Rubyのテンプレートエンジンはいろいろあるようですが、標準ライブラリに同封されかつ
Railsのデフォルトのテンプレートエンジン ERB を試してみます。

JavaからバインディングしたいオブジェクトはString,List,Map,Beanと
なんでも渡せるので十分利用できそうです。

ただ、ひとつ問題が。

ERBは他のテンプレートファイルをインクルードできないようです。
Railsでは、ERBではなく、RailsのHelperで行っている様子。

テンプレートエンジンでインクルード機能がないとは。。。

Java側でインクルードしてERBに読ませることにします。

[株専][Java][Uruma][JRuby]JRubyを BSFで扱ってみる(その3)

JRubyもgemライブラリを使用して動作したので、次は、BSF経由で実行してみます。

以下のライブラリをビルドパスに追加します。

BSF利用コード

ポイントは、JRUBY_HOMEとJRUBY_LIBをSystemプロパティに登録すること。
登録しない場合、gemライブラリなどが見つかりません。

private static final String SCRIPT_ENGINE = "org.jruby.javasupport.bsf.JRubyEngine";

private static final String JRUBY = "jruby";

private static final String FILE_NAME = "(java)";

private static final int START_LINE = 1;

private static final int START_COLUMN = 1;

public static void main(String[] args) {

     System.setProperty("jruby.home", JRUBY_HOME);
     System.setProperty("jruby.lib", JRUBY_LIB);

     BSFManager.registerScriptingEngine(JRUBY, SCRIPT_ENGINE, new String[] { "rb" });

     String script = "require 'rubygems'\n" + "require 'hpricot'\n"
	+ "require 'open-uri'\n"
	+ "doc = Hpricot( open(\"http://www.kmc.gr.jp/\").read )\n"
	+ "(doc/:a).each do |link|\n"
	+ "  puts \"#{link.inner_html} → #{link[:href]}\"\n" + "end";

     manager.eval(JRUBY, FILE_NAME, START_LINE, START_COLUMN, script);
}

結果

KMChttp://www.kmc.gr.jp/
Top → http://www.kmc.gr.jp
Guidance → guidance.html
Project → project.html
Event → event.html
Members → members.html
Link → link.html
SitePolicy → misc.html
部員専用ページへ → https://www.kmc.gr.jp/
京大マイコンクラブ公式WEBhttp://www.kmc.gr.jp/
・・・

今度は文字化けしていないですね。


ただ、遅いんですよ。orz

再計測

スクリプトを以下に変更し計測しました。

script = "$out.println 'hello jruby!!'";

初期化処理は250ms で、eval処理はなんと 4141ms !!
hello jruby!!の出力だけなのでおそらくJRubyインスタンス化のオーバーヘッドでは??

と思い、以下のように複数回実行。

TimeWatchUtil.start("jruby2");
manager.eval(JRUBY, FILE_NAME, START_LINE, START_COLUMN, script);
long end = TimeWatchUtil.end("jruby2");
System.out.println(end + "ms");

TimeWatchUtil.start("jruby2");
manager.eval(JRUBY, FILE_NAME, START_LINE, START_COLUMN, script);
end = TimeWatchUtil.end("jruby2");
System.out.println(end + "ms");

TimeWatchUtil.start("jruby2");
manager.eval(JRUBY, FILE_NAME, START_LINE, START_COLUMN, script);
end = TimeWatchUtil.end("jruby2");
System.out.println(end + "ms");

TimeWatchUtil.start("jruby2");
manager.eval(JRUBY, FILE_NAME, START_LINE, START_COLUMN, script);
end = TimeWatchUtil.end("jruby2");
System.out.println(end + "ms");

結果

実行すると、以下のように取得できました。

初期化
250ms
hello jruby!!
4328ms
hello jruby!!
16ms
hello jruby!!
16ms
hello jruby!!
0ms

おぉ、一回目のevalのみ遅い!!

総論

gemのライブラリを含め、rubyjavaから扱えるようになりました。
スクレイピングやテンプレートエンジンとして利用すると便利そうです。
一回目のevalは遅いが2回目以降は十分に早いのでパフォーマンスも大丈夫でしょう。

[株専][Java][Uruma][JRuby]JRubyを BSFで扱ってみる(その2)

JRubyディレクトリ構造

主要そうなディレクトリのみ記載。

jruby
 + bin 
 + lib
   + bsf.jar
   + jruby.jar   
   + ruby   
          + 1.8 ← Rubyのデフォルトライブラリ
          + gems ← gemで追加したライブラリ
          + site_ruby ← 各ディストリビューション向け 
               JRubyJava関連もこの中
 + share ← ライブラリ

gem

Rubyには gem というライブラリ管理コマンドがあります。
例えるなら、PerlCPANLinux Rpmのapt、yumみたいなもの。

使い方の参考サイト。

HTML解析ライブラリのmechanizeをインストールしてみます。
mechanizeについては以下を参考。

インストール

$ gem install mechanize
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Updating metadata for 265 gems from http://gems.rubyforge.org
.........................................................................................................................................................................................................................................................................
complete
Successfully installed hpricot-0.6-java
Successfully installed rubyforge-0.4.5
Successfully installed hoe-1.5.1
Successfully installed mechanize-0.7.5
4 gems installed
Installing ri documentation for hpricot-0.6-java...
Installing ri documentation for rubyforge-0.4.5...
Installing ri documentation for hoe-1.5.1...
Installing ri documentation for mechanize-0.7.5...
Installing RDoc documentation for hpricot-0.6-java...
Installing RDoc documentation for rubyforge-0.4.5...
Installing RDoc documentation for hoe-1.5.1...
Installing RDoc documentation for mechanize-0.7.5...

テストソースコード

gemのライブラリを利用するため、一行目に require 'rubygems' を記載します。

$ cat ~/ruby/test.rb 
require 'rubygems'
require 'hpricot'
require 'open-uri'

doc = Hpricot( open("http://www.kmc.gr.jp/").read )

(doc/:a).each do |link|
  puts "#{link.inner_html}#{link[:href]}"
end

実行してみます。Errorになりますね。。。

結果

$ jruby ./test.rb 
Exception in thread "main" java.lang.NoSuchMethodError: org.jruby.runtime.builtin.IRubyObject.getInstanceVariable(Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;
        at HpricotScanService.hpricot_scan(HpricotScanService.java:931)
        at HpricotScanService.__hpricot_scan(HpricotScanService.java:1324)
        at HpricotScanServiceCallback$__hpricot_scan_S1.call(Unknown Source)
        at org.jruby.runtime.callback.InvocationCallback.execute(InvocationCallback.java:67)
        at org.jruby.internal.runtime.methods.FullFunctionCallbackMethod.call(FullFunctionCallbackMethod.java:69)
        at org.jruby.runtime.CallSite$InlineCachingCallSite.cacheAndCall(CallSite.java:87)

小一時間格闘の末、パッチがあることが判明。

JRubyベンチマーク

http://blog.gijutsuya.jp/harajune/2008/04/04/jruby%e3%83%99%e3%83%b3%e3%83%81%e3%83%9e%e3%83%bc%e3%82%af/
hpricotはgemで落としてきたのではエラーが出て動きません。パッチがあるらしくそれを当ててあるのが、ここのサイトから落とせます。mechanaizeでもhpricotを使っているのでこれは必須。

http://www.telscenter.org/confluence/download/attachments/20236/hpricot-0.6.159-java.gem

インストール

$ gem install --local hpricot
Successfully installed hpricot-0.6.159-java
1 gem installed
Installing ri documentation for hpricot-0.6.159-java...
Installing RDoc documentation for hpricot-0.6.159-java...

再度実行

$ jruby ./test.rb 
KMChttp://www.kmc.gr.jp/
Top → http://www.kmc.gr.jp
Guidance → guidance.html
Project → project.html
Event → event.html
Members → members.html
Link 竊’ link.html
SitePolicy 竊’ misc.html
部員専用ページへ 竊’ https://www.kmc.gr.jp/
京大マイコンクラブ公式WEB 竊’ http://www.kmc.gr.jp/
Guidance 竊’ guidance.html
Project 竊’ project.html
Event 竊’ event.html

おぉー うまく動きました。
でも、文字化けしてますね。。。。


あと、JRubyの立ち上げが遅い です。 3秒はかかってますね。