-Tapestry-S2連携再考(3)

今やりかけているのは、IRequestCycle をいじって、以下のようなページオブジェクトがあるときに、デフォルトでS2Containerからコンポーネントをセットしてくれるようにしようとしてます。

package sample.org.seasar.contribute.tapestry;
import org.apache.tapestry.html.BasePage;
public class Home extends BasePage {
  private Counter counter;

  public Counter getCounter() {
    return counter;
  }

  public void setCounter(Counter counter) {
    this.counter = counter;
  }
}

いつでも、getCounter()したら、S2Container上の"counter"という名前のコンポーネントを自動で取得できるようにしようと思ってます。動かないコードですが、以下をデバッグ中。

package org.seasar.contribute.tapestry;
import org.apache.tapestry.IEngine;
import org.apache.tapestry.IPage;
import org.apache.tapestry.engine.IEngineService;
import org.apache.tapestry.engine.IMonitor;
import org.apache.tapestry.engine.RequestCycle;
import org.apache.tapestry.request.RequestContext;
import org.seasar.framework.beans.BeanDesc;
import org.seasar.framework.beans.PropertyDesc;
import org.seasar.framework.beans.impl.BeanDescImpl;
import org.seasar.framework.container.S2Container;
public class RequestCycleProxy extends RequestCycle {
  public RequestCycleProxy(IEngine engine, RequestContext requestContext,
    IEngineService service, IMonitor monitor) {
      super(engine, requestContext, service, monitor);
  }

  // ベタですが、フィルタです。
  private Class[] filteredClasses = {
    java.util.Collection.class,
    java.util.Map.class,
    org.apache.tapestry.event.ChangeObserver.class,
    org.apache.tapestry.IBeanProvider.class,
    org.apache.tapestry.IComponent.class,
    org.apache.tapestry.IEngine.class,
    org.apache.tapestry.ILocation.class,
    org.apache.tapestry.IMessages.class,
    org.apache.tapestry.INamespace.class,
    org.apache.tapestry.IPage.class,
    org.apache.tapestry.IRequestCycle.class,
    org.apache.tapestry.spec.IComponentSpecification.class
  };
  
  private boolean isFiltered(Class clazz) {
    for(int i = 0; i < filteredClasses.length; i++) {
      if(clazz.equals(filteredClasses[i])) {
      	return true;
      }
    }
    return false;
  }

  private void setS2Components(IPage page) {
    Object global = page.getGlobal();
    if(global instanceof GlobalProxy) {
      S2Container container = *1;
      for(int i = 0; i < pageDesc.getPropertyDescSize(); i++) {
        PropertyDesc propertyDesc = pageDesc.getPropertyDesc(i);
        Class propertyClass = propertyDesc.getPropertyType();
        String propertyName = propertyDesc.getPropertyName();
        if(propertyClass.isInterface() && !isFiltered(propertyClass)) {
          try {
            Object component = container.getComponent(propertyName);
            propertyDesc.setValue(page, component);
          } catch (RuntimeException e) {/*do nothing*/}
        }
      }
    }
  }
  // ここの、setS2Components(page);を呼び出すタイミングは考慮中
  public IPage getPage() {
    IPage page = super.getPage();
    setS2Components(page);
    return page;
  }
  public IPage getPage(String name) {
    IPage page = super.getPage(name);
    setS2Components(page);
    return page;
  }
}

propertyDesc.setValue(page, component);で、IllegalArgumentExceptionがでちゃうんですよ。あと、めちゃんこ効率が悪いです。ぐるぐるループが廻ってます。またしばらく仕事したら続きをやります。


...ということで、いろいろ見ましたが、わからんです。しっかりとCounterImplとってきて、setCounter(Counter)を呼ぶとIllegalArgumentException。なにかに執り付かれたにちがいない。ひがさんのヒントも見たのですが、やってることはまったく変らない。。。ように見える。

*1:GlobalProxy)global).getS2Container(); BeanDesc pageDesc = new BeanDescImpl(page.getClass(