Package net.infopeers.restrant

Source Code of net.infopeers.restrant.ControllerServlet

package net.infopeers.restrant;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.infopeers.restrant.engine.PatternInvokerBuilderFactory;
import net.infopeers.restrant.engine.PrefixedPlaceholderFormatter;
import net.infopeers.restrant.engine.Invoker;
import net.infopeers.restrant.engine.InvokerBuilderFactory;
import net.infopeers.restrant.engine.PlaceholderFormatter;
import net.infopeers.restrant.engine.jsservice.JsServiceInvokerBuilderFactory;
import net.infopeers.restrant.engine.params.ExtensionMultimapFactory;
import net.infopeers.restrant.engine.parser.CompositeUrlParserArranger;
import net.infopeers.restrant.engine.parser.PatternParserArranger;
import net.infopeers.restrant.route.RouteClassUrlParserArranger;
import net.infopeers.restrant.util.ServletConfigUrlParserArranger;

/**
* このシステムのサーブレット
*
* @author ms2
*
*/
@SuppressWarnings("serial")
public class ControllerServlet extends HttpServlet {

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

  private static final String ROOT_PACKAGE_LABEL = "RootPackage"; // Web.xmlのルートパッケージ指定ラベル
  private static final String ROUTE_CLASS_LABEL = "RouteClass"; // Web.xmlのRouteクラス指定ラベル
  private static final String SERVICE_JS_LABEL = "ServiceJs"; // Web.xmlのJavaScriptサービス指定ラベル
  private static final String SERVICE_JS_NAMESPACE_LABEL = "ServiceJsNamespace"; // Web.xmlのJavaScriptでJSのネームスペース指定ラベル

  private static final String ENCODING = "Encoding"; // Web.xmlのエンコーディング指定ラベル

  private PlaceholderFormatter phFormatter = new PrefixedPlaceholderFormatter();

  private static final String ibfDefaultName = ":default"; // 将来的にはパス→実装クラス対応か?
  private Map<String, InvokerBuilderFactory> path2ibf = new HashMap<String, InvokerBuilderFactory>();

  /*
   * (non-Javadoc)
   *
   * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
   */
  public void init(ServletConfig config) throws ServletException {
    super.init(config);

    try {
      initInvokerBuilder(config);
    } catch (MalformedURLException e) {
      throw new ServletException(e);
    }
  }

  private void initInvokerBuilder(ServletConfig config)
      throws MalformedURLException {

    String rootPackage = config.getInitParameter(ROOT_PACKAGE_LABEL);
    if (rootPackage == null) {
      throw new RuntimeException(
          "document(web.xml)/web-app/servlet/init-paramに"
              + ROOT_PACKAGE_LABEL
              + "の指定でコントローラーの格納されたパッケージを設定してください。");
    }

    PatternParserArranger parserArranger = createParserArranger(config);
    ExtensionMultimapFactory exPolicy = createExtensionPolicy();
    path2ibf.put(ibfDefaultName, new PatternInvokerBuilderFactory(
        rootPackage, parserArranger, exPolicy));

    String serviceJsPath = config.getInitParameter(SERVICE_JS_LABEL);
    if (serviceJsPath != null) {

      String serviceJsNamespace = config
          .getInitParameter(SERVICE_JS_NAMESPACE_LABEL);
      path2ibf.put(serviceJsPath, new JsServiceInvokerBuilderFactory(
          getServletContext().getContextPath(), rootPackage, parserArranger, serviceJsNamespace,
          phFormatter));
    }

  }

  private CompositeUrlParserArranger createParserArranger(ServletConfig config) {
    CompositeUrlParserArranger arranger = new CompositeUrlParserArranger();

    String routeClass = config.getInitParameter(ROUTE_CLASS_LABEL);
    if (routeClass != null) {
      try {
        Class<?> cls = Class.forName(routeClass);
        RouteClassUrlParserArranger cdarranger = new RouteClassUrlParserArranger(
            phFormatter, cls);
        arranger.add(cdarranger);
      } catch (ClassNotFoundException e) {
        throw new RuntimeException(
            "document(web.xml)/web-app/servlet/init-paramに"
                + ROUTE_CLASS_LABEL + "で指定されたクラスが見つかりません。", e);
      }
    }

    arranger.add(new ServletConfigUrlParserArranger(phFormatter, config));
    return arranger;
  }

  private ExtensionMultimapFactory createExtensionPolicy() {
    Map<String, String> multimap2exPolicy = new HashMap<String, String>();
    multimap2exPolicy
        .put("com.google.appengine.repackaged.com.google.common.collect.ArrayListMultimap",
            "net.infopeers.restrant.util.gae.GaeExtensionMultimapFactory");
    multimap2exPolicy
        .put("com.google.common.collect.ArrayListMultimap",
            "net.infopeers.restrant.util.GoogleCollectionExtensionMultimapFactory");

    ExtensionMultimapFactory exPolicy = null;
    for (String key : multimap2exPolicy.keySet()) {
      try {
        Class.forName(key);
        try {
          exPolicy = (ExtensionMultimapFactory) Class.forName(
              multimap2exPolicy.get(key)).newInstance();
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      } catch (ClassNotFoundException e) {
        // continue;
      }
    }

    if (exPolicy == null) {
      throw new IllegalStateException(
          "GoogleCollection's ArrayListMultimap was not found.");
    }
    return exPolicy;
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest
   * , javax.servlet.http.HttpServletResponse)
   */
  public void service(HttpServletRequest req, HttpServletResponse resp)
      throws IOException {

    String enc = getServletConfig().getInitParameter(ENCODING);
    if (enc != null) {
      req.setCharacterEncoding(enc);
    }

    beforeExecute(req, resp);

    if (logger.isLoggable(Level.INFO)) {
      outputRequest(req);
    }

    try {
      Invoker invoker = getInvoker(req);
      invoker.invoke(req, resp);
    } catch (ResourceNotFoundException e) {
      logger.log(Level.WARNING, e.getMessage(), e);
      resp.sendError(HttpServletResponse.SC_NOT_FOUND);
    } catch (Exception e) {
      logger.log(Level.WARNING, e.getMessage(), e);
      resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    } finally {
      afterExecute(req, resp);
    }
  }

  private Invoker getInvoker(HttpServletRequest req)
      throws ResourceNotFoundException, MalformedURLException {

    String path = req.getRequestURI().substring(
        req.getContextPath().length());
    InvokerBuilderFactory factory = path2ibf.get(path);
    if (factory == null) {
      factory = path2ibf.get(ibfDefaultName);
    }

    // TODO: 柔軟にするには切り出す。本来は初期化時に行えれば良い
    URL url = new URL(req.getRequestURL().toString());
    String host = url.getHost();
    factory.setEvery(host.equals("localhost"));

    Invoker invoker = factory.getInvokerBuilder().build(this, req);
    return invoker;
  }

  @SuppressWarnings("unchecked")
  private void outputRequest(HttpServletRequest req) {
    logger.info(req.getRequestURL().toString());
    Enumeration<String> nameEnum = req.getParameterNames();
    while (nameEnum.hasMoreElements()) {
      String name = nameEnum.nextElement();
      String[] values = req.getParameterValues(name);
      for (int i = 0; i < values.length; ++i) {
        logger.info("param[" + name + "]=" + values[i]);
      }
    }
  }

  /**
   * 処理を開始する際に必ず呼ばれる
   *
   * @param req
   * @param resp
   * @throws IOException
   */
  protected void beforeExecute(HttpServletRequest req,
      HttpServletResponse resp) throws IOException {

  }

  /**
   * 処理が終了した際に必ず呼ばれる
   *
   * @param req
   * @param resp
   */
  protected void afterExecute(HttpServletRequest req, HttpServletResponse resp) {
  }

}
TOP

Related Classes of net.infopeers.restrant.ControllerServlet

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.