2015-11-23

Nashornでletとconstを使う

1. Nashornのバージョンを確認する

>echo "quit();" | jjs -version
nashorn 1.8.0_66
jjs> quit();
jjs>
>

2. 実行するスクリプト(LetAndConst.js):

try {
    const CONST_VALUE = 100;
    print("CONST_VALUE=${CONST_VALUE}");
    try {
        CONST_VALUE = 200;
    } catch (e) {
        print(e);
    }
    let letValue = CONST_VALUE + 1;
    print("letValue=${letValue}");
    var varValue = letValue + 1;
    print("varValue=${varValue}");
} finally {
    print("typeof CONST_VALUE: " + typeof CONST_VALUE);
    print("typeof letValue: " + typeof letValue);
    print("typeof varValue: " + typeof varValue);
}

3. jjsで実行する(--language=es6オプションが無いので文法エラーが起きた):

>jjs -scripting -fullversion LetAndConst.js
nashorn full version 1.8.0_66-b18
LetAndConst.js:2:1 Expected an operand but found const
    const CONST_VALUE = 100;
    ^
LetAndConst.js:9:5 Expected ; but found letValue
    let letValue = CONST_VALUE + 1;
        ^
LetAndConst.js:13:0 Expected eof but found }
} finally {
^

4. jjsで実行する(--language=es6オプションが有るので実行された):

>jjs -scripting -fullversion --language=es6 LetAndConst.js
nashorn full version 1.8.0_66-b18
CONST_VALUE=100
TypeError: Assignment to constant "CONST_VALUE"
letValue=101
varValue=102
typeof CONST_VALUE: undefined
typeof letValue: undefined
typeof varValue: number

NashornでFileVisitorを使って再帰的に同じ拡張子のファイルを収集する

1. ファイルを収集する対象のディレクトリ構造

./
  article-result.html
  article.html
  FileVisitorTest.js
  dir1/
    test1.txt
  dir2/
    test2.js

2. 実行するスクリプト(FileVisitorTest.js):

var Files = Java.type("java.nio.file.Files");
var Paths = Java.type("java.nio.file.Paths");
var FileVisitResult = Java.type("java.nio.file.FileVisitResult");
var SimpleFileVisitor = Java.type("java.nio.file.SimpleFileVisitor");
var ArrayList = Java.type("java.util.ArrayList");

function getPathListByPredicate(rootDir, predicateFunc) {
    var SimpleFileVisitorExtender = Java.extend(SimpleFileVisitor);
    var pathList = new ArrayList();
    var visitor = new SimpleFileVisitorExtender() {
        visitFile: function(path, attrs) {
            if (predicateFunc(path, attrs)) {
                pathList.add(path);
            }
            return FileVisitResult.CONTINUE;
        }
    };
    Files.walkFileTree(Paths.get(rootDir), visitor);
    return pathList;
}

var rootDir = Paths.get(".");

// List all files
var allFiles = getPathListByPredicate(rootDir, function(path, attrs) {
    return true;
});
print("allFiles=${allFiles}");

// List .js files
var jsFiles = getPathListByPredicate(rootDir, function(path, attrs) {
    return path.getFileName().toString().toLowerCase().endsWith(".js");
});
print("jsFiles=${jsFiles}");

3. jjsで実行する:

>jjs -scripting -fullversion FileVisitorTest.js
nashorn full version 1.8.0_66-b18
allFiles=[.\article-result.html, .\article.html, .\dir1\test1.txt, .\dir2\test2.js, .\FileVisitorTest.js]
jsFiles=[.\dir2\test2.js, .\FileVisitorTest.js]

Java8のjrunscriptでshowdown.js 1.3.0を使ってみる

過去に「Java6のjrunscriptでshowdown.jsを使ってみる」で書いたことをJava8で試してみる。

まず、input.txtに以下のように書いておく。

Markdown *rocks*.

showdown.js 1.3.0のzipをダウンロードして展開し、コマンドプロンプト(Windowsの場合)でshowdown.jsのあるディレクトリに移動した後、以下の1行を入力する。ちなみに、showdown.jsはconsole.logメソッドを使用するがNashornは提供していないので、最初の-eオプションで代わりのconsoleオブジェクトを作成する必要がある。

jrunscript -e "var console={log:function(s){print(s);}};" -f showdown.js -e "print('\n'+new showdown.Converter().makeHtml(read(new java.lang.StringBuilder(),true)));" < input.txt

すると以下のHTMLが出力される。1行目はread関数の第1引数で指定したプロンプト(空の行)、2行目からがshowdown.jsの出力。

(空の行)
<p>Markdown <em>rocks</em>.</p>

ちなみに、上記においてread関数の第1引数にnew StringBuilder()を渡しているのは、read関数が入力ファイルの行数と同じ数だけプロンプトを出力するのを見せないための醜いやり方なので、read関数ではなく入力ファイルの内容をStringに変える短い関数を自作した方が良いと思う。

--
showdown.jsは、以下のGitHubからダウンロード可能:
showdownjs/showdown · GitHub
https://github.com/showdownjs/showdown

Javaでshowdown.jsを使う方法は、以下の記事を参考にさせていただきました:
Markdown記法をJavaで扱いたい...Scripting for the Java と showdownを組み合わせる - Object Design
http://osima.jp/blog/showdown-on-java.html

2015-11-01

Twiccaのツイート表示アクションでプラグインに渡されるIntentのExtraの例

a. Twiccaのツイート表示アクションについて

ツイート表示アクション | Developers | twicca - Yet another Twitter client for Android.

b. Twiccaで開くツイートの例

Finding new worlds with a play of light & shadow can tell us about systems like our own: http://go.nasa.gov/1Q0aJF9 - Twitter / NASA

c. bに対してTwiccaのツイート表示アクションが発生した時にプラグインに渡されるIntentのExtra

android.intent.extra.TEXT=Finding new worlds with a play of light & shadow can tell us about systems like our own: https://t.co/zX0YzJuhnX https://t.co/LB6f55po2W
id=660176856839245824
latitude=null
longitude=null
created_at=1446233402953
source=Sprinklr
in_reply_to_status_id=null
user_screen_name=NASA
user_name=NASA
user_id=null
user_profile_image_url=http://pbs.twimg.com/profile_images/188302352/nasalogo_twitter.jpg
user_profile_image_url_mini=http://pbs.twimg.com/profile_images/188302352/nasalogo_twitter_mini.jpg
user_profile_image_url_normal=http://pbs.twimg.com/profile_images/188302352/nasalogo_twitter_normal.jpg
user_profile_image_url_bigger=http://pbs.twimg.com/profile_images/188302352/nasalogo_twitter_bigger.jpg

d. cを見た結果、ツイート表示アクションを使うプラグインを作成する際に注意すべきこと

  1. 短縮URLの展開やハッシュタグの抽出をしたい場合、プラグイン側がツイート本文の解析処理を実装する必要がある。
  2. 特に短縮URLは https://t.co/{7つの数字または文字} という形式なので、展開してみないとリソースの種類(添付画像、外部サイト等)すら判断できない。
  3. 添付画像の短縮URLは https://twitter.com/{user_screen_name}/status/{id}/photo/1 の単一ツイート表示ページに転送される。この点だけで判断すると、ツイート本文から添付画像の実際のURLを抽出したい場合は、短縮URLの展開に加えて /photo/1 で終わるURLのWebページ(か、単一ツイートの表示ページ)から目的の画像のファイル名を見つけ出す処理が必要となる。
  4. ツイート自体を指すURLはExtraに入っていないが、代わりにuser_screen_nameとidを使って https://twitter.com/{user_screen_name}/status/{id} あるいは https://twitter.com/statuses/{id} という形式でツイートのURLを作成できる。

Jumblrで日本語データを送信するプログラムがeclipseで動くのにjavaコマンドで動かない場合の対処法

Tumblrの公式ライブラリJumblrで日本語のテキストを投稿するJavaプログラムを書いてみたところ、eclipseから実行した場合は投稿に成功し、javaコマンドから実行した場合は401 Not Authorizedが返ってくる、という現象が発生した。
Jumblrのソースコードを見た限りでは、リクエストメッセージを作成する際にStringを引数なしのString.getBytes()でbyte配列に変換しているのが原因のようだ。
対策として、javaコマンドの引数に -Dfile.encoding=UTF-8 を加えると、期待通り動いた。

2014-05-27

eclipseにGlassFish ToolsをインストールしたがサーバービューにGlassFishを追加できない場合の対処方法

まさに以下のQ/Aで指摘されている現象が発生した。
eclipseでGlassfhsh4.0の実行 - QA@IT

経緯:
  1. Windows 8.1のパソコンにeclipse(Kepler)をインストールした。
  2. GlassFish4も「標準インストール」でインストールした。
  3. eclipseを起動し、Eclipse マーケットプレースからGlassFish Tools for Keplerをインストールした。
  4. サーバービューの新規追加ウィザードを起動し、GlassFish ToolsのGlassFish 4.0を選択したが、GlassFishのディレクトリを指定する画面で「次へ」ボタンを押しても次の画面に切り替わらなかった。「戻る」ボタンや「キャンセル」ボタンを押すことはできた。


対処方法(上記Q/Aの回答の1つ):
  1. GlassFishの既定のドメインディレクトリにあるdomain.xmlをテキストエディタで開く(GlassFishのインストールフォルダ\glassfish4\glassfish\domains\domain1\config\domain.xml)。
  2. 文字エンコーディングをShift_JISからUTF-8に変更して上書き保存する。

上記対応の結果、eclipseのサーバービューにGlassFish4.0を追加できるようになった。

2012-09-29

Rhino1.7R4向けに、単一の関数をJavaイベントリスナに変換する関数を作ってみた

Rhino1.7R4で単一の関数をWindowLisenerの実装に使うとエラーが発生する件で、 対策案としてWindowLisenerの全てのメソッドを実装する例を挙げた。
が、7つもあるメソッドのうち主に使用するのはwindowClosingくらいなので、これは面倒くさい。
そこで、過去のRhinoと似た動きをさせるための関数を作ってみた。

1-1. 単一の関数をJavaイベントリスナに変換する関数(function-as-listener.js前半):
function newListener(listenerInterface, handlerFunc) {
    function getDispatcher(methodName) {
        return function(args) {
            var actualArgs = [];
            for (var i = 0; i < arguments.length; i++) {
                actualArgs.push(arguments[i]);
            }
            actualArgs.push(methodName);
            return handlerFunc.apply(this, actualArgs);
        };
    };
    var clazz = listenerInterface.__javaObject__;
    var methods = clazz.getMethods();
    var handlerObj = {};
    for (var i = 0; i < methods.length; i++) {
        var method = methods[i];
        handlerObj[method.getName()] = getDispatcher(String(method.getName()));
    }
    return new listenerInterface(handlerObj);
}

1-2. 使用例(function-as-listener.js後半):
var gui = new java.awt.Frame("function-as-listener");
gui.addWindowListener(newListener(
    java.awt.event.WindowListener,
    function(event, methodName){
        if (methodName === "windowClosing") {
            event.getWindow().setVisible(false);
            return;
        }
        java.lang.System.out.println(methodName);
    }
));
gui.setSize(200, 100);
gui.setVisible(true);
java.lang.Thread.currentThread().sleep(1000);
gui.dispose();
java.lang.System.out.println("ok");

2. Rhino1.7R4で実行する:
>java -classpath .;js.jar org.mozilla.javascript.tools.shell.Main -w -debug function-as-listener.js
windowActivated
windowOpened
ok
windowDeactivated
windowClosed

3. jrunscript(Java1.7)で実行する:
>jrunscript function-as-listener.js
windowActivated
windowOpened
windowDeactivated
windowClosed
ok