Eclipse Juno (4.2) のパフォーマンスを改善するパッチ

Eclipse Juno、使ってますか?おっそいですよね・・・
特にMavenのPOMファイルを開こうものなら、エディタ切り替えごとにツールバーが高速点滅したりして、まともに使えたもんじゃありません。というわけで、現行のEclipse Juno SR1 (4.2.1) のパフォーマンスを改善するパッチが公開されています。
Bug 394588 – Provide a feature patch for Juno SR1 Optimizations

Eclipseの更新サイトに登録されているので、Eclipseの「新規ソフトウェアのインストール」から適用できます。


エディタの切り替えなどは劇的に改善されるので、Junoを使っている場合は即入れましょう。
2月中くらいにリリースが予定されている SR2 (4.2.2) には、この改善も含まれているようです。早く出ないかな。

DBFluteで親テーブルをキャッシュから取得するサンプル

DBFlute-0.9.9.1B から、Entityの親テーブルがnullの場合に、代わりとなるインスタンスを返すことができるようになりました。この仕組みを使うことで、頻繁に結合されるテーブル(マスタなど)を、毎回DBアクセスせずにキャッシュから取得させることができます。DBFluteの設定方法とキャッシュの実装サンプルをGithubに上げたついでに、ちょっと解説します。

普通のDBFlute

普通のDBFluteで、関連テーブルも一緒に取得するには、ConditionBeanのSetupSelectを使います。こんな感じですね。

MemberCB cb = new MemberCB();
cb.setupSelect_MemberStatus();
cb.query.setMemberId_Equal(1);
Member member = memberBhv.selectEntity(cb);

こうすることで、member.getMemberStatus() で MemberStatus インスタンスを取得できます。cb.setupSelect_MemberStatus() を呼び出さなかった場合、member.getMemberStatus() はnullを返します。

relationalNullObjectMap の設定

member.getMemberStatus() がnullを返すとき、代わりにキャッシュからインスタンスを取得させるようにします。それには、littleAdjustmentMap.dfprop の relationalNullObjectMap を設定します。該当するコミットはこちら

; relationalNullObjectMap = map:{
    ; providerPackage = com.github.taktos.dbflute.cache
    ; foreignMap = map:{
        ; MEMBER_STATUS = MemberStatusCache.get($$PrimaryKey$$)
    }
}

foreignMap の MEMBER_STATUS は、テーブル名です。MEMBER_STATUSへの外部キーを持つテーブルのEntityすべてに設定が効きます。MemberStatusCache.get($$PrimaryKey$$) が、関連テーブルがnullのとき代わりに実行されるコードになります。providerPackage はimport文に追加されます(多分)。ので、MemberStatusCacheをFQDNで書いたら不要(多分)。


設定を追加してDBFluteでコード生成しなおすと、BsEntityの関連テーブル取得メソッドが以下のように変わります。

 public MemberStatus getMemberStatus() {
+    if (_memberStatus == null) {
+        _memberStatus = MemberStatusCache.get(getMemberStatusCode());
+    }
     return _memberStatus;
 }

MEMBER_STATUSテーブルのインスタンスがnullかチェックし、nullの場合は代わりのコードを実行するようになりました。

なお、キャッシュの仕組みは自前で用意する必要がありますので、都合に応じて作ってください。(Githubに上げたサンプルは、staticイニシャライザでキャッシュしたインスタンスを返す簡単な実装しかしていません。)

Cygwinでgitkを実行するのにX serverが必要になった

Cygwinでパッケージ追加しようと思って久しぶりにsetup.exeを実行したところ、正常に完了せずにエラーがでてしまった。Terminalどころかcmdでのashも無反応になってしまったので、仕方なく http://cygwin.com から最新のsetup.exeをダウンロードして再実行。今度はうまくいって、Terminal上げて何気に gitk を打つと、下のエラーを吐いて上がらない。

$ gitk
Application initialization failed: no display name and no $DISPLAY environment variable
Error in startup script: no display name and no $DISPLAY environment variable
    while executing
"load /usr/lib/tk8.5/../../bin/libtk8.5.dll Tk"
    ("package ifneeded Tk 8.5.11" script)
    invoked from within
"package require Tk"
    (file "/usr/bin/gitk" line 10)

調べてみると、Cygwinに含まれるTcl/Tkがつい最近更新され、GDKに代わりX11に依存するようになったとのこと。

仕方ないのでsetup.exeから xinit と xorg-server を追加。gitkを実行する前に startxcmd でX serverを上げておき、

$ DISPLAY=localhost:0 gitk

で無事起動・・・しない。今度は

Error in startup script: unknown color name "SystemButtonFace"
    while executing
"winfo rgb . $c"
    (procedure "setui" line 3)
    invoked from within
"setui $uicolor"
    (file "/usr/bin/gitk" line 11522)

と言われてしまった。どうも古い ~/.gitk があるとまずい様子。どうせ大したこと書いてないのでさくっと消して、再度gitkで無事起動!

gmaven-plugin 1.3 の generateStubs に sourceEncoding を効かせるパッチを書いた

Mavengmaven-plugin 1.3 で providerSelection に 1.7 を指定している場合、マルチバイト文字列のあるGroovyファイルで generateStubs ゴールが失敗する問題がある。GMaven の JIRA には GMAVEN-85 で上がってるのでそのうち直りそうだけど、とりあえず版でパッチを書いた。
https://svn.codehaus.org/gmaven/trunk から全部チェックアウトして、パッチ当てて、mvn install で使えるようになるはず。

Index: gmaven-plugin/src/main/java/org/codehaus/gmaven/plugin/stubgen/AbstractGenerateStubsMojo.java
===================================================================
--- gmaven-plugin/src/main/java/org/codehaus/gmaven/plugin/stubgen/AbstractGenerateStubsMojo.java	(リビジョン 123)
+++ gmaven-plugin/src/main/java/org/codehaus/gmaven/plugin/stubgen/AbstractGenerateStubsMojo.java	(作業コピー)
@@ -22,7 +22,9 @@
 import org.apache.maven.shared.io.scan.mapping.SuffixMapping;
 import org.apache.maven.shared.model.fileset.FileSet;
 import org.codehaus.gmaven.feature.Component;
+import org.codehaus.gmaven.feature.Configuration;
 import org.codehaus.gmaven.plugin.CompilerMojoSupport;
+import org.codehaus.gmaven.runtime.ClassCompiler;
 import org.codehaus.gmaven.runtime.StubCompiler;
 
 import java.io.File;
@@ -51,11 +53,21 @@
  */
 public abstract class AbstractGenerateStubsMojo
     extends CompilerMojoSupport
+    implements ClassCompiler.Keys
 {
     protected AbstractGenerateStubsMojo() {
         super(StubCompiler.KEY);
     }
     
+    /**
+     * Sets the encoding to be used when reading source files.
+     *
+     * @parameter expression="${sourceEncoding}" default-value="${project.build.sourceEncoding}"
+     *
+     * @noinspection UnusedDeclaration
+     */
+    private String sourceEncoding;
+
     public void execute() throws MojoExecutionException, MojoFailureException {
         super.execute();
 
@@ -128,6 +140,11 @@
         // TODO: Bridge mojo config to component config
         //
 
+        Configuration config = component.config();
+
+        if (sourceEncoding != null) {
+        	config.set(SOURCE_ENCODING, sourceEncoding);
+        }
         compile(compiler, sources != null ? sources : getDefaultSources());
     }
 
Index: gmaven-runtime/gmaven-runtime-1.7/src/main/java/org/codehaus/gmaven/runtime/v1_7/StubCompilerFeature.java
===================================================================
--- gmaven-runtime/gmaven-runtime-1.7/src/main/java/org/codehaus/gmaven/runtime/v1_7/StubCompilerFeature.java	(リビジョン 123)
+++ gmaven-runtime/gmaven-runtime-1.7/src/main/java/org/codehaus/gmaven/runtime/v1_7/StubCompilerFeature.java	(作業コピー)
@@ -19,6 +19,7 @@
 import groovy.lang.GroovyClassLoader;
 import org.codehaus.gmaven.feature.Component;
 import org.codehaus.gmaven.feature.support.FeatureSupport;
+import org.codehaus.gmaven.runtime.ClassCompiler;
 import org.codehaus.gmaven.runtime.StubCompiler;
 import org.codehaus.gmaven.runtime.support.CompilerSupport;
 import org.codehaus.groovy.control.CompilerConfiguration;
@@ -74,6 +75,7 @@
             Map<String,Object> options = new HashMap<String,Object>();
             options.put("stubDir", getTargetDirectory());
             cc.setJointCompilationOptions(options);
+            cc.setSourceEncoding((String) config().get(ClassCompiler.Keys.SOURCE_ENCODING));
             ClassLoader parent = ClassLoader.getSystemClassLoader();
 
             GroovyClassLoader gcl = new GroovyClassLoader(parent, cc);

利用する場合のPOMはこんな感じで。

<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.gmaven</groupId>
      <artifactId>gmaven-plugin</artifactId>
      <version>1.4-SNAPSHOT</version>
      <configuration>
        <providerSelection>1.7</providerSelection>
        <sourceEncoding>UTF-8</sourceEncoding>
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>generateStubs</goal>
            <goal>compile</goal>
            <goal>generateTestStubs</goal>
            <goal>testCompile</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
</build>

codenarc-maven-pluginをmvn siteで使えるようにするパッチ

GroovyのコーディングスタイルをチェックするCodeNarcには、Mavenプラグインが用意されてはいるのだけど、mvn siteから実行させようとすると無限ループに陥ってしまう。
仕方ないから codenarc-maven-plugin 0.8-alpha-SNAPSHOT に対するパッチを書いた。
http://svn.codehaus.org/mojo/trunk/sandbox/codenarc-maven-plugin/ ここからチェックアウトして、パッチ当てて、mvn installして使って下さい。
pom.xmlのほうは、CodeNarcのバージョンを上げたついでにMaven 3.0でも動くように修正した(はず)。

Index: pom.xml
===================================================================
--- pom.xml	(revision 13777)
+++ pom.xml	(working copy)
@@ -12,7 +12,7 @@
   <groupId>org.codehaus.mojo</groupId>
 -->
   <artifactId>codenarc-maven-plugin</artifactId>
-  <version>0.8-alpha-SNAPSHOT</version>
+  <version>0.8-beta-SNAPSHOT</version>
   <packaging>maven-plugin</packaging>
 
   <name>CodeNarc Maven Plugin</name>
@@ -56,35 +56,19 @@
   </issueManagement>
 
   <properties>
-    <groovy.plugin.version>1.0-rc-3</groovy.plugin.version>
+    <gmaven.version>1.2</gmaven.version>
   </properties>
 
   <dependencies>
     <dependency>
       <groupId>org.apache.maven.reporting</groupId>
       <artifactId>maven-reporting-impl</artifactId>
-      <version>2.0</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.reporting</groupId>
-      <artifactId>maven-reporting-api</artifactId>
-      <version>2.0.8</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.shared</groupId>
-      <artifactId>maven-doxia-tools</artifactId>
-      <version>1.0</version>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>3.8.1</version>
-      <scope>test</scope>
+      <version>2.1</version>
     </dependency>
     <dependency>
       <groupId>org.codenarc</groupId>
       <artifactId>CodeNarc</artifactId>
-      <version>0.8.1</version>
+      <version>0.13</version>
       <exclusions>
         <exclusion>
           <groupId>ant</groupId>
@@ -93,21 +77,6 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>log4j</groupId>
-      <artifactId>log4j</artifactId>
-      <version>1.2.14</version>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.groovy.maven</groupId>
-      <artifactId>gmaven-mojo</artifactId>
-      <version>1.0-rc-4</version>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.groovy.maven</groupId>
-      <artifactId>gmaven-mojo</artifactId>
-      <version>${groovy.plugin.version}</version>
-    </dependency>
-    <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-resources</artifactId>
       <version>1.0-alpha-4</version>
@@ -128,22 +97,20 @@
           <version>2.5</version>
         </plugin>
         <plugin>
-          <groupId>org.codehaus.mojo</groupId>
-          <artifactId>shitty-maven-plugin</artifactId>
-          <version>1.0-alpha-3</version>
-        </plugin>
-        <plugin>
-          <groupId>org.codehaus.groovy.maven</groupId>
+          <groupId>org.codehaus.gmaven</groupId>
           <artifactId>gmaven-plugin</artifactId>
-          <version>${groovy.plugin.version}</version>
+          <version>${gmaven.version}</version>
         </plugin>
       </plugins>
     </pluginManagement>
     <plugins>
       <plugin>
-        <groupId>org.codehaus.groovy.maven</groupId>
+        <groupId>org.codehaus.gmaven</groupId>
         <artifactId>gmaven-plugin</artifactId>
-        <version>${groovy.plugin.version}</version>
+        <configuration>
+          <providerSelection>1.6</providerSelection>
+          <sourceEncoding>UTF-8</sourceEncoding>
+        </configuration>
         <executions>
           <execution>
             <goals>
Index: src/main/groovy/org/codehaus/mojo/codenarc/CodeNarcMojo.groovy
===================================================================
--- src/main/groovy/org/codehaus/mojo/codenarc/CodeNarcMojo.groovy	(revision 13777)
+++ src/main/groovy/org/codehaus/mojo/codenarc/CodeNarcMojo.groovy	(working copy)
@@ -21,8 +21,7 @@
 
 import org.apache.maven.reporting.AbstractMavenReport
 import org.apache.maven.project.MavenProject
-import org.codehaus.doxia.site.renderer.SiteRenderer;
-import org.apache.maven.doxia.tools.SiteTool
+import org.apache.maven.doxia.siterenderer.Renderer
 import org.codehaus.plexus.resource.ResourceManager
 import org.codehaus.plexus.resource.loader.FileResourceLoader
 
@@ -30,10 +29,9 @@
  * Create a CodeNarc Report.
  *
  * @goal codenarc
- * @execute phase="site"
  * @requiresDependencyResolution compile
  * @requiresProject
- * 
+ *
  * @author <a href="mailto:gleclaire@codehaus.org">Garvin LeClaire</a>
  * @version $Id: CodeNarcMojo.groovy gleclaire $
  */
@@ -76,7 +74,7 @@
      * @readonly
      */
     MavenProject project
-  
+
     /**
      * Location where generated html will be created.
      *
@@ -101,16 +99,7 @@
      * @required
      * @readonly
      */
-    SiteRenderer siteRenderer
-
-    /**
-     * SiteTool.
-     *
-     * @component role="org.apache.maven.doxia.tools.SiteTool"
-     * @required
-     * @readonly
-     */
-    protected SiteTool siteTool
+    Renderer siteRenderer
 
     /**
      * @component
@@ -216,7 +205,7 @@
         if (outputFile.exists()) {
             log.info("Generating CodeNarc HTML")
 
-            CodeNarcReportGenerator generator = new CodeNarcReportGenerator( getSink(), getBundle(locale), this.project.getBasedir(), siteTool)
+            CodeNarcReportGenerator generator = new CodeNarcReportGenerator( getSink(), getBundle(locale), this.project.getBasedir())
 
             generator.setLog(log)
 
@@ -304,7 +293,7 @@
         return outputDirectory.getAbsolutePath()
     }
 
-    protected SiteRenderer getSiteRenderer() {
+    protected Renderer getSiteRenderer() {
         return this.siteRenderer
     }
 
Index: src/main/groovy/org/codehaus/mojo/codenarc/CodeNarcReportGenerator.groovy
===================================================================
--- src/main/groovy/org/codehaus/mojo/codenarc/CodeNarcReportGenerator.groovy	(revision 13777)
+++ src/main/groovy/org/codehaus/mojo/codenarc/CodeNarcReportGenerator.groovy	(working copy)
@@ -21,12 +21,11 @@
 
 import groovy.util.slurpersupport.GPathResult
 import org.apache.maven.doxia.sink.Sink
-import org.apache.maven.doxia.tools.SiteTool
 import org.apache.maven.plugin.logging.Log
 
 /**
  * The reporter controls the generation of the CodeNarc report.
- * 
+ *
  * @author <a href="mailto:gleclaire@codehaus.org">Garvin LeClaire</a>
  * @version $Id: CodeNarcReportGenerator.groovy Z gleclaire $
  */
@@ -209,14 +208,6 @@
     File outputDirectory
 
 
-    /**
-     * "org.apache.maven.doxia.tools.SiteTool"
-     *
-     */
-    SiteTool siteTool
-
-
-
     File basedir
 
     GPathResult CodeNarcResults
@@ -231,21 +222,17 @@
      *            The resource bundle to get the messages from.
      * @param basedir
      *            The project base directory.
-     * @param siteTool
-     *            Doxia SiteTool Handle.
      */
-    CodeNarcReportGenerator(Sink sink, ResourceBundle bundle, File basedir, SiteTool siteTool) {
+    CodeNarcReportGenerator(Sink sink, ResourceBundle bundle, File basedir) {
 
 
         assert sink
         assert bundle
         assert basedir
-        assert siteTool
 
         this.sink = sink
         this.bundle = bundle
         this.basedir = basedir
-        this.siteTool = siteTool
 
 
 
@@ -475,7 +462,7 @@
         sink.section1_()
     }
 
- 
+
     /**
      * Print the File Detail Section.
      */
@@ -618,7 +605,7 @@
         }
 
 
- 
+
         sink.table_()
 
         sink.section1_()

Windowsのコマンドプロンプトを使いやすく(Linuxに近付ける的な意味で)

普段からWindowsとそれ以外のOSを使っていると、コマンドプロンプトを使ったときに思わず「ls」って打っちゃいますよね?コマンドプロンプトを複数上げてると、どの窓がどれだったか分からなくなりますよね?cygwinを入れたり、GnuWin32 を入れたりすれば、「ls」問題は解決するのですが、日本語がうまく表示できなかったりして何かと面倒です。そこで doskey を使って、コマンドのエイリアスを設定してみましょう。また、Linuxにおける「.bashrc」のようなことをWindowsでやる方法も紹介します。

doskeyの使い方

doskeyは「alias」のような「マクロの作成」という機能があります。詳しい使い方やその他の機能は、コマンドプロンプトを起動して「doskey /?」で確認してください。

とりあえずここでは、以下のような内容を持つテキストファイルを「macro.txt」という名前で用意してみます。

ls=dir /d /og $*
ll=dir /od $*
cp=copy $*
mv=move $*
pwd=cd $*

コマンドプロンプトを開き、上記のファイルをdoskeyで読み込みます。

 > doskey /macrofile=macro.txt

すると、まあ、なんということでしょう!「ls」でファイル一覧が表示されるじゃありませんか!!これだけでも結構嬉しかったりしますが、doskeyで定義するマクロの内容には、上記のような単純なコマンドだけでなく、自分で用意したバッチファイルを指定することもできます。これを使って、「cdでディレクトリを移動したら、カレントディレクトリのパスをコマンドプロンプトのタイトルに表示する」マクロを定義してみましょう。

カレントディレクトリ名をコマンドプロンプトのタイトルに表示させる

コマンドプロンプトのタイトル変更には「title」コマンドを使用します。また、カレントディレクトリは「%CD%」という変数で参照できるので、以下のコマンドによりカレントディレクトリのパス名をコマンドプロンプトのタイトルに設定できます。

 > title %CD%

では、まずcdの後にタイトルを変更するバッチを作りましょう。

@echo off
if %1. == . cd /d %HOMEDRIVE%%HOMEPATH% && goto end
cd /d %1
:end
title %CD%

基本は「cd %1」と「title %CD%」だけあればよいのですが、ここでは「引数なしならホームに移動する」「常にドライブも変更する」ようにしてあります。このバッチを適当な名前で保存して(ここではホームディレクトリ直下の mycd.bat とします)、doskeyコマンドでcdに割り当てます。

 > doskey cd="%HOMEDRIVE%%HOMEPATH%\mycd.bat" $*

さあ、cd でどこかに移動してみましょう!コマンドプロンプトのタイトルは、どこに行こうともそのパスを表示してくれます!

コマンドプロンプト起動時にマクロを読み込む

ここまでの作業の結果、「作業を行ったコマンドプロンプトでは」doskeyが効いています。が、新しいコマンドプロンプトを立ち上げると、cdしてもタイトルが変わらないし、lsはコマンドとして認識されません。doskeyはそのコマンドプロンプトにしか効かないんですね。だからといって、コマンドプロンプトを立ち上げるたびに「doskey /macrofile=macro.txt」とかやってられません。そこで、コマンドプロンプトの起動時に、自動でマクロを読み込ませるよう設定しましょう。Linuxで言うところの「.bashrc」みたいな感じですね。

cmd.exeのヘルプ(「cmd /?」で表示できます)を見ると、以下のような記述が見つかります。

コマンド ラインで /D が指定されなかった場合は、CMD.EXE の開始時に次の REG_SZ
または REG_EXPAND_SZ レジストリ変数が検索されます。次のレジストリ変数の両方ま
たはどちらかが存在する場合、それらを最初に実行します。

    HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun

    HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun

ようは、立ち上げ時に上記レジストリで指定されたコマンドを実行するよ、って事なので、実行させるバッチファイルを用意します。

@title %CD%
@doskey /macrofile="%HOMEDRIVE%%HOMEPATH%\macro.txt"
@doskey cd="%HOMEDRIVE%%HOMEPATH%\mycd.bat" $*

これを「cmdrc.bat」など適当な名前で保存したら、レジストリを編集します。HKLMかHKCUで上記レジストリをたどり、Command Processor で右クリックして「新規」から「文字列値」を作成します。「名前」には「AutoRun」、「値のデータ」には上で作成したバッチファイルを「"%HOMEDRIVE%%HOMEPATH%\cmdrc.bat"」のように指定します。レジストリを設定したら、コマンドプロンプトを起動してみましょう。これまで設定してきたマクロが自動で読み込まれ、最初から「ls」が使えるようになりましたね!


AutoRunで実行するバッチには、エイリアスの設定以外にも、PATHの設定やプロンプトの変更といった使い道が考えられます。お好みに合わせて、色々いじってみてください。これでもう「えーっと今Windowsだからdir・・・」とか、「タイトルが同じコマンドプロンプトが何枚もあってどれがどれだか分からない」といった悩みとはさよならです!

ea2xmi-0.0.3をリリースしました

Enterprise Architect からXMI形式でパッケージ情報を出力するWin32コンソールアプリケーションである ea2xmi のバージョン0.0.3をリリースしました。ダウンロードは下記のサイトからどうぞ。

XMIファイルの出力は Enterprise Architect の機能を外から呼び出しているだけなので、動作には Enterprise Architect 本体がインストールされていることが必要です。

用途としては、Hudson等のCIで、最新の*.eapからXMIファイルを出力して、それを元に自動でDDLを作ってDBを作り直してからUnitTestを流すとか、そんなところです。
DBFlute の classificationResource.dfprop 用にXMIファイルを出力したい、でもいちいちEAを起動するのがめんどくさい、そんなところにも使えると思います。

使い方

Enterprise Architect がインストールされた環境にて、下記のコマンドで実行します。

ea2xmi.exe [in.eap] [SearchPath] [out.xml]
    [in.eap]      対象とする*.eapファイル
    [SearchPath]  XMIファイルに出力するパッケージのパス
    [out.xml]     出力先ファイル名(フルパスで指定)

パッケージのパスとは、ルートパッケージから出力対象パッケージまでの事を指します。ルートパッケージ名は指定不要で、階層の区切りは"/"(半角スラッシュ)を使用します。
例えば、下記のようなパッケージ構成になっていて、「ER図」以下の「FOO」のみ対象とする場合、SearchPath には "ER図/FOO" と指定します。

  • プロジェクトルート