SyntaxHighlighter

2011年2月13日日曜日

root化しました

昨年の6月ぐらいからHTC Desire (X06HT)を使っていたんですが、とうとうroot取得しました。

スマートフォンは最初の1台目で、もし壊れてしまうと致命的となるんで、保証対象外となるroot化はせずにいたんですが、とうとう知的欲求に勝てず、root化に踏み切ってしまいました。

goldcardの手法は、SDカードを用意するとかなにやらめんどくさかったので、unrevoked3を利用してroot化に成功しました。

以下、簡単に手順を残しておきます。
  1. 本体のUSB接続モードを「USBデバッグ」(「設定」→「アプリケーション」→「開発」の画面からチェックを入れる)にする
  2. リカバリモード(HOMEボタン+電源ON)で起動し、PCにUSBで繋ぐ
  3. PCのHTC Syncをアンインストールし、PCにドライバーを入れ直す
  4. 本体をPCから外し、本体を再起動する
  5. unrevoked3をダウンロードし、reflasher.exeを実行する
  6. リカバリーモードで再起動&通常の再起動が何回か行われ、以下の画面のようになれば終了です。
      成功していれば、アプリ一覧に「Superuser Permissions」という忍者アイコンのアプリが追加されます。
    意外なほどあっけなくroot化してしまいました。

    助長する訳ではないんですが、スマートフォンなんてPCと同じだと考えると、PCが壊れたら基本保証なんてないわけで、かつカーネルの再コンパイルやレジストリをいじって使いやすくするなどの普段やっていることとあまり変わらない気がしてます。

    さて、これからようやく本格的にAndroidをいじってみようと思います。

    2011年1月31日月曜日

    Eclipseの起動時にInitializing Java Toolingがいつまでたっても終わらない場合の対処法

    Eclipseの起動時にInitializing Java Toolingが1%のままで、いつまでたっても終わらない場合があります。

    Eclipseに-cleanオプションをつけたり、何度か起動を繰り返すうちにうまく動作するようになったりするする場合もありますが、このInitializing Java Toolingがハングする現象は、ワークスペースでオープンしているプロジェクト数が多い場合に発生するようです。

    どうにもならない場合、workspaceの.metadataフォルダを削除して初期化すれば良いのですが、プラグインの設定も削除されてしまいますので、プロジェクトに関する情報だけ削除(.metadata/.plugins/org.eclipse.core.resourcesフォルダの下にあるファイルを全て削除)し、Eclipseを起動してから必要なプロジェクトをインポートすれば、比較的被害は少なくて済みます。

    でも、基本的には、必要なプロジェクトだけを開いて作業するようにしましょう。

    2011年1月30日日曜日

    CASのJASPIC(JSR-196)モジュール

    先日の「GlassFishでCasLoginModuleを動かしてみた」のエントリーのあと、JASPIC(JSR-196)のモジュールを作ってみました。

    http://code.google.com/p/cas-jaspic/

    とりあえず、HTTP profileのみで、SOAP profileについては現在調査中です。
    加えて、GlassFishでしか動作確認しません。(JBossに関しては、メッセージエクスチェンジをするとエラーと判断されるようで、動作しません。orz)

    まだプロジェクトの運営自体こなれてませんが、何かご意見があれば、コメントお願いします。

    2011年1月20日木曜日

    JSFのManagedBeanをFacesContextから取得する

    前回は、「いにゃの場合: BeanManagerからManagedBeanを取得する」でCDIのManagedBean取得を説明したが、今回はFacesContextからJSFのManagedBeanを取得する方法をメモしておきます。

    前回と同じManagedBeanを例として考えると、

    1. package sample;  
    2. import java.util.Date;  
    3. import javax.enterprise.context.RequestScoped;  
    4. import javax.inject.Named;  
    5.   
    6. @RequestScoped  
    7. @Named("test1")  
    8. public class TestBean1 {  
    9.  public Date getDate() {  
    10.   return new Date();  
    11.  }  
    12. }  

    こんな感じ

    1. FacesContext ctx = FacesContext.getCurrentInstance();  
    2. ELContext context = ctx.getELContext();  
    3. ELResolver resolver = context.getELResolver();  
    4. TestBean1 bean = (TestBean1)resolver.getValue(  
    5.   context, null"test1");  

    JSFではなくJSPのpageContextを利用する場合、以下のようにELContextを取得すればOKです。
    1. ELContext context = pageContext.getELContext();  

    resolver#getValueの第2引数は、ベースのオブジェクトを指定します。
    beanのプロパティ"date"を取得するのであれば、以下のようにします。

    1. Date date = (Date)resolver.getValue(context, bean, "date");  

    BeanManagerからManagedBeanを取得する

    CDI(JSR-299)を利用すれば、ServletやJSFのManagedBean、EJBなどにコンテナがDIしてくれるけど、DIではなく、直接CDIで管理しているManagedBeanを取得する方法をメモしておきます。

    これを知っていると、DIできないコンポーネントでManagedBeanを利用(例えば、JSFやJSPのスクリプトレット内)できたりします。

    例として、以下のようなManagedBeanがあったとします。

    1. package sample;  
    2. import java.util.Date;  
    3. import javax.enterprise.context.RequestScoped;  
    4. import javax.inject.Named;  
    5.   
    6. @RequestScoped  
    7. @Named("test1")  
    8. public class TestBean1 {  
    9.  public Date getDate() {  
    10.   return new Date();  
    11.  }  
    12. }  

    これを以下のように取得する。

    1. InitialContext ic = new InitialContext();  
    2. BeanManager manager =  
    3.   (BeanManager)ic.lookup("java:comp/BeanManager");  
    4.   
    5. Set<Bean<?>> beans = manager.getBeans(  
    6.   TestBean1.class,  
    7.   new AnnotationLiteral<Default>() {});  
    8.   
    9. Bean<?> bean = manager.resolve(beans);  
    10. TestBean1 obj = (TestBean1)manager.getReference(  
    11.   bean,  
    12.   TestBean1.class,  
    13.   manager.createCreationalContext(bean));  

    9行目のresolveは、5行目でBeanが1つに絞られているからできるのであり、もし絞られていないようであれば、5行目で取得したSet<Bean<?>>をQualifierやNameから要求にあったBeanを取得してgetReferenceを行えば良いです。

    また、EL名で取得したい場合は、5行目を
    1. Set<Bean<?>> beans = manager.getBeans("test1");  
    のようにすれば良いです。

    2011年1月17日月曜日

    GlassFishでCasLoginModuleを動かしてみた

    CASのJAASモジュールであるCasLoginModuleをGlassFishで動かしてみました。

    CASのticketは1度しかバリデーションできない(あたりまえか)ので、セッションが利用できないrealmではオブジェクト(この場合、ticketなど)を保持できないので、全てのアクセスで同じticketを使いまわす→2回目以降のバリデーションでエラーになると思われる。
    ProgrammaticLoginとか、HttpServletRequest#login(V3.0~)もrealmを利用するので、LoginContextで取得したSubjectを解析し、Assertionとかを取得して制御するようにしてみた。
    JBossやTomcat用のintegrationモジュールも似たことやってるし、それを参考に作ってみた。

    1. CAS Clientのjarファイルをコンテナに配備
      • cas-client-core-3.1.xx.jar
      • commons-logging-1.1.jar
      これを${com.sun.aas.instanceRoot}/lib/extとかにおいておく。
    2. ログイン構成ファイルにcasのLoginModuleを登録する
    3. デフォルトでは、${com.sun.aas.instanceRoot}/config/login.confというのがログイン構成ファイルで指定してあるので、そこに以下のエントリを追加する。
      1. cas {  
      2.   org.jasig.cas.client.jaas.CasLoginModule required  
      3.   ticketValidatorClass="org.jasig.cas.client.validation.Cas20ProxyTicketValidator"  
      4.   casServerUrlPrefix="http://localhost/cas-server"  
      5.   defaultRoles="";  
      6. };  
      詳しくは以下のjavadocに書いてあります。 http://www.jarvana.com/jarvana/view/org/jasig/cas/client/cas-client-core/3.1.11/cas-client-core-3.1.11-javadoc.jar!/org/jasig/cas/client/jaas/CasLoginModule.html ※defaultRolesはoptionalと書いてあるけど、何も指定していないとNPEになります。 上記の設定ができたら、GlassFishを再起動します。
    4. フィルターを作成する
      1. /** 
      2.  * 
      3.  */  
      4. package test;  
      5.   
      6. import java.io.IOException;  
      7. import java.security.GeneralSecurityException;  
      8. import java.security.Principal;  
      9.   
      10. import javax.security.auth.Subject;  
      11. import javax.security.auth.login.LoginContext;  
      12. import javax.servlet.FilterChain;  
      13. import javax.servlet.ServletException;  
      14. import javax.servlet.ServletRequest;  
      15. import javax.servlet.ServletResponse;  
      16. import javax.servlet.http.HttpServletRequest;  
      17. import javax.servlet.http.HttpServletRequestWrapper;  
      18. import javax.servlet.http.HttpServletResponse;  
      19. import javax.servlet.http.HttpSession;  
      20.   
      21. import org.jasig.cas.client.jaas.AssertionPrincipal;  
      22. import org.jasig.cas.client.jaas.ServiceAndTicketCallbackHandler;  
      23. import org.jasig.cas.client.util.AbstractCasFilter;  
      24. import org.jasig.cas.client.util.CommonUtils;  
      25. import org.jasig.cas.client.validation.Assertion;  
      26.   
      27. /** 
      28.  * @author hisato 
      29.  *  
      30.  */  
      31. public final class WebAuthenticationFilter extends AbstractCasFilter {  
      32.   
      33.  public class WebAuthenticationRequestWrapper extends  
      34.    HttpServletRequestWrapper {  
      35.   
      36.   private Principal principal = null;  
      37.   
      38.   /** 
      39.    * @param request 
      40.    */  
      41.   public WebAuthenticationRequestWrapper(HttpServletRequest request,  
      42.     Principal principal) {  
      43.    super(request);  
      44.    this.principal = principal;  
      45.   }  
      46.   
      47.   /* 
      48.    * (non-Javadoc) 
      49.    * @see javax.servlet.http.HttpServletRequestWrapper#getUserPrincipal() 
      50.    */  
      51.   @Override  
      52.   public Principal getUserPrincipal() {  
      53.    return this.principal;  
      54.   }  
      55.  }  
      56.   
      57.  public static final String CONST_CAS_LAST_TICKET = "_const_cas_last_ticket_";  
      58.   
      59.  public static final String CONST_CAS_LOGIN_SUBJECT = "_const_cas_login_subject_";  
      60.   
      61.  /* 
      62.   * (non-Javadoc) 
      63.   * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, 
      64.   * javax.servlet.ServletResponse, javax.servlet.FilterChain) 
      65.   */  
      66.  @Override  
      67.  public void doFilter(ServletRequest servletRequest,  
      68.    ServletResponse servletResponse, FilterChain chain)  
      69.    throws IOException, ServletException {  
      70.   HttpServletRequest request = (HttpServletRequest) servletRequest;  
      71.   HttpServletResponse response = (HttpServletResponse) servletResponse;  
      72.   HttpSession session = request.getSession();  
      73.   if (session != null) {  
      74.    String ticket = CommonUtils.safeGetParameter(request,  
      75.      getArtifactParameterName());  
      76.    Assertion assertion = (Assertion) session  
      77.      .getAttribute(CONST_CAS_ASSERTION);  
      78.    AssertionPrincipal principal = null;  
      79.    if (assertion != null) {  
      80.     request = new WebAuthenticationRequestWrapper(request,  
      81.       assertion.getPrincipal());  
      82.    }  
      83.    if (ticket != null  
      84.      && !ticket.equals(session  
      85.        .getAttribute(CONST_CAS_LAST_TICKET))) {  
      86.     try {  
      87.      String service = constructServiceUrl(request, response);  
      88.      LoginContext lc = new LoginContext(  
      89.        "cas",  
      90.        new ServiceAndTicketCallbackHandler(service, ticket));  
      91.      lc.login();  
      92.      Subject subject = lc.getSubject();  
      93.      for (Principal p : subject.getPrincipals()) {  
      94.       if (p instanceof AssertionPrincipal) {  
      95.        principal = (AssertionPrincipal) p;  
      96.        break;  
      97.       }  
      98.      }  
      99.      if (principal != null) {  
      100.       session.setAttribute(CONST_CAS_LOGIN_SUBJECT,  
      101.         subject);  
      102.       session.setAttribute(CONST_CAS_ASSERTION,  
      103.         principal.getAssertion());  
      104.       session.setAttribute(CONST_CAS_LAST_TICKET, ticket);  
      105.       request = new WebAuthenticationRequestWrapper(request,  
      106.         principal);  
      107.      } else {  
      108.       throw new GeneralSecurityException(  
      109.         "Web authentication did not produce CAS AssertionPrincipal.");  
      110.      }  
      111.     } catch (GeneralSecurityException e) {  
      112.      response.sendError(HttpServletResponse.SC_FORBIDDEN,  
      113.        e.getMessage());  
      114.     }  
      115.    }  
      116.    if (request.getUserPrincipal() == null) {  
      117.     session.removeAttribute(CONST_CAS_LOGIN_SUBJECT);  
      118.     session.removeAttribute(CONST_CAS_ASSERTION);  
      119.     session.removeAttribute(CONST_CAS_LAST_TICKET);  
      120.    }  
      121.   }  
      122.   chain.doFilter(request, response);  
      123.  }  
      124. }  
    5. アプリケーションにフィルターを設定する

    クラスローダーは子を優先するようにしておく必要がありました。
    1.をスキップして、casのjarファイルをアプリケーションに放り込んでおけば、クラスローダーの設定はどっちでも良いようです。

    とりあえず、コンテナー依存のコードはないので、GlassFish以外でも多分動くと思われます。

    でも、UserPrincipalと、デフォルトロールのマッピングぐらいしかできないです。
    (配備記述子で設定したグループとロールのマッピングはやってくれるはずがないw)

    まぁ認証(Authorization)だけならこれでもいいけど、承認(Authentication)をちゃんとやるなら、JSR-196でメッセージ認証を実装した方がいい気がします。

    そのうち作ってみます~。

    2011年1月13日木曜日

    Blogaway

    Bloggerに引越ししたので、携帯(Android)からも投稿できるようにBlogawayというアプリケーションをインストールしてみた。

    使いやすいんだけど...Draftが編集できない...。

    どうもPCで編集したDraftがアプリから編集できないようだ。
    せっかく携帯から投稿できるように引っ越したのに...でも、他のアプリに比べて使いやすそうなので、まぁしょうがないか。

    アプリの評価に対応希望とコメントしておこうかな。