トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS

Java:Rhino:初めてのRhino のバックアップ(No.2)


Java:Rhino:初めてのRhino

JavaからJavaScript?を実行できる、Rhinoを使って見ました。

これから、Webページのスクレイピングで使おうとおもってます。Javaでやるより、JQueryとか使った方が楽そうだもんねw

環境設定

Rhinoのjarにクラスパスが通っているだけでOKです。

Rhinoのjarは以下のURLよりDLします。

※日本語ページもありますが、日本語の方はバイナリが古いです。更新もされてないみたいだし。

ソースコード

RhinoをつかってJavaScript?を読み込み、JavaScript?に定義されている関数を任意のタイミングで呼び出す、ってサンプルです。

ファイルは以下の2つです。

  • sample.js
  • RhinoFirstSample?.java

まず、JavaScript?のソースコード。

■sample.js

function sample(){
	print("hello world");
	print("This output is from JavaScript.");
	return "Return value";
};

他愛もないjsです。

次にjavaのソースコード。大雑把に、以下の内容を実行してます。

  • コンストラクタ:Rhinoの初期可処理をしてます。
    • Rhinoのシェルにしかない関数(print等)を使用したいために、Globalオブジェクトを生成し、スコープ生成の際に引数として渡しています。
  • execScriptメソッド:引数に指定されたスクリプトを実行します。
  • execFunctionメソッド:引数に指定された関数名及び引数から、関数を実行する1行のJavaScript?文を生成し、実行します。

まあ、ポイントはコードを読んでもらえればw

コンストラクタ→execScriptメソッド→execFunctionメソッド→contextExitメソッドの順に処理が流れています。

※mainの中身どおりw

RhinoFirstSample?.java

package rhinotest;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.Script;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.tools.shell.Global;

public class RhinoFirstSample {

	private Global global = null;
	private Context cx = null;
	private Scriptable scope = null;

	/**
	 * コンストラクタ
	 * Rhinoの初期化処理を実行
	 */
	public RhinoFirstSample() {
		// コンテキストの生成
		cx = ContextFactory.getGlobal().enterContext();
		// shellでしか使えない関数(print等)を使用するため、使用
		global = new Global();
		global.init(cx);
		// optimazationのレベルを指定。-1だと、Scriptを逐次解釈する。
		// 1-9だと、レベルに応じて適切にclassファイルを生成する。
		cx.setOptimizationLevel(-1);
		cx.setLanguageVersion(Context.VERSION_1_5);
		// スタンダードオブジェクトを生成。
		// Javadocには「return: the initialized scope」と記載あり。
		scope = cx.initStandardObjects(global);
	}
	
	/**
	 * 指定されたパス、ファイル名のJavaScriptを実行する。
	 * @param path
	 * @param filename
	 * @throws IOException
	 */
	public void execScript(String path, String filename) throws IOException {
		
		Reader scriptReader = new FileReader(path + File.separator + filename);
		Script script = cx.compileReader(scriptReader, filename, 1, null);
		scriptReader.close();
		script.exec(cx, scope);
	}
	
	
	/**
	 * 指定された関数を実行する。
	 * 以下の場合、実行行を以下のように組み立て、スクリプトとして実行する。
	 *  jsFuncName:testFunc
	 *  args : ["test1","test2"]
	 * => testFunc("test1","test2");
	 * @param jsFuncName : 関数名を指定
	 * @param args : 引数をString配列で指定、引数がない場合は空の配列もしくはnullも可
	 * @return
	 */
	@SuppressWarnings("static-access")
	public String execFunction(String jsFuncName,String[] args){
		StringBuffer execLine = new StringBuffer();
		execLine.append(jsFuncName + "(" );
		if(args != null){
			for(int i=0; i < args.length; i++){
				execLine.append("\"");
				execLine.append(args[i]);
				execLine.append("\"");
				if (i != args.length){
					execLine.append(",");
				}
			}
		}
		execLine.append(");");
		Object result = cx.evaluateString(scope, execLine.toString(), "<cmd>",
				1, null);
		return cx.toString(result);
	}
	
	/**
	 * Rhinoのコンテキストをクローズする。
	 * RhinoのJavadocに、exit()しろってかいてあったので書いてみた。
	 */
	public void contexExit(){
		Context.exit();
	}

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		
		RhinoFirstSample rhino = null;
		try{
			rhino = new RhinoFirstSample();
			final String RESOURCE_PATH = "bin/resources";
			rhino.execScript(RESOURCE_PATH, "sample.js");
			
			System.out.println("This output is java(println) : "
					+ rhino.execFunction("sample", null));
		}finally{
			rhino.contexExit();	
		}		
	}
}

実行結果

こんな感じです。

hello world
This output is from JavaScript.
This output is java(println) : Return value

うん、いい感じw

参考

Rhinoのjavadocがアーカイブに含まれているため、これをちゃんと見ましょう。

特に、以下のクラスについてはw

  • ContextFactory?
  • Context