メモ代わり。てきとーに。 いや、ですからてきとーですって。 2年前ぐらいにPythonあたりでメールくれた方、ごめんなさい。メール紛失してしまい無視した形になってしまいました。。。

2009年6月13日土曜日

[Apache Shindig][お勉強][OpenSocial][Gadget] メモ12 blacklistの追加

Apache Shindigである特定のURLからGadgetのXMLファイルを読ませたくないとする。

Apache Shindigではblacklistを作成しておくと、blacklist内のURLへは取りに行かなく
なるらしい。

ソースの場所は、


./java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetBlacklist.java
 

と。

このソースによると、

./java/common/conf/shindig.properties
 

に、

shindig.blacklist.file=/tmp/blacklist.txt
 

などと追加し、
/tmp/blacklist.txtに以下の感じで追加しておく。

hogehoge.com
REGEXP .+.net
 


頭にREGEXPとあり、さらにスペースがあると、その次の「.+.net」を正規表現として
扱ってくれる。この正規表現にマッチした場合はとりにいかない。
上記の1行目のように、REGEXPと無い場合は、xml設置場所のURLとhogehoge.comを比較し、
マッチした場合にとりにいかない。

っぽい。
実際に試していないので、違うかも。

.

2009年6月12日金曜日

[Apache Shindig][お勉強][Gadget][OpenSocial] メモ11 とりあえずPersonServiceを実装してみる

とりあえず、PersonServiceを実装してみる。


1. SampleModuleをNanashiModuleとしてコピーしてくる。
2. NananshiModuleをweb.xmlで登録。
3. PersonServiceをimplements。
4. NanashiModuleのPersonServiceへのbindを書き換え。
 

多分、こんな感じでできると思う。

ということでやってみる。

SampleModuleをコピー

social-api/src/main/java/org/apache/shindig/social/sample/SampleModule.java
 

をコピー。
名前は適当にNanashiModule.javaにした。

NananshiModuleをweb.xmlで登録
クラス名とパッケージ以外は修正していない。
とりあえずパッケージはjp.qsdn.nanashi.social。
で、

<context-param>
<param-name>guice-modules</param-name>
<param-value>
org.apache.shindig.common.PropertiesModule:
org.apache.shindig.gadgets.DefaultGuiceModule:
org.apache.shindig.social.sample.SampleModule:
org.apache.shindig.gadgets.oauth.OAuthModule:
org.apache.shindig.common.cache.ehcache.EhCacheModule
</param-value>
</context-param>
 

の、org.apache.shindig.social.sample.SampleModuleを削除。
そこに、
jp.qsdn.nanashi.social.NanashiModuleを追加。

org.apache.shindig.social.opensocial.spi.PersonServiceをimplements
名前は適当にjp.qsdn.nanashi.social.spi.PersonServiceImplとでもつけておく。

で、

* Future<RestfulCollection<Person>> getPeople(Set userIds, GroupId groupId,
CollectionOptions collectionOptions, Set<String> fields, SecurityToken token)
throws ProtocolException

* Future getPerson(UserId id, Set<String> fields, SecurityToken token)
throws ProtocolException
 

を実装する。
やはり、securityTokenもわたってくるので、
たとえばあるGadgetではPersonは誰も返さない、そしてあるGadgetにはPerson全部返す、
なんてことが可能っぽい。
今のところ、getPersonが呼ばれてエラーになっているので、とりあえず
getPersonだけ実装してみる。と思ったら、getPeopleも呼ばれるらしい。

で、実装。

public class PersonServiceImpl
implements PersonService {

protected final Log logger = LogFactory.getLog(PersonServiceImpl.class);

public Future<RestfulCollection<Person>> getPeople(Set<UserId> userIds, GroupId groupId,
CollectionOptions options, Set<String> fields, SecurityToken token)
throws ProtocolException {
List<Person> result = Lists.newArrayList();

Name name = new NameImpl("rootの友達1 だぞー");
Person personObj = new PersonImpl("rootfrend1", "rootの友達1だよーん", name);
result.add(personObj);
name = new NameImpl("rootの友達2 だぞー");
personObj = new PersonImpl("rootfrend2", "rootの友達2だよーん", name);
result.add(personObj);

int totalSize = result.size();
return ImmediateFuture.newInstance(new RestfulCollection(result, 0, totalSize));
}

public Future<Person> getPerson(UserId id, Set<String> fields, SecurityToken token)
throws ProtocolException {
logger.debug("UserId:[" + id.getUserId(token) + "]");
Name name = new NameImpl("root だぞー");
Person personObj = new PersonImpl("root", "rootだよーん", name);
return ImmediateFuture.newInstance(personObj);
}
}
 


な感じ。
カスみたいなソースだけど、とりあえずGadgetから友達一覧を取得できた。
他のインタフェースも似た感じでしょう。たぶん。

--
やはりGuiceかSpringがどちらかに統一したい。。
Springは資産があるので、できればSpringで使いたいんだけど、、
http://cwiki.apache.org/confluence/display/SHINDIG/Shindig+Spring+Example
を見る限り、ApplicationContextをGuice用に作りなおさなきゃいけないのかしら。

.

[Apache Shindig][お勉強][Gadget][OpenSocial] メモ10 JsonRpcServlet

/social/rpcの実態は、JsonRpcServlet。

ソースは、


common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java
 



common/src/main/java/org/apache/shindig/protocol/ApiServlet.java
 

を継承している模様。

--

public void setBeanConverters(
@Named("shindig.bean.converter.json") BeanConverter jsonConverter,
@Named("shindig.bean.converter.xml") BeanConverter xmlConverter,
@Named("shindig.bean.converter.atom") BeanConverter atomConverter) {
// fix this
this.jsonConverter = (BeanJsonConverter) jsonConverter;
this.xmlConverter = xmlConverter;
this.atomConverter = atomConverter;
}


ほっほー。
Guiceでも名前でBeanをセットできるのね。(違うかもしれないけど)

--
で、早速、

<beans>
<bean id="jsonRpcController"
class="jp.qsdn.nanashi.web.spring.controller.gadget.JsonRpcController">
<property name="handlers"><value>org.apache.shindig.social.handlers</value></property>
</bean>
</beans>


 

完成。動かしてみる。

--
実行したら、

({message:"unauthorized: The request did not have a proper security token nor oauth message and unauthenticated
requests are not allowed", code:401});
/* !eval(new String('(' + text + ');)) */
 


なんてレスポンスが帰ってきた。
なんだこれ。

先にsecurityTokenを理解しないと意味不明。
ハンドラディスパッチャーを読めば分かるのかしら。。

--
そもそもAuthenticationServletFilterを入れていなかった。
で、入れてやってみても401。

どうもSecurityTokenの要素数が合っていない。

common/src/main/java/org/apache/shindig/auth/BasicSecurityTokenDecoder.java
 

を見ると、

private static final int OWNER_INDEX = 0;
private static final int VIEWER_INDEX = 1;
private static final int APP_ID_INDEX = 2;
private static final int DOMAIN_INDEX = 3;
private static final int APP_URL_INDEX = 4;
private static final int MODULE_ID_INDEX = 5;
private static final int CONTAINER_ID_INDEX = 6;
private static final int TOKEN_COUNT = CONTAINER_ID_INDEX + 1;
 

となっていて、TOKEN数は7。
だけど、サンプルに書いてあったプログラムが生成するTOKEN数は、6個。
container idが足りないみたい。

とりあえずcontainer_idを追加。
実行すると、、、

org.apache.shindig.protocol.ProtocolException: Person not found
at org.apache.shindig.social.sample.spi.JsonDbOpensocialService.getPerson(JsonDbOpensocialService.java:325)
at org.apache.shindig.social.opensocial.service.PersonHandler.get(PersonHandler.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.shindig.protocol.DefaultHandlerRegistry$MethodCaller.call(DefaultHandlerRegistry.java:474)
at org.apache.shindig.protocol.DefaultHandlerRegistry$RpcInvocationHandler.execute(DefaultHandlerRegistry.java:300)
at org.apache.shindig.protocol.DefaultHandlerRegistry$RpcInvocationWrapper.execute(DefaultHandlerRegistry.java:324)
at jp.qsdn.nanashi.web.spring.controller.gadget.JsonRpcController.dispatchBatch(JsonRpcController.java:205)
at jp.qsdn.nanashi.web.spring.controller.gadget.JsonRpcController.doPost(JsonRpcController.java:173)
at jp.qsdn.nanashi.web.spring.controller.gadget.JsonRpcController.handleRequestInternal(JsonRpcController.java:84)
at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at jp.qsdn.comp.util.web.filter.RequestLogFilter.doFilter(RequestLogFilter.java:62)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.shindig.auth.AuthenticationServletFilter.callChain(AuthenticationServletFilter.java:123)
at org.apache.shindig.auth.AuthenticationServletFilter.doFilter(AuthenticationServletFilter.java:86)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Thread.java:619)
 

ってな感じで怒られる。

やっと、ここまできた。
多分、
org.apache.shindig.social.sample.spi.JsonDbOpensocialService.getPerson
をMySNS用にimplementsしてあげれば完了っぽい。

.

[Apache Shindig][お勉強][Gadget][OpenSocial] メモ9 とりあえず友達ゲット

http://wiki.opensocial.org/index.php?title=OpenSocial_Tutorial
にある、サンプルをとりあえず実行してみる。


<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="Hello">
<Require feature="opensocial-0.8" />
</ModulePrefs>
<Content type="html"><![CDATA[
<h1>Hello, World</h1>
<script type="text/javascript">
gadgets.util.registerOnLoadHandler(init);

function init() {
loadFriends();
}
function loadFriends() {
var req = opensocial.newDataRequest();
req.add(req.newFetchPersonRequest(opensocial.IdSpec.PersonId.VIEWER), 'viewer');

var viewerFriends = opensocial.newIdSpec({ "userId" : "VIEWER", "groupId" : "FRIENDS" });
var opt_params = {};
opt_params[opensocial.DataRequest.PeopleRequestFields.MAX] = 100;
req.add(req.newFetchPeopleRequest(viewerFriends, opt_params), 'viewerFriends');

req.send(onLoadFriends);
}
function onLoadFriends(data) {
var viewer = data.get('viewer').getData();
var viewerFriends = data.get('viewerFriends').getData();

html = new Array();
html.push('<ul>');
viewerFriends.each(function(person) {
if (person.getId()) {
html.push('<li>' + person.getDisplayName() + "</li>");
}
});
html.push('</ul>');
document.getElementById('friends').innerHTML = html.join('');
}
</script>
<div id="friends"></div>
]]>
</Content>
</Module>
 

な感じ。

実効すると、サーバ側に、

POST /social/rpc?st=unknown%3Aroot%3A0%3Adefault%3Ahttp%253A%252F%252Flocalhost%252Fhello.xml%3A0
 

なリクエストが飛んでくる。

ちなみにShindig使ってみているけど、勉強のため、そのまま使っているわけではなく、
SpringのControllerでShindigのServletと同じことをやっているもんで、
まだ、/social/rpcは用意していないので、エラーになるけど。
(SpringとGuiceの両方を有効にしているんで、DIが意味不明な感じだけど。)

--
なんとなく、securityToken(stパラメータ)でどのガジェットからのリクエストか
判断できるっぽい。もちろん詐称Welcomeだけど。

--

try {
JSONObject request = JsonConversionUtil.fromRequest(servletRequest);
dispatch(request, null, servletRequest, servletResponse, token);
} catch (JSONException je) {
sendJsonParseError(je, servletResponse);
}
 

って書いてあるので、やはりsecurityTokenで判断しているのかな?
tokenがsecurityToken。


.

[Apache Shindig][お勉強][Gadget][OpenSocial] メモ8 OpenSocial v0.8を使用をGadgetで宣言(?)

GadgetでOpenSocial v0.8を使用するには、


<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="Hello">
<Require feature="opensocial-0.8" />
</ModulePrefs>
<Content type="html"><![CDATA[
<h1>Hello, World</h1>
]]>
</Content>
</Module>
 

と、ModulePrefsの中に、

<Require feature="opensocial-0.8" />
 

と書くらしい。

ふーん。
--
すると、レンダリング結果にJavaScriptが展開される。

ふーん。

.

[Apache Shindig][お勉強][Gadget] メモ7 Hello,Worldガジェット

Hello, Worldを出力するだけのGadget。


<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="Hello"/>
<Content type="html"><![CDATA[
<h1>Hello, World</h1>
]]>
</Content>
</Module>
 

[Apache Shindig][お勉強] メモ6 ifrのURL仕様

http://cwiki.apache.org/SHINDIG/iframe-url-format.html
に書いてある。


http://<SHINDIG>/gadgets/ifr

* ?synd=<YOURCONTAINERNAME>
* &container=<YOURCONTAINERNAME>
* &viewer=<VIEWER ID>
* &owner=<OWNER ID>
* &aid=<APPLICATION ID, CAN BE NUMERIC OR GADGET URL>
* &mid=<MODULE ID (AKA '4TH GADGET ON THIS PAGE')>
* &country=<COUNTRY CODE: eg "US">
* &lang=<LANG CODE: eg "EN">
* &view=<INSERT VIEW NAME HERE: profile, home, canvas, preview>
* &parent=<CONTAINER URL>
* &up_<FOO>=<BAR>
* &st=<LONG ENCRYPTED TOKEN>
* &v=<CACHE BUSTING MD5 OF THE GADGET XML>
* &url=<URL OF GADGET'S XML FILE>
* #rpctoken=<RANDOM UNIQUE NUMBER>
 


.

[Apache Shindig][お勉強] メモ5 Gadgetを表示するまでの流れ

ソース読み中。

Shindigを使って、Gadgetを表示するまでの流れ。


1. iframeで/gadgets/ifr?url=なんたらかんたら
2. /gadgets/ifrはurlパラメータで指定されたURLからGadgetのXMLを取得し、レンダリング。
3. レンダリング結果をiframeにレスポンス。
 

以上。

どうも、レンダリング結果はキャッシュされていないっぽい。
GadgetのXMLが、URLを一意なキーとしてキャッシュされているっぽい。

で、iframe。

http://cwiki.apache.org/SHINDIG/display-a-gadget-in-a-web-page.html
から、コピペ。


<iframe id="remote_iframe_0" src="#{userApplicationBean.iframeUrl}"
scrolling="auto" class="gadgets-gadget" style="display: block;"
frameborder="no" height="400" width="100%" name="remote_iframe_0">
</iframe>
 

な感じのiframeに、

private void generateIframeUrl() throws UnsupportedEncodingException {
Application application = applicationService.getApplication(appid);
title = application.getTitle();
url = application.getUrl();

// generate SecurityToken
String viewerId = viewer;
String ownerId = owner;
String domain = "default";
long moduleId = 0;
String separator = URLEncoder.encode(":", "UTF-8");
String urlEncoded = url.replaceAll(":", "%253A");
urlEncoded = urlEncoded.replaceAll("/", "%252F");
StringBuilder out = new StringBuilder();
out.append(URLEncoder.encode(ownerId, "UTF-8")).append(separator).append(URLEncoder.encode(viewerId, "UTF-8"))
.append(separator).append(Long.toString(appid)).append(separator).append(URLEncoder.encode(domain, "UTF-8"))
.append(separator).append(urlEncoded).append(separator).append(Long.toString(moduleId));

securityToken = out.toString();

// generate iframeUrl
String serverBase = "http://localhost:8080/gadgets/";
String container = "default";
String parent = URLEncoder.encode("http://localhost:8080", "UTF-8");

iframeUrl = serverBase + "ifr?" + "container=" + container + "&mid=" + "0" + "&nocache=" + "1" + "&country="
+ "ALL" + "&lang=" + "ALL" + "&view=" + "canvas" + "&parent=" + parent + "&debug=" + "1" + "&st="
+ securityToken + "&url=" + URLEncoder.encode(url, "UTF-8");
iframeUrl += "#rpctoken=" + getRpcTokenRandom();
}
 

な感じのプログラム。

view=profileとかするとちっちゃくなる。

---
外部のサイトのGadgetにはproxy経由でアクセスするっぽい。
データとかは全て外部のものを使っている気がする。

さて、内部のデータを使う内部のGadgetはどうやるのだろう。

.

[Apache Shindig][お勉強] メモ4 GadgetのソースファイルをDBなどから読む?(仮)

ソース読み中。


/gadgets/ifr?url=Gadgetのソースファイル
 

のように指定するものらしいけど、必要かどうかは別にして、
仮にGadgetのソースファイル(XML)をDBから読むには、
たぶん、

org.apache.shindig.gadgets.DefaultGadgetSpecFactory
 

の、fetchFromNetworkメソッドを自前メソッドに挿げ替えれば、良いかも。

privateなんで、DefaultGadgetSpecFactoryをそのままコピーした
なんたらGadgetSpecFactoryを作り、さらに、なんたらModule作って、
bindすればよいのかしら。(Guiceも初体験)

要はGadgetSpecFactoryをimplementsした偽DefaultGadgetSpecFactoryを作成し、
よくわからないけど、@ImplementedByがきっと有効そうなので、Module作って自前でセット。

全然違うか。

そもそも、ehcache使ってCacheしているし、Content中とか(?)なんたらPrefにhref
があるとリクエスト投げちゃうようなので、思いっきり無意味な気もする。。

うーん。
.

2009年6月11日木曜日

[Apache Shindig][お勉強] メモ3 xml-to-html

ガジェットのXML定義をHTMLに変換するサーブレット。


org.apache.shindig.gadgets.servlet.GadgetRenderingServlet
 


サンプルのhttp://localhost:8080/gadgets/ifrにあたる。

ソースの場所は、

./java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingServlet.java

 


.

[Apache Shindig][お勉強] メモ2 典型的な処理の流れ

典型的な処理の流れ

サーバサイド


1. JsonRpcServletをコール
2. 適当なハンドラを取得
3. DBからJSONオブジェクトなるものを取得
4. レスポンスにlistを投入
5. クライアントへ
 

な感じ。
RESTの場合は、

1. DataServiceServletをコール。
2. 適当なconverterを取得
3. ハンドラを取得
4. DBからJSONオブジェクトを取得
5. クライアントへ。
 

な感じ。

うーん。
ハンドラを実装すれば自由にいろいろできるのかしら。

で、クライアントサイド。

1. リクエストオブジェクトを作成
2. リクエストオブジェクトにパラメータ投入
3. リクエスト送信
 

だそうで。


Apache Shindigが実装しているいくつかのOpenSocialAPI。

1. サーバ間通信 =>OpenSocial REST
2. ガジェットとサーバ間の通信=>OpenSocial JSON-RPC
3. ガジェットで使うJavascript=>javascript
 

らしい。
OpenSocial RESTは今のところ、必要そうじゃないので、とばし。

.

[Apache Shindig][お勉強] メモ1

現状JavaとPHPをサポートしてるらしい。

で、Apache Shindigのサーバサイドの大きく三つの仕組み。


1. Persistent Data Loading Mechanism;
2. Gadget Rendering Infrastructure;
3. OpenSocial server side implementation.
 

ふーん。

以下現状の個人的イメージ。

Gadgetなるものはおいといて、Persistent Data Loading Mechanismあたりをいじれば
サイト固有の情報を出し入れできるのかしら。

Gadget Rendering InfrastructureはRESTfulの場合すかね?
RESTfulはJavascriptとか使えない端末用にサーバサイドでレンダリングする
仕組みですかね?

OpenSocial server side implementationは、そのままコールしておけばよい感じか?


ぜんぜん違うか?


で、クライアントサイドの特徴。

* Gadget container (gadget.js), fully opensocial gadget compliant;
* OpenSocial container;
* JSON, Restful container and Caja support.
 

だそうで。
はて。
.

[work] ガジェット?

Apache Shindigのサンプルとして、

http://localhost:8080/gadgets/ifr?url=http://www.labpixies.com/campaigns/minesweeper/minesweeper.xml

をやったら、無駄に時間を消費した。

おもしろいねー
.

[work] ガジェット?

Apache Shindigって、元々iGoogleなんすねー。

ほっほー。

iGoogle?
.

[work] ガジェット?

ガジェットって何ってところからスタート。

XのWidgetとは違う?

SNS?

OpenSocial?

Apache Shindig?

よくわからないけど、とりあえず、Apache Shindigインストール。
で、動かしてみた。

で?
.