Package com.taobao.top.analysis.node.monitor

Source Code of com.taobao.top.analysis.node.monitor.NHttpServer$HttpFileHandler

package com.taobao.top.analysis.node.monitor;

import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.StringWriter;
import java.io.Writer;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.HttpStatus;
import org.apache.http.MethodNotSupportedException;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.nio.DefaultHttpServerIODispatch;
import org.apache.http.impl.nio.DefaultNHttpServerConnection;
import org.apache.http.impl.nio.DefaultNHttpServerConnectionFactory;
import org.apache.http.impl.nio.reactor.DefaultListeningIOReactor;
import org.apache.http.nio.NHttpConnection;
import org.apache.http.nio.NHttpConnectionFactory;
import org.apache.http.nio.NHttpServerConnection;
import org.apache.http.nio.entity.NFileEntity;
import org.apache.http.nio.entity.NStringEntity;
import org.apache.http.nio.protocol.BasicAsyncRequestConsumer;
import org.apache.http.nio.protocol.BasicAsyncResponseProducer;
import org.apache.http.nio.protocol.HttpAsyncExchange;
import org.apache.http.nio.protocol.HttpAsyncRequestConsumer;
import org.apache.http.nio.protocol.HttpAsyncRequestHandler;
import org.apache.http.nio.protocol.HttpAsyncRequestHandlerRegistry;
import org.apache.http.nio.protocol.HttpAsyncService;
import org.apache.http.nio.reactor.IOEventDispatch;
import org.apache.http.nio.reactor.ListeningIOReactor;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.params.SyncBasicHttpParams;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.ImmutableHttpProcessor;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.resource.ResourceManagerImpl;

import com.taobao.top.analysis.config.MasterConfig;
import com.taobao.top.analysis.exception.AnalysisException;
import com.taobao.top.analysis.node.IComponent;
import com.taobao.top.analysis.node.component.MasterMonitor;


/**
* 使用apache http components的一个简单HttpServer
* @author sihai
*
*/
public class NHttpServer implements IComponent<MasterConfig>{

  private static final Log logger = LogFactory.getLog(NHttpServer.class);
 
  /**
   * Master端配置
   */
  private MasterConfig config;
 
  /**
   * Master的监控组件, 提供监控数据
   */
  private MasterMonitor monitor;
 
  /**
   * 模板编码
   */
  private String templateEncode = "utf-8";
 
  /**
   * 模板缓存
   */
  private ConcurrentHashMap<String, Template> templateCache;
 
  /**
   *
   */
  private boolean velocityOK = false;
 
  /**
   *
   */
  private ListeningIOReactor ioReactor;
 
  @Override
  public MasterConfig getConfig() {
    return config;
  }

  @Override
  public void init() throws AnalysisException {
   
    //
    templateCache = new ConcurrentHashMap<String, Template>();
   
    // 初始化模板引擎
    try {
      Velocity.setProperty(Velocity.RESOURCE_MANAGER_CLASS, ResourceManagerImpl.class.getName());
      Velocity.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, config.getMonitorDocRoot());
      Velocity.setProperty(Velocity.INPUT_ENCODING, "utf-8");
      Velocity.setProperty(Velocity.OUTPUT_ENCODING, "utf-8");
      Velocity.init();
      velocityOK = true;
    } catch (Exception e) {
      velocityOK = false;
      logger.error("Exception: init velocity:", e);
    }
    // init the server
   
    // HTTP parameters for the server
        HttpParams params = new SyncBasicHttpParams();
        params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
            .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
            .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
            .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpTest/1.1");
        // Create HTTP protocol processing chain
        HttpProcessor httpproc = new ImmutableHttpProcessor(new HttpResponseInterceptor[] {
                // Use standard server-side protocol interceptors
                new ResponseDate(),
                new ResponseServer(),
                new ResponseContent(),
                new ResponseConnControl()
        });
        // Create request handler registry
        HttpAsyncRequestHandlerRegistry reqistry = new HttpAsyncRequestHandlerRegistry();
        // Register the default handler for all URIs
        reqistry.register("*", new HttpFileHandler(new File(config.getMonitorDocRoot())));
        // Create server-side HTTP protocol handler
        HttpAsyncService protocolHandler = new HttpAsyncService(
                httpproc, new DefaultConnectionReuseStrategy(), reqistry, params) {

            @Override
            public void connected(final NHttpServerConnection conn) {
                System.out.println(conn + ": connection open");
                super.connected(conn);
            }

            @Override
            public void closed(final NHttpServerConnection conn) {
                System.out.println(conn + ": connection closed");
                super.closed(conn);
            }

        };
        // Create HTTP connection factory
        NHttpConnectionFactory<DefaultNHttpServerConnection> connFactory;
        connFactory = new DefaultNHttpServerConnectionFactory(params);
        // Create server-side I/O event dispatch
        final IOEventDispatch ioEventDispatch = new DefaultHttpServerIODispatch(protocolHandler, connFactory);
        // Create server-side I/O reactor
        new Thread(new Runnable(){
         
          @Override
          public void run() {
            try {
              ioReactor = new DefaultListeningIOReactor();
                  // Listen of the given port
                  ioReactor.listen(new InetSocketAddress(config.getMonitorPort()));
                  // Ready to go!
                  ioReactor.execute(ioEventDispatch);
              } catch (InterruptedIOException ex) {
                  System.err.println("Interrupted");
                  logger.error("NHttpServer failed", ex);
              } catch (IOException e) {
                  System.err.println("I/O error: " + e.getMessage());
                  logger.error("NHttpServer failed", e);
              }
          }
        }, "NHttp-Server-Thread").start();
  }

  @Override
  public void releaseResource() {
    templateCache.clear();
    if(ioReactor != null) {
      try {
        ioReactor.shutdown();
      } catch (IOException e) {
        logger.error(e);
      }
    }
  }

  @Override
  public void setConfig(MasterConfig config) {
    this.config = config;
  }
 
  public MasterMonitor getMonitor() {
    return monitor;
  }

  public void setMonitor(MasterMonitor monitor) {
    this.monitor = monitor;
  }
 
  /**
   *
   * @author sihai
   *
   */
  private class HttpFileHandler implements HttpAsyncRequestHandler<HttpRequest> {

        private final File docRoot;

        public HttpFileHandler(final File docRoot) {
            super();
            this.docRoot = docRoot;
        }

        public HttpAsyncRequestConsumer<HttpRequest> processRequest(
                final HttpRequest request,
                final HttpContext context) {
            // Buffer request content in memory for simplicity
            return new BasicAsyncRequestConsumer();
        }

        public void handle(
                final HttpRequest request,
                final HttpAsyncExchange httpexchange,
                final HttpContext context) throws HttpException, IOException {
            HttpResponse response = httpexchange.getResponse();
            handleInternal(request, response, context);
            httpexchange.submitResponse(new BasicAsyncResponseProducer(response));
        }

        private void handleInternal(
                final HttpRequest request,
                final HttpResponse response,
                final HttpContext context) throws HttpException, IOException {

            String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
            if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) {
                throw new MethodNotSupportedException(method + " method not supported");
            }

            String target = URLDecoder.decode(request.getRequestLine().getUri(), "UTF-8");
            if(target.endsWith(".jhtml")) {
              if(velocityOK) {
                Template template = templateCache.get(target);
                if(template == null) {
                  try {
                    String vmFileName = target.replace(".jhtml", ".vm").replace("/", "\\").substring(1);
                    final File file = new File(this.docRoot, target.replace(".jhtml", ".vm"));
                    if(!file.exists()) {
                      response.setStatusCode(HttpStatus.SC_NOT_FOUND);
                          NStringEntity entity = new NStringEntity(
                                  "<html><body><h1>File" + file.getPath() +
                                  " not found</h1></body></html>",
                                  ContentType.create("text/html", "UTF-8"));
                          response.setEntity(entity);
                          System.out.println("File " + file.getPath() + " not found");
                    } else {
                      template = Velocity.getTemplate(vmFileName, templateEncode);
                      //
                      templateCache.putIfAbsent(target, template);
                    }
                  } catch (Exception e) {
                    logger.error("Exception: get template", e);
                  }
                }
               
                // 渲染VM
                VelocityContext cxt = new VelocityContext();
                monitor.getData(cxt);
                Writer writer = new StringWriter();
                template.merge(cxt, writer);
                response.setStatusCode(HttpStatus.SC_OK);
                NStringEntity entity = new NStringEntity(writer.toString(), ContentType.create("text/html", "UTF-8"));
                response.setEntity(entity);
              } else {
                response.setStatusCode(HttpStatus.SC_NOT_FOUND);
                  NStringEntity entity = new NStringEntity("Velocity not init succeed",
                          ContentType.create("text/html", "UTF-8"));
                  response.setEntity(entity);
                  System.out.println("Velocity not init succeed");
              }
            } else {
              final File file = new File(this.docRoot, target);
              if (!file.exists()) {
                  response.setStatusCode(HttpStatus.SC_NOT_FOUND);
                  NStringEntity entity = new NStringEntity(
                          "<html><body><h1>File" + file.getPath() +
                          " not found</h1></body></html>",
                          ContentType.create("text/html", "UTF-8"));
                  response.setEntity(entity);
                  System.out.println("File " + file.getPath() + " not found");
 
              } else if (!file.canRead() || file.isDirectory()) {
 
                  response.setStatusCode(HttpStatus.SC_FORBIDDEN);
                  NStringEntity entity = new NStringEntity(
                          "<html><body><h1>Access denied</h1></body></html>",
                          ContentType.create("text/html", "UTF-8"));
                  response.setEntity(entity);
                  System.out.println("Cannot read file " + file.getPath());
 
              } else {
                NHttpConnection conn = (NHttpConnection) context.getAttribute(
                          ExecutionContext.HTTP_CONNECTION);
                  response.setStatusCode(HttpStatus.SC_OK);
                  NFileEntity body = new NFileEntity(file, ContentType.create("text/html"));
                  response.setEntity(body);
                  System.out.println(conn + ": serving file " + file.getPath());
              }
            }
        }
    }
}
TOP

Related Classes of com.taobao.top.analysis.node.monitor.NHttpServer$HttpFileHandler

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.