Prev / Next / たまにっき。

Maven2 native2ascii plugin

Category: [Java][Maven2][Tips]
2006-09-11

Maven2 で native2ascii コマンドを実行するプラグイン.

    <plugins>
      <plugin>
        <groupId>com.jakubpawlowicz.maven.plugins</groupId>
        <artifactId>maven-ant-plugins</artifactId>
        <executions>
          <execution>
            <phase>compile</phase>
            <goals>
              <goal>native2ascii</goal>
            </goals>
            <configuration>
              <encoding>shift_jis</encoding>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>


みたいなのを pom.xml に追加すれば native2ascii がかけられる.ただし,tools.jar にクラスパスを通しておく必要がある.

困った点
- filter を見事に無視してくれる.
- 拡張子が properties なものが全て対象になるようだ.

filter が無視されるのはイタイ.properties ファイル中に ${pom.version}とか ${pom.artifactId} などを参照することが多いと思うんだが.これさえ OK ならある拡張子を全て処理の対象になっても良いんだがなぁ.ただし,拡張子が properties 決めうちはイマイチだ.

ついカッとなって作ってしまった.拡張子についてはまだ未対応だけど,まぁ,よしなに.ライセンスは 無償・無保証・著作権放棄 です.


まずは maven-resources-plugin をチェックアウトする.

svn co https://svn.apache.org/repos/asf/maven/plugins/tags/maven-resources-plugin-2.2



で,以下の Native2AsciiWriter を適当な場所に置く.置く場所により package 名は変更する必要がある.以下のコードでは ResourcesMojo.java と同じ場所に置いている.

package org.apache.maven.plugin.resources;

import java.io.FilterWriter;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.io.*;

/**
 * FilterWriter for `native2ascii' command.
 *
 * @author Haruaki TAMADA
 * @version 1.0   2006/09/11
 */
public class Native2AsciiWriter extends FilterWriter{
    /**
     * constructor
     */
    public Native2AsciiWriter(Writer out){
        super(out);
    }

    /**
     * write encoded code (exclude ASCII code)
     */
    public void write(char[] data, int offset, int length) throws IOException{
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < length; i++){
            int value = (int)data[i + offset];

            if(value <= 0xff && (value & 0x80) == 0){
                sb.append(data[i + offset]);
            }
            else{
                sb.append("\\u");
                String characterCodeString = Integer.toString(value & 0xffffffff, 16);
                for(int j = characterCodeString.length(); j < 4; j++){
                    sb.append("0");
                }
                sb.append(characterCodeString);
            }
        }
        out.write(new String(sb).toCharArray());
    }
}



次に,チェックアウトした maven-resources-plugin-2.2 に以下のパッチを当てる.

Index: src/test/java/org/apache/maven/plugin/resources/ResourcesMojoTest.java
===================================================================
--- src/test/java/org/apache/maven/plugin/resources/ResourcesMojoTest.java      (revision 442118)
+++ src/test/java/org/apache/maven/plugin/resources/ResourcesMojoTest.java      (working copy)
@@ -418,6 +418,41 @@
         assertTrue( fileContains( resourcesDir + "/file4.properties", checkString ) );
     }

+    /**
+     * @throws Exception
+     */
+    public void testPropertyFiles_FilteringAndNative2Ascii()
+        throws Exception
+    {
+        File testPom = new File( getBasedir(), defaultPomFilePath );
+        ResourcesMojo mojo = (ResourcesMojo) lookupMojo( "resources", testPom );
+        MavenProjectResourcesStub project = new MavenProjectResourcesStub( "resourcePropertyFiles_FilteringAndNative2Ascii" );
+        List resources = project.getBuild().getResources();
+        LinkedList filterList = new LinkedList();
+
+        assertNotNull( mojo );
+
+        project.addFile( "file4.properties", "current working directory=${dir}" );
+        project.addFile( "filter.properties", "dir:testdir" );
+        project.setResourceFiltering( 0, true );
+        project.setupBuildEnvironment();
+        filterList.add( project.getResourcesDirectory() + "filter.properties" );
+
+        //setVariableValueToObject(mojo,"encoding","UTF-8");
+        setVariableValueToObject( mojo, "native2ascii", Boolean.TRUE );
+        setVariableValueToObject( mojo, "project", project );
+        setVariableValueToObject( mojo, "resources", resources );
+        setVariableValueToObject( mojo, "outputDirectory", project.getBuild().getOutputDirectory() );
+        setVariableValueToObject( mojo, "filters", filterList );
+        mojo.execute();
+
+        String resourcesDir = project.getOutputDirectory();
+        String checkString = "current working directory=testdir";
+
+        assertTrue( FileUtils.fileExists( resourcesDir + "/file4.properties" ) );
+        assertTrue( fileContains( resourcesDir + "/file4.properties", checkString ) );
+    }
+
     // reads the first line of the file and compares it
     // with data. returns true if equal
     private boolean fileContains( String fileName, String data )
Index: src/main/java/org/apache/maven/plugin/resources/ResourcesMojo.java
===================================================================
--- src/main/java/org/apache/maven/plugin/resources/ResourcesMojo.java  (revision 442118)
+++ src/main/java/org/apache/maven/plugin/resources/ResourcesMojo.java  (working copy)
@@ -77,6 +77,13 @@
     private List resources;

     /**
+     *
+     *
+     * @parameter
+     */
+    private boolean native2ascii;
+
+    /**
      * @parameter expression="${project}"
      * @required
      * @readonly
@@ -250,6 +257,9 @@

                     fileWriter = new OutputStreamWriter( outstream, encoding );
                 }
+                if(native2ascii){
+                    fileWriter = new Native2AsciiWriter(fileWriter);
+                }

                 // support ${token}
                 Reader reader = new InterpolationFilterReader( fileReader, filterProperties, "${","}" );


ユニットテストは別に追加せんでもええけど.これで mvn install してローカルリポジトリに maven-resources-plugin を登録する.

次に,native2ascii をかけたいプロジェクトの pom.xml を編集.

  <build>
    <plugins>
        :
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <configuration>
          <native2ascii>true</native2ascii>
        </configuration>
      </plugin>
        :
    </plugins>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>


これで mvn package を実行すると src/main/resources 以下のファイルがフィルタリングされつつ native2ascii もかけられる.

ただ,native2ascii とか言っているけど,内部では全く native2ascii を呼んでいない.なので,tools.jar にクラスパスを通す必要もない.その代わりどんな場合でも動くかどうかはわかんない.
native2ascii は要するに utf-8 のコードを全て ascii コードの数値で表しているだけなので,char 型を int 型に変換すれば同じことだと思う.要するに,「あ」は utf-8 コードでは 0x3042 なのだが,これを native2ascii にかけると "\u3042" という 6 文字になる.これで大丈夫だと思う.んでもって,ascii コードに含まれる文字列(0x00〜0x7f)だけ処理を行わないようにすればいいかなぁ,なんて.ASCII コードと utf-8 の ASCII コードに相当する部分は同じコード体系だったと思うし,ASCII コードまでエンコードされたんじゃ見にくいし.

Category: [Java][Maven2][Tips]