Package com.google.appengine.tools.appstats

Source Code of com.google.appengine.tools.appstats.AppstatsServlet

// Copyright 2009 Google Inc. All Rights Reserved.

package com.google.appengine.tools.appstats;

import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.tools.appstats.Recorder.Clock;
import com.google.appengine.tools.appstats.StatsProtos.RequestStatProto;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

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

/**
* A servlet that can be used to render statistics to the user.
*
*/
@SuppressWarnings("serial")
public class AppstatsServlet extends HttpServlet {

  private static final String PREFIX = "/apphosting/ext/appstats/static/";

  private static final Map<String, String> CONTENT_TYPES;
  static {
    Map<String, String> contentTypes = new HashMap<String, String>();
    contentTypes.put("css", "text/css");
    contentTypes.put("js", "application/javascript");
    contentTypes.put("gif", "image/gif");
    CONTENT_TYPES = Collections.unmodifiableMap(contentTypes);

  }

  private boolean requireAdminAuthentication = true;
  private final MemcacheWriter memcache;
  private final Renderer renderer;
  Clock clock = new Clock();

  AppstatsServlet(MemcacheWriter writer, Renderer renderer) {
    this.memcache = writer;
    this.renderer = renderer;
  }

  public AppstatsServlet() {
    this(
        new MemcacheWriter(
            new Clock(), MemcacheServiceFactory.getMemcacheService(MemcacheWriter.STATS_NAMESPACE)),
        new Renderer());
  }

  @Override
  public void init(ServletConfig config) throws ServletException {
    String requireAuthParam = config.getInitParameter("requireAdminAuthentication");
    if (requireAuthParam != null) {
      requireAdminAuthentication = "yes".equalsIgnoreCase(requireAuthParam)
          || "true".equalsIgnoreCase(requireAuthParam);
    }
  }

  private boolean requireAdminAuthentication(UserService userService,
      HttpServletRequest req, HttpServletResponse resp) throws IOException {
    if (!requireAdminAuthentication) {
      return true;
    }

    if (!userService.isUserLoggedIn()) {
      resp.sendRedirect(userService.createLoginURL(req.getRequestURI()));
      return false;
    }

    if (!userService.isUserAdmin()) {
      resp.sendError(HttpServletResponse.SC_FORBIDDEN);
      return false;
    }

    return true;
  }

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    String path = req.getPathInfo();

    if (path == null) {

      resp.sendRedirect(req.getServletPath() + "/stats");
    } else if (path.startsWith("/static/")) {

      serveStaticContent(req, resp);
    } else if (path.equals("/details")) {

      RequestStatProto data;
      try {
        long asTimeStamp = Long.parseLong(req.getParameter("time"));
        data = memcache.getFull(asTimeStamp);
      } catch (NumberFormatException e) {
        data = null;
      }
      if (data == null) {
        resp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }

      authenticateAndServeDetails(data, req, resp);
    } else if (path.equals("/stats")) {

      if (!requireAdminAuthentication(UserServiceFactory.getUserService(), req, resp)) {
        return;
      }
      renderer.renderSummaries(resp.getWriter(), memcache.getSummaries());
    } else {

      resp.sendRedirect(req.getServletPath() + "/stats");
    }
  }

  /**
   * Helper: Checks authentication as needed and renders the details view, either
   * as HTML or JSON depending on the contents of the query string.
   */
  private void authenticateAndServeDetails(RequestStatProto data, HttpServletRequest req,
      HttpServletResponse resp) throws IOException {
    String type = req.getParameter("type");

    UserService userService = UserServiceFactory.getUserService();
    if (type == null) {
      if (requireAdminAuthentication(userService, req, resp)) {
        renderer.renderDetails(resp.getWriter(), data);
      }
      return;
    }

    if ("json".equalsIgnoreCase(type)) {
      if (requireAdminAuthentication(userService, req, resp)) {
        resp.setContentType("application/json");
        renderer.renderDetailsAsJson(resp.getWriter(), data);
      } else {
        resp.sendError(HttpServletResponse.SC_FORBIDDEN);
      }
      return;
    }

    resp.sendError(HttpServletResponse.SC_NOT_FOUND);
  }

  /**
   * Helper: loads static content bundled with this class and serves it as part
   * of this servlet.
   */
  void serveStaticContent(HttpServletRequest req, HttpServletResponse resp) throws IOException {

    String resource = req.getRequestURI();
    resource = PREFIX + resource.substring(resource.lastIndexOf('/') + 1);
    URL byName = AppstatsServlet.class.getResource(resource);
    if (byName == null) {
      resp.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    if (resource.lastIndexOf('.') < 0) {
      resp.sendError(HttpServletResponse.SC_NOT_FOUND);
    }
    String ext = resource.substring(resource.toLowerCase().lastIndexOf('.') + 1);
    if (!CONTENT_TYPES.containsKey(ext)) {
      resp.sendError(HttpServletResponse.SC_NOT_FOUND);
    }

    resp.addHeader("Content-type", CONTENT_TYPES.get(ext));
    resp.addHeader("Cache-Control", "public, max-age=expiry");
    SimpleDateFormat httpDateFormat = new SimpleDateFormat(
        "EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
    httpDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
    resp.addHeader("Expires", httpDateFormat.format(
        new Date(clock.currentTimeMillis() + 3600000L)));

    ServletOutputStream out = resp.getOutputStream();
    InputStream in = byName.openStream();
    try {
      byte[] b = new byte[256];
      int len = in.read(b);
      while (len > 0) {
        out.write(b, 0, len);
        len = in.read(b);
      }
    } finally {
      try {
        in.close();
      } finally {
        out.close();
      }
    }
  }
}
TOP

Related Classes of com.google.appengine.tools.appstats.AppstatsServlet

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.