Package org.eweb4j.mvc.config

Source Code of org.eweb4j.mvc.config.ActionAnnotationConfig

package org.eweb4j.mvc.config;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import org.eweb4j.cache.ActionConfigBeanCache;
import org.eweb4j.cache.Props;
import org.eweb4j.cache.SingleBeanCache;
import org.eweb4j.config.LogFactory;
import org.eweb4j.mvc.action.annotation.ActionLevel;
import org.eweb4j.mvc.action.annotation.Controller;
import org.eweb4j.mvc.action.annotation.Result;
import org.eweb4j.mvc.action.annotation.ShowValMess;
import org.eweb4j.mvc.action.annotation.Singleton;
import org.eweb4j.mvc.action.annotation.ValField;
import org.eweb4j.mvc.action.annotation.ValMess;
import org.eweb4j.mvc.action.annotation.ValParam;
import org.eweb4j.mvc.action.annotation.ValParamName;
import org.eweb4j.mvc.action.annotation.Validator;
import org.eweb4j.mvc.config.bean.ActionConfigBean;
import org.eweb4j.mvc.config.bean.ResultConfigBean;
import org.eweb4j.mvc.config.bean.ValidatorConfigBean;
import org.eweb4j.mvc.config.creator.ValidatorUtil;
import org.eweb4j.util.FileUtil;
import org.eweb4j.util.ReflectUtil;
import org.eweb4j.util.StringUtil;

public class ActionAnnotationConfig {
  /**
   * action注解
   *
   * @param cb
   * @return
   */
  public static String readAnnotation(List<String> scanPackages) {
    String error = null;

    try {
      if (scanPackages == null)
        return error;

      for (String scanPackage : scanPackages) {
        if (scanPackage == null || scanPackage.length() == 0)
          continue;

        // 扫描jar包
        String jarPath = FileUtil.getJarPath();
        scanPackage(jarPath, scanPackage);

        String classDir = FileUtil
            .getTopClassPath(ActionAnnotationConfig.class);

        scanDir(scanPackage, classDir);

        String classDir2 = FileUtil.getClassPath("classes");

        scanDir(scanPackage, classDir2);
      }

    } catch (Exception e) {
      error = StringUtil.getExceptionString(e);
      LogFactory.getMVCLogger("ERROR").write(error);
    }

    return error;
  }

  private static void scanDir(String scanPackage, String classDir)
      throws Exception {
    File dir = null;
    if (".".equals(scanPackage)) {
      scanPackage = "";
      dir = new File(classDir);
    } else
      dir = new File(classDir + File.separator
          + scanPackage.replace(".", File.separator));

    LogFactory.getMVCLogger("INFO").write("scan " + dir);
    // 递归文件目录
    if (dir.isDirectory())
      scanPackage(dir, scanPackage);
  }

  /**
   * 扫描action文件
   *
   * @param dir
   * @param actionPackage
   * @throws Exception
   */
  private static void scanPackage(File dir, String actionPackage)
      throws Exception {
    if (!dir.isDirectory())
      return;

    File[] files = dir.listFiles();
    if (files == null || files.length == 0)
      return;
    for (File f : files) {

      if (f.isDirectory())
        if (actionPackage.length() == 0)
          scanPackage(f, f.getName());
        else
          scanPackage(f, actionPackage + "." + f.getName());

      else if (f.isFile()) {
        if (!f.getName().endsWith(".class"))
          continue;

        StringBuilder sb = new StringBuilder(actionPackage);
        int endIndex = f.getName().lastIndexOf(".");

        String clsName = sb.append(".")
            .append(f.getName().subSequence(0, endIndex))
            .toString();

        if (clsName == null || "".equals(clsName))
          continue;

        if (clsName.startsWith("."))
          clsName = clsName.substring(1);

        handleActionClass(clsName);
      }
    }
  }

  /**
   * scan package by jars
   *
   * @param jarsParentDirPath
   * @param packageName
   * @throws Exception
   */
  public static void scanPackage(String jarsParentDirPath, String packageName) {
    String path = jarsParentDirPath;
    LogFactory.getMVCLogger("INFO").write("scan " + path + " for jars");
    File[] ff = new File(path).listFiles();
    if (ff == null)
      return;

    for (File f : ff) {
      ZipInputStream zin = null;
      ZipEntry entry = null;
      try {
        zin = new ZipInputStream(new FileInputStream(f));

        LogFactory.getMVCLogger("INFO").write(
            "scanning " + f.getAbsolutePath());

        while ((entry = zin.getNextEntry()) != null) {
          String entryName = entry.getName().replace('/', '.');
          if (".".equals(packageName)
              || entryName.startsWith(packageName))
            handleActionClass(entryName.replace(".class", ""));

          zin.closeEntry();

        }
        zin.close();
      } catch (Error e) {
        continue;
      } catch (Exception e) {
        continue;
      }
    }
  }

  /**
   * handle action class
   *
   * @param clsName
   * @throws Exception
   */
  private static void handleActionClass(String clsName) {

    Class<?> cls = null;
    try {
      cls = Class.forName(clsName);

      if (cls == null)
        return;

      if (cls.getAnnotation(Controller.class) == null
          && !clsName.endsWith("Controller")
          && !clsName.endsWith("Action")
          && !clsName.endsWith("Control"))
        return;

      Object obj = null;
      try {
        if (cls.getAnnotation(Singleton.class) != null) {
          obj = SingleBeanCache.get(cls);
          if (obj == null) {
            obj = cls.newInstance();
            SingleBeanCache.add(cls, obj);
          }
        } else
          obj = cls.newInstance();

      } catch (Exception e) {
        LogFactory.getMVCLogger("WARRING").write(
            "the action class new instance failued -> " + clsName);
      }

      ReflectUtil ru = new ReflectUtil(obj);
      Method[] ms = ru.getMethods();
      if (ms == null)
        return;

      // 扫描方法的注解信息
      for (Method m : ms) {
        if (m.getModifiers() != 1)
          continue;

        Path path = m.getAnnotation(Path.class);

        if (path == null) {
          String methodName = m.getName();
          Method getter = ru.getGetter(methodName.replace("get", ""));
          Method setter = ru.getSetter(methodName.replace("set", ""));
          // 默认下setter和getter不作为action方法
          if (getter != null || setter != null)
            continue;
        }

        readMethodAnnotation(ru, cls, m);
      }
    } catch (Error e) {
      return;
    } catch (Exception e) {
      return;
    }
  }

  /**
   * 读取方法里的注解
   *
   * @param cls
   * @param m
   * @throws Exception
   */
  private static void readMethodAnnotation(ReflectUtil ru, Class<?> cls,
      Method m) {
    String methodName = m.getName();
    String fullName = cls.getName() + "." + methodName;
    LogFactory.getMVCLogger("INFO").write(
        "read action.method --> " + fullName);

    String methodReqMapVal = null;

    Path m_path = m.getAnnotation(Path.class);
    if (m_path != null) {
      methodReqMapVal = StringUtil.parsePropValue(m_path.value());
    } else if (methodName.startsWith("do")) {
      methodReqMapVal = methodName.substring("do".length());
      methodReqMapVal = StringUtil.toLowCaseFirst(methodReqMapVal);
      methodReqMapVal = StringUtil.hump2ohter(methodReqMapVal, "-");
    } else {
      String info = fullName
          + " does not starts with 'do' so that can not be a valid action uri mapping";
      LogFactory.getMVCLogger("INFO").write(info);
      return;
    }

    final String GET = HttpMethod.GET;
    final String POST = HttpMethod.POST;
    final String PUT = HttpMethod.PUT;
    final String DELETE = HttpMethod.DELETE;

    String[] methods = new String[4];
    methods[0] = cls.getAnnotation(GET.class) != null ? GET : "";
    methods[1] = cls.getAnnotation(POST.class) != null ? POST : "";
    methods[2] = cls.getAnnotation(DELETE.class) != null ? DELETE : "";
    methods[3] = cls.getAnnotation(PUT.class) != null ? PUT : "";

    StringBuilder m_sb = new StringBuilder("");
    for (String s : methods) {
      if (m_sb.length() > 0 && s.length() > 0)
        m_sb.append("|");

      m_sb.append(s);
    }

    String controlMethod = m_sb.toString();
    ShowValMess cls_vm = cls.getAnnotation(ShowValMess.class);
    String controlShowValErr = cls_vm == null ? "alert" : cls_vm.value();

    controlShowValErr = StringUtil.parsePropValue(controlShowValErr);

    String clazzName = cls.getName();

    String reqMethod = controlMethod.length() == 0 ? GET + "|" + POST + "|"
        + PUT + "|" + DELETE : controlMethod;// 默认四种HTTP方法都支持
    String valErrType = controlShowValErr.trim().length() == 0 ? "alert"
        : controlShowValErr;// 验证器验证信息输出方式默认”alert“

    String[] _methods = new String[4];
    _methods[0] = m.getAnnotation(GET.class) != null ? GET : "";
    _methods[1] = m.getAnnotation(POST.class) != null ? POST : "";
    _methods[2] = m.getAnnotation(DELETE.class) != null ? DELETE : "";
    _methods[3] = m.getAnnotation(PUT.class) != null ? PUT : "";

    StringBuilder _sb = new StringBuilder("");
    for (String s : _methods) {
      if (_sb.length() > 0 && s.length() > 0)
        _sb.append("|");

      _sb.append(s);
    }
    String m_reqMethod = _sb.toString();

    reqMethod = m_reqMethod.trim().length() > 0 ? m_reqMethod : reqMethod;

    ShowValMess m_vm = m.getAnnotation(ShowValMess.class);
    valErrType = m_vm == null ? "alert" : m_vm.value();

    controlShowValErr = StringUtil.parsePropValue(valErrType);

    // Action properties
    String propId = cls.getName();
    Hashtable<String, String> props = Props.getMap(propId);
    String parentPath = null;
    String path = null;
    String method = null;
    String showValMess = null;
    String retn = null;
    ResultConfigBean rcb = null;

    Path cls_path = cls.getAnnotation(Path.class);
    String controlReqMapVal = cls_path == null ? "" : cls_path.value();

    controlReqMapVal = StringUtil.parsePropValue(controlReqMapVal);

    if (controlReqMapVal.length() > 0 && !methodReqMapVal.startsWith("/"))
      controlReqMapVal = controlReqMapVal + "/";

    String actionName = controlReqMapVal + methodReqMapVal;
    if (actionName.startsWith("/"))
      actionName = actionName.substring(1);
    if (actionName.endsWith("/"))
      actionName = actionName.substring(0, actionName.length() - 1);

    if (props != null) {

      path = props.get(methodName + ".path");
      String _path = path == null ? methodReqMapVal : path;

      parentPath = props.get("path");
      String _parentPath = parentPath == null ? controlReqMapVal
          : parentPath;

      actionName = _parentPath + _path;

      method = props.get(methodName + ".method");
      reqMethod = method == null ? reqMethod : method;
      showValMess = props.get(methodName + ".showValMess");
      retn = props.get(methodName + ".return");
      rcb = null;
      if (retn != null) {
        rcb = new ResultConfigBean();
        rcb.setName("_props_");
        if (retn.startsWith("redirect:")) {
          rcb.setType(MVCConfigConstant.REDIRECT_TYPE);
          rcb.setLocation(retn.replace("redirect:", ""));
        } else if (retn.startsWith("forward:")) {
          rcb.setType(MVCConfigConstant.FORWARD_TYPE);
          rcb.setLocation(retn.replace("forward:", ""));
        } else if (retn.equalsIgnoreCase("null")
            || retn.equalsIgnoreCase(MVCConfigConstant.AJAX_TYPE)) {
          rcb.setType(MVCConfigConstant.AJAX_TYPE);
        } else if (retn.equalsIgnoreCase("action:")) {
          rcb.setType(MVCConfigConstant.ACTION_TYPE);
          rcb.setLocation(retn.replace("action:", ""));

        } else if (retn.startsWith("out:")) {
          rcb.setType(MVCConfigConstant.OUT_TYPE);
          rcb.setLocation(retn.replace("out:", ""));
        } else if (retn.equalsIgnoreCase(MVCConfigConstant.JSON_TYPE)) {
          rcb.setType(MVCConfigConstant.JSON_TYPE);
        } else {
          rcb.setType(MVCConfigConstant.FORWARD_TYPE);
          rcb.setLocation(retn);
        }
      }
    }
    ActionConfigBean action = new ActionConfigBean();
    action.setShowValErrorType(showValMess == null ? valErrType
        : showValMess);
    action.setClazz(clazzName);
    action.setMethod(methodName);
    action.setName(actionName);
    action.setReqMethod(reqMethod);

    // 读取@ActionLevel注解
    ActionLevel actionLevel = cls.getAnnotation(ActionLevel.class);
    if (actionLevel == null)
      actionLevel = m.getAnnotation(ActionLevel.class);
    int level = 1;
    if (actionLevel != null)
      level = actionLevel.value();

    action.setLevel(String.valueOf(level));

    // 读取@Produces注解
    Produces producesAnn = m.getAnnotation(Produces.class);
    if (producesAnn != null) {
      String producesStr = StringUtil
          .parsePropValue(producesAnn.value()[0]);
      action.getProduces().add(producesStr);
    }

    // 读取@Result注解
    Result resultAnn = m.getAnnotation(Result.class);
    if (resultAnn != null)
      action.setResult(ResultAnnUtil.readResultAnn(resultAnn));

    if (rcb != null)
      action.getResult().add(rcb);

    // 读取@Validator注解
    Validator validatorAnn = m.getAnnotation(Validator.class);
    if (validatorAnn != null)
      action.setValidator(ValidatorUtil.readValidator(validatorAnn,
          m.getAnnotation(ValField.class),
          m.getAnnotation(ValMess.class),
          m.getAnnotation(ValParamName.class),
          m.getAnnotation(ValParam.class)));

    // 读取Action object 的属性 验证信息
    List<ValidatorConfigBean> vals = ValidatorUtil.readValidator(null, ru,
        null, null);
    if (vals != null)
      action.setValidator(vals);

    // Action全名,框架用,包括对“{xxx}”url参数的正则化,HttpRequestMethod
    String actionFullName = ActionUrlUtil.mathersUrlMapping(m, actionName,
        cls);
    if (actionFullName == null)
      return;

    if (actionFullName.endsWith("/")) {
      actionFullName.substring(0, actionFullName.length() - 1);
    }

    actionFullName = actionFullName + "@" + reqMethod;

    // 将读取成功的配置信息放入缓存供框架运行期使用
    ActionConfigBeanCache.add(actionFullName, action);
    ActionClassCache.add(clazzName, cls);
  }
}
TOP

Related Classes of org.eweb4j.mvc.config.ActionAnnotationConfig

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.