ラベル rhino の投稿を表示しています。 すべての投稿を表示
ラベル rhino の投稿を表示しています。 すべての投稿を表示

日曜日, 1月 09, 2011

Googleの検索機能をAPI的に使える!?

Googleドキュメントにuploadした文書は、"Google Documents List Data API"経由で全文検索ができるらしい。これをJavascriptからやってみました(Rhino)。
/*
 * FullTextSearch
 * http://bit.ly/i4QaUO
 */

importPackage(com.google.gdata.client.docs);
importPackage(com.google.gdata.client);
importPackage(com.google.gdata.data.docs);
importPackage(java.util);
importPackage(java.util.logging);

function getDocsService(applicationName, username, password){
    var service = new DocsService(applicationName)
    service.setUserCredentials(username, password)
    return service;
}

var username = 'xxxx@gmail.com';
var password = 'xxxx';
var client   = getDocsService('fts-test-1', username, password);

var feedUri  = new java.net.URL('https://docs.google.com/feeds/default/private/full/');
var query    = new DocumentQuery(feedUri);

var qStr     = "first"; // 検索文字列
query.setFullTextQuery(qStr);

var feed = client.getFeed(
    query,
    java.lang.Class.forName("com.google.gdata.data.docs.DocumentListFeed")
);

print( feed );

if(feed){
    var entries = feed.getEntries();

    for (var i = 0; i < entries.size();i++){
        print("- " + entries.get(i).getTitle().getPlainText());
    }

    print(entries.size());
}

もちろん元ネタは、ぶいてくさんの「すごいのはGDriveより全文検索でしょ!?」です。カスタム検索という機能は提供されていましたが、検索結果としてHTMLが返されたりと、プログラムから使える感じではなかったのですが、これは便利そうです。

日曜日, 1月 02, 2011

JavaからJavascriptを使うとき

以下では、組込み変数のenvironmentなどがない環境での実行になってしまう。
Context cx = Context.enter();
Scriptable scope = new ImporterTopLevel(cx);
Object obj = cx.evaluateReader(scope, reader, "JsScript", 1, null);

これは以下のように、GlobalオブジェクトでContectを初期化することで(それら変数が入った)シェルと同様の環境で実行させることができる。
Global global = new Global();
Context cx = ContextFactory.getGlobal().enterContext();
global.init(cx);
Scriptable scope = cx.initStandardObjects(global);
Object obj = cx.evaluateReader(scope, reader, "JsScript", 1, null);

EnvJSの過去MLで知りました。
なお、ここのGlobalはorg.mozilla.javascript.tools.shell.Globalです。

水曜日, 11月 10, 2010

rhinoから"Google Storage"にupload!

GSUtil というコマンドラインツールが用意されているものの、Python(?Rubyだっけ)なので使っていなかった、が、以下ソースでuploadに成功。
"WebOS Goodies"さんの情報を参考にしました。ありがとうございます!
importPackage(javax.crypto);
importPackage(javax.crypto.spec);
importPackage(org.apache.commons.codec.binary);

importPackage(org.apache.commons.httpclient);
importPackage(org.apache.commons.httpclient.methods);

var ACCESS_KEY = 'GOOG4C72MAOUMK7xxx3Z';
var SECRET     = 'xy4jTrxxxxuTZEtqUItfZIViVUF3xEKx4xxxp';
var HOST       = 'commondatastorage.googleapis.com';

var strDate    = getDate();
var strPath    = '/test/start.txt';

var headers = {
//  'Content-Length': '0',
'Content-Type': 'text/plain',
'Date': strDate,
    'User-Agent': 'Jakarta Commons-HttpClient/3.1',
    'Host': 'commondatastorage.googleapis.com'
};

// rhino + Java package/class
// http://d.hatena.ne.jp/terurou/20100918/1284791541

// http://www.fireproject.jp/feature/uzumi/httpclient/logging.html
java.lang.System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
java.lang.System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
java.lang.System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire.header", "debug");
java.lang.System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "debug");

var httpclient = new HttpClient();

if(false){ 
var httpget = new GetMethod("http://commondatastorage.googleapis.com" + strPath); 
httpget.setRequestHeader(new Header("Date",strDate));
httpget.setRequestHeader(new Header("Authorization",getAuthHeader('GET', headers,strPath)));

var statusCode = httpclient.executeMethod(httpget);  
print(httpget.getStatusLine());
}else{
var httpput = new PutMethod("http://commondatastorage.googleapis.com" + '/tf0054'+strPath);
var jstrTmp = "Hello this is a test in one line that is longer 12345677890\n";

httpput.setRequestHeader(new Header("Authorization",getAuthHeader('PUT', headers, strPath)));
httpput.setRequestHeader(new Header("Date",strDate));
httpput.setRequestHeader(new Header("x-goog-acl","public-read"));
httpput.setRequestHeader(new Header("Content-Type","text/plain"));
httpput.setRequestHeader(new Header("Content-Length","" + jstrTmp.length));
httpput.setRequestBody(jstrTmp);

httpclient.executeMethod(httpput);
print(httpput.getResponseBodyAsString());
}

function getAuthHeader(strMethod, headers, strPath){

function getHmacSign(strTmp){
var strType = 'HmacSHA1';
var jstrTmp = new java.lang.String(strTmp);
var jstrSec = new java.lang.String(SECRET);
var mac = Mac.getInstance(strType);
mac.init(new SecretKeySpec(jstrSec.getBytes(), strType));
return new java.lang.String(Base64.encodeBase64(mac.doFinal(jstrTmp.getBytes())),"UTF-8");
}

var strHeaders = strMethod + "\n";
strHeaders += "\n"; // Content-MD5 value
for(var i in headers){
if(i.toLowerCase() == 'date' || i.toLowerCase() == 'content-type'){
strHeaders += headers[i] + "\n";
} else {
// strHeaders += i.toLowerCase()+':'+headers[i]+"\r\n";
}
}
strHeaders += "x-goog-acl:public-read\n";
strHeaders += '/tf0054' + strPath;
print(">"+strHeaders);
return 'GOOG1 ' + ACCESS_KEY + ':' + getHmacSign(strHeaders);
}

function getDate(){
var d = new Date(new Date().getTime());
return d.toGMTString().replace(/UTC/,'GMT');
}

適当なソースですが、ご参考までに。

火曜日, 11月 02, 2010

JavascriptでHIVEを操作する(JDBC@Thrift)

rhinoを使って、JavascriptからHIVEを操作してみるテスト。普通にできた(あたりまえ)。

/*
http://wiki.apache.org/hadoop/Hive/HiveClient#Thrift_Java_Client
*/

importPackage(java.sql);
importPackage(java.lang);

Class.forName("org.apache.hadoop.hive.jdbc.HiveDriver");

var tableName = "testHiveDriverTable";

// make connection
var conn = DriverManager.getConnection("jdbc:hive://localhost:10000/default", "", "");
var stmt = conn.createStatement();

// init
stmt.executeQuery("drop table " + tableName);
stmt.executeQuery("create table " + tableName + " (key int, value string)");

// show tables
var sql = "show tables '" + tableName + "'";
print("Running: " + sql);
var resp = stmt.executeQuery(sql);
if (resp.next()) {
print(resp.getString(1));
}

// describe table
sql = "describe extended " + tableName;
print("Running: " + sql);
resp = stmt.executeQuery(sql);
while (resp.next()) {
print(resp.getString(1) + "\t" + resp.getString(2));
}

// load data into table
var filepath = "/tmp/a.txt";
sql = "load data local inpath '" + filepath + "' into table " + tableName;
print("Running: " + sql);
resp = stmt.executeQuery(sql);

// select * query
sql = "select * from " + tableName;
print("Running: " + sql);
resp = stmt.executeQuery(sql);
while (resp.next()) {
print(String(resp.getInt(1)) + "\t" + resp.getString(2));
}

// regular hive query
sql = "select count(1) from " + tableName;
print("Running: " + sql);
resp = stmt.executeQuery(sql);
while (resp.next()) {
print(resp.getString(1));
}

一応、走らせるときのbuild.xmlもサンプルとして。

<path id="clspath">
<fileset dir="build/jar">
<!-- メインの読込み -->
<include name="*.jar"/>
</fileset>
<fileset dir="${hive.dir}">
<!-- HIVEのjarを読込み -->
<include name="**/*.jar"/>
</fileset>
<fileset dir="${hadoop.dir}">
<!-- Hadoopのjarを読込み -->
<include name="*.jar"/>
</fileset>
</path> 

<!-- blog-gae>ant rhino-run -Dfile.encoding=UTF-8 -Dscript="env0.js" -->
<target name="rhino-run">
<echo message="Running ${script}"/> 
<java fork="yes"
classname="org.mozilla.javascript.tools.shell.Main"
failonerror="true">
<classpath>
<path refid="clspath" />
<pathelement path="js.jar" />
</classpath>
<arg value="${script}" />
</java>
</target>

HIVEの力なんだけど、とても簡単にM/Rが動くのは素晴らしい、と思います。

金曜日, 9月 10, 2010

Solrクエリのパーサ2

以下を忘れいたので、GINによるSolrクエリパーサを改訂しました。

・NOT
・レンジクエリ(pub_date:[2009-10-01T00:00:00Z+TO+*])

// Solrクエリパーサの作成(LL) v0.2

// パーサジェネレータを読込み
load('work\\mod_gin.js');

// パーサを作成(EBNFで文法を定義)
// JS_STRINGはダブルクウォートで括らなくてはならないのでTermを定義して使う
// Termで+記号は定義せず+desc/+ascを別書きとする(+OR+等とかぶるため全体がターム扱いとなる)
// Rangeには[]で括って作られるレンジクエリ用の記述を入れて別出し
var calc = new Gin.Grammar({
Solr: / Object ( '&' Object )* /,
Object: / ( Value '=' Factor ) /,
Factor: / Value ( ',' Factor | '+AND+' Factor | '+OR+' Factor | '+NOT+' Factor )* /,
Value: / Term | '(' Factor ')' /,
Term: / <[a-zA-Z0-9_.]+> ':[' Range ']' | <[a-zA-Z0-9_.:]+(\+desc|\+asc)?> /,
Range: / <[a-zA-Z0-9_.+*\-]+> /
}, "Solr", Gin.SPACE);

// 検証するSolrクエリ
var strInput = 'start=0&q=AREA_CD:050+OR+DISP:1+AND+HAN_CD:011)+AND+EKI_CD:26610+AND+pub_date:[2009-10-01T00:00:00Z+TO+*]&sort=EKI_CD+asc,HAN_CD+desc&wt=javabin&rows=0&version=2.2';

// パーサのデバッグを行うときは以下のコメントを復活
var input = [
// 'q=((AAA:1+AND+BBB:2))&start=1',
// '"q"=(("AAA:x"+AND+"BBB:2")+AND+"CCC:3")&"start"=1&"var"=1.1',
// '"q"=("DDD"+OR+("AAA"+AND+"BBB")+AND+"CCC")&"sort"="test+desc","kkk+asc"&"start"=1',
strInput
];

// 検証!
for (var i = 0; i < input.length; i++) {
var match = calc.parse(input[i]);
if (match && match.full){
print("AST: " + match.value.toSource());
}else{
print(input[i]);
print("Sentence was wrong.");
}
}

月曜日, 8月 09, 2010

Solrクエリのパーサ1

"Days on the Moon"さんのブログを参考に、Solrのクエリを整形(Lint)する目的でパーサを作る実験中です。

以下、なんとなく通った版です(GINはmod_gin.jsとリネームし、rhinoで起動)。

// Solrクエリパーサの作成(LL) v0.1

// パーサジェネレータを読込み
load('work\\mod_gin.js');

// パーサを作成(EBNFで文法を定義)
// JS_STRINGはダブルクウォートで括らなくてはならないのでTermを定義して使う
// Termで+記号は定義せず+desc/+ascを別書きとする(+OR+等とかぶるため全体がターム扱いとなる)
// Termには数字は入ってこない想定(Valueに$REALがあるため)
var calc = new Gin.Grammar({
Solr: / Object ( '&' Object )* /,
Object: / ( Value '=' Factor ) /,
Factor: / Value ( ',' Factor | '+AND+' Factor | '+OR+' Factor )* /,
Value: / $REAL | Term | '(' Factor ')' /,
Term: / <[a-zA-Z0-9:_.]+(\+desc|\+asc)?> /
}, "Solr", Gin.SPACE);

// 検証するSolrクエリ
var strInput = 'start=0&q=(AREA_CD:050+OR+DISP:1+AND+HAN_CD:011)+AND+EKI_CD:26610&sort=EKI_CD+asc,HAN_CD+desc&wt=javabin&rows=0&version=2.2';

// パーサのデバッグを行うときは以下のコメントを復活
var input = [
// 'q=((AAA:1+AND+BBB:2))&start=1',
strInput
];

// 検証!
for (var i = 0; i < input.length; i++) {
var match = calc.parse(input[i]);
if (match && match.full){
print("AST: " + match.value.toSource());
}else{
print(input[i]);
print("Sentence was wrong.");
}
}

月曜日, 7月 19, 2010

rhinoでe4xを使う

Windowsのantでスクリプト実行をしていたのだけど、何故かant経由だとe4xがうまく使えなかった。javaコマンドで直接起動する分には問題ない。

D:\work\blog-gae>java -cp war\WEB-INF\lib\js.jar org.mozilla.javascript.tools.shell.Main work\e4x.js

以下そのときのantのターゲット。

<target name="rhino-run">
<property name="classes" value="war/WEB-INF/lib/js.jar:war/WEB-INF/lib/mailapi.jar:war/WEB-INF/lib/smtp.jar"/>
<echo message="Running ${script}"/>
<java classname="org.mozilla.javascript.tools.shell.Main"
classpath="${classes}"
failonerror="true">
<arg value="${script}" />
</java>
</target>

そのときのe4xテストスクリプトは以下。
// var a = require("test0.js");

var i = '<a><b><c>aaaa</c></b><b><c>bbbb</c></b></a>';

var xml = new XML(i);

//print(xml.a.b.c[1].toString());
//print(xml.a.b.c[1]);

// 何故か先頭要素を省いたものが正解
print(xml.b.c[1]);

エラーは以下のとおり。

D:\work\blog-gae>ant rhino-run -Dscript="work\e4x.js"
Buildfile: build.xml

rhino-run:
[echo] Running work\e4x.js
[java] js: uncaught JavaScript runtime exception: ReferenceError: "XML" is not defined.
[java]

BUILD FAILED
D:\work\blog-gae\build.xml:141: Java returned: 3

Total time: 1 second
D:\work\blog-gae>

これは(やはり)classpathの問題のようで、以下のスクリプト(コチラを参考)でclasspathを出してみると、
var strConf = "java.class.path";
var cwd = environment[strConf];
cwd = cwd.replace(/;/g, "\n");
print(strConf + " = " + cwd);

antのものばかりで、肝心のjs.jarが出ない。

D:\work\blog-gae>ant rhino-run -Dscript="work\env0.js"
Buildfile: build.xml

rhino-run:
  [echo] Running work\env0.js
  [java] java.class.path = D:\work\apache-ant-1.7.1\bin\..\lib\ant-launcher.j
ar
  [java] d:\Documents and Settings\00962724\.ant\lib\ivy-2.0.0-rc2.jar
  [java] D:\work\apache-ant-1.7.1\lib\ant-antlr.jar
  [java] D:\work\apache-ant-1.7.1\lib\ant-apache-bcel.jar
  [java] D:\work\apache-ant-1.7.1\lib\ant-apache-bsf.jar
snip
  [java] D:\work\apache-ant-1.7.1\lib\xercesImpl.jar
  [java] D:\work\apache-ant-1.7.1\lib\xml-apis.jar
  [java] C:\Program Files\Java\jdk1.6.0_18\lib\tools.jar

BUILD SUCCESSFUL
Total time: 1 second
D:\work\blog-gae>

そこで、上記ターゲットにantを実行しているjvmとは別のvmで実行するようforkを入れると、

<target name="rhino-run">
 <property name="classes" value="war/WEB-INF/lib/js.jar:war/WEB-INF/lib/mailapi.jar:war/WEB-INF/lib/smtp.jar">
 <echo message="Running ${script}">
 <java fork="yes" classname="org.mozilla.javascript.tools.shell.Main" classpath="${classes}" failonerror="true">
     <arg value="${script}">
 </arg>
</java>
</echo></property></target>

うまくjs.jarが動くようになり、

D:\work\blog-gae>ant rhino-run -Dscript="work\env0.js"
Buildfile: build.xml

rhino-run:
  [echo] Running work\env0.js
  [java] java.class.path = D:\work\blog-gae\war\WEB-INF\lib\js.jar
  [java] D:\work\blog-gae\war\WEB-INF\lib\mailapi.jar
  [java] D:\work\blog-gae\war\WEB-INF\lib\smtp.jar

BUILD SUCCESSFUL
Total time: 3 seconds
D:\work\blog-gae>

e4xが正常に動作した。

D:\work\blog-gae>ant rhino-run -Dscript="work\e4x.js"
Buildfile: build.xml

rhino-run:
  [echo] Running work\e4x.js
  [java] bbbb

BUILD SUCCESSFUL
Total time: 1 second
D:\work\blog-gae>

検索すると意外にrhinoのバージョン問題か、などいろいろでるけど、1.7R1で正常に使えています