Package net.infopeers.restrant.engine

Source Code of net.infopeers.restrant.engine.ReflectInvoker

package net.infopeers.restrant.engine;

import java.lang.reflect.Field;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.infopeers.restrant.Controller;
import net.infopeers.restrant.ControllerServlet;
import net.infopeers.restrant.Method;
import net.infopeers.restrant.Params;
import net.infopeers.restrant.Request;
import net.infopeers.restrant.ResourceNotFoundException;
import net.infopeers.restrant.util.AnnotationUtils;
import net.infopeers.util.Convertor;

/**
* リフレクションを利用したInvoker
*
* @author ms2
*
*/
public class ReflectInvoker implements Invoker {

  private static final Logger logger = Logger.getLogger(ReflectInvoker.class
      .getName());

  private Controller controller;

  private java.lang.reflect.Method method;

  private Params params;

  private String[] argLabels; // 引数となるプレースホルダ

  private ControllerServlet servlet; //サーブレット

  /**
   * コンストラクタ
   * @param servlet ControllerServlet
   * @param controller Controller
   * @param methodName コールするメソッド名
   * @param params パラメータ
   * @throws ResourceNotFoundException
   */
  public ReflectInvoker(ControllerServlet servlet, Controller controller, String methodName,
      Params params) throws ResourceNotFoundException{
    this.servlet = servlet;
    this.controller = controller;
    this.params = params;

    this.method = getMethod(controller, methodName);
  }

  private java.lang.reflect.Method getMethod(Controller controller,
      String methodName) throws ResourceNotFoundException {
    Class<?> cls = controller.getClass();

    Set<String> exNames = params.getExtensionNames();
    removeCorePlaceholders(exNames);

    // 名前が一致し、引数なしのメソッドをデフォルトとして扱う。
    // 引数まで完全に一致しない場合にはこれが呼ばれる。
    java.lang.reflect.Method defaultMethod = null;
   
    java.lang.reflect.Method methods[] = cls.getMethods();
    for (int i = 0; i < methods.length; ++i) {

      java.lang.reflect.Method method = methods[i];
      Method ma = method.getAnnotation(Method.class);
     
      if (ma == null) {
        String name = method.getName();
        if(!name.equals(methodName)){
          continue;
        }
       
        argLabels = new String[] {};
       
      } else {
        String name = (ma.name().equals(""))? method.getName() : ma.name();
        if(!name.equals(methodName)){
          continue;
        }
       
//        argLabels = ma.value();// 直接配列が指定されているケース
//       
//        //指定がデフォルトの可能性があるなら
//        if (argLabels.length == 0) {
//          // ラベル指定
//          argLabels = ma.args();
//        }
       
        argLabels = AnnotationUtils.getArgs(ma);
      }

      //実際のパラメータの数と、アノテーションのラベルの数が一致しなければならない
      int parameterLen = AnnotationUtils.checkParameterLengthToAnnotationArgLabelLength(method, argLabels);
     
      if(parameterLen != exNames.size()){
        if(parameterLen == 0){
          defaultMethod = method;
        }
        continue;
      }

      for (int j = 0; j < argLabels.length; ++j) {
        if (!exNames.contains(argLabels[j])) {
          continue;
        }
      }
     
     
      return method;
    }
   
    if(defaultMethod == null){
      throw new ResourceNotFoundException("Method not found: " + cls.getName() + "#" + methodName);
    }
   
    return defaultMethod;
  }


  static void removeCorePlaceholders(Set<String> exNames) {
    exNames.remove(PatternInvokerBuilder.CONTROLLER_PLACEHOLDER_LABEL);
    exNames.remove(PatternInvokerBuilder.ACTION_PLACEHOLDER_LABEL);
  }

  /* (non-Javadoc)
   * @see net.infopeers.restrant.engine.Invoker#invoke(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
   */
  public void invoke(HttpServletRequest req, HttpServletResponse resp)
      throws Exception {

    controller.setServlet(servlet);
    controller.setRequest(req);
    controller.setResponse(resp);
    controller.setParams(params);

    setMembers(controller, req);

    Class<?>[] types = method.getParameterTypes();
    if (types.length == 0) {
      invoke(new Object[] {});
      return;
    }

    Object[] args = new Object[types.length];
    for (int i = 0; i < argLabels.length; ++i) {
      args[i] = params.asObject(types[i], argLabels[i]);
    }

    invoke(args);
  }

  private void invoke(Object[] args) throws Exception {
    String m = method.toString();
    logger.info("method: " + m);
    if(controller.beforeInvoke(m)){
      method.invoke(controller, args);
      controller.afterInvoke(m);
    }
  }

  private void setMembers(Object action, HttpServletRequest req) {

    for (Field field : action.getClass().getFields()) {
      Request annotation = field.getAnnotation(Request.class);
      if (annotation == null)
        continue;

      setValue(action, annotation, field);
    }
  }

  private void setValue(Object action, Request annotation, Field field) {

    String name = annotation.name();
    if (field.getType().isArray()) {
      String[] values = params.getParameters(name);
      if (values == null)
        return;

      try {
        field.set(action, values);
      } catch (Exception e) {
        handleParameterException(e, field, values);
      }
      return;
    }

    // 設定されていなければフィールドの名前を利用する
    if (name == null || name.length() == 0) {
      name = field.getName();
    }

    String value = params.get(name);

    if (value != null) {
      try {
        field.set(action, Convertor.convert(value, field.getType()));
      } catch (Exception e) {
        handleParameterException(e, field, value);
      }
    }
  }

  private void handleParameterException(Exception e, Field field, Object value) {
    logger.log(Level.INFO, "リクエストパラメータが設定出来ません:" + e.toString()
        + "\n[field]" + field.getName() + "\n[value]" + value, e);
  }

}
TOP

Related Classes of net.infopeers.restrant.engine.ReflectInvoker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.