Java から evaluateString する形で javascript コードを実行する場合に logger.log() で指定したファイルにログを書き出したい、という場合の解決方法.
Logger という ScriptableObject を自分でつくって解決する:
class Logger extends ScriptableObject {
@Override
String getClassName() { return "Logger" }
Logger(){}
private File file
void jsConstructor(String filePath){
this.file = new File(filePath)
}
@JSFunction
void log(String msg){
file.text = msg
}
}
このクラスを logger という名前で 現在の scope に存在させる:
def logFile = new File('log.txt')
ScriptableObject.defineClass(scope, Logger.class)
def logger = cx.newObject(scope, "Logger", logFile.absolutePath)
ScriptableObject.putProperty(scope, "logger", logger)
ポイントは cx.newObject するときに、保存するログファイルのパスを渡しておきます.
あとは、たとえばこんな js を書く:
var value = 1+2;
logger.log( ''+value );
これを evaluteString すればよい:
cx.evaluateString(scope, script0, "<cmd>", 1, null)
Logger クラスの log 関数内が...
@JSFunction
void log(String msg){
file.text = msg
}
このような実装になっているので、一つのメッセージしかファイルに保存できない.
(新しいメッセージがくると前のメッセージは消える.)
これでは不便なので、古いメッセージに追記する形に修正します.
@JSFunction
void log(String msg){
def lines = []
if( file.exists() ){
lines = file.text.readLines()
}
lines << msg
file.text = lines.join(System.getProperty('line.separator'))
}
これで、複数の logger.log() をしてもログを全部保存できるようになりました.
@Grab(group='org.mozilla', module='rhino', version='1.7.12')
import org.mozilla.javascript.Context
import org.mozilla.javascript.ScriptableObject
import org.mozilla.javascript.annotations.JSFunction
class Logger extends ScriptableObject {
@Override
String getClassName() { return "Logger" }
Logger(){}
private File file
void jsConstructor(String filePath){
this.file = new File(filePath)
}
@JSFunction
void log(String msg){
def lines = []
if( file.exists() ){
lines = file.text.readLines()
}
lines << msg
file.text = lines.join(System.getProperty('line.separator'))
}
}
def script0 = '''\
|logger.log('message-1');
|logger.log('message-2');
|logger.log('message-3');
|'''.stripMargin('|')
def cx = Context.enter()
def scope = cx.initStandardObjects()
def logFile = new File('log.txt')
ScriptableObject.defineClass(scope, Logger.class)
def logger = cx.newObject(scope, "Logger", logFile.absolutePath )
ScriptableObject.putProperty(scope, "logger", logger)
cx.evaluateString(scope, script0, "<cmd>", 1, null)
Context.exit()
以上です.