// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.consoleproxy;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

import com.cloud.consoleproxy.util.Logger;

public class ConsoleProxyResourceHandler implements HttpHandler {
    private static final Logger s_logger = Logger.getLogger(ConsoleProxyResourceHandler.class);

    static Map<String, String> s_mimeTypes;
    static {
        s_mimeTypes = new HashMap<String, String>();
        s_mimeTypes.put("jar", "application/java-archive");
        s_mimeTypes.put("js", "text/javascript");
        s_mimeTypes.put("css", "text/css");
        s_mimeTypes.put("jpg", "image/jpeg");
        s_mimeTypes.put("html", "text/html");
        s_mimeTypes.put("htm", "text/html");
        s_mimeTypes.put("log", "text/plain");
    }

    static Map<String, String> s_validResourceFolders;
    static {
        s_validResourceFolders = new HashMap<String, String>();
        s_validResourceFolders.put("applet", "");
        s_validResourceFolders.put("logs", "");
        s_validResourceFolders.put("images", "");
        s_validResourceFolders.put("js", "");
        s_validResourceFolders.put("css", "");
        s_validResourceFolders.put("html", "");
    }

    public ConsoleProxyResourceHandler() {
    }

    @Override
    public void handle(HttpExchange t) throws IOException {
        try {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Resource Handler " + t.getRequestURI());

            long startTick = System.currentTimeMillis();

            doHandle(t);

            if (s_logger.isDebugEnabled())
                s_logger.debug(t.getRequestURI() + " Process time " + (System.currentTimeMillis() - startTick) + " ms");
        } catch (IOException e) {
            throw e;
        } catch (Throwable e) {
            s_logger.error("Unexpected exception, ", e);
            t.sendResponseHeaders(500, -1);     // server error
        } finally {
            t.close();
        }
    }

    @SuppressWarnings("deprecation")
    private void doHandle(HttpExchange t) throws Exception {
        String path = t.getRequestURI().getPath();

        if (s_logger.isInfoEnabled())
            s_logger.info("Get resource request for " + path);

        int i = path.indexOf("/", 1);
        String filepath = path.substring(i + 1);
        i = path.lastIndexOf(".");
        String extension = (i == -1) ? "" : path.substring(i + 1);
        String contentType = getContentType(extension);

        if (!validatePath(filepath)) {
            if (s_logger.isInfoEnabled())
                s_logger.info("Resource access is forbidden, uri: " + path);

            t.sendResponseHeaders(403, -1);     // forbidden
            return;
        }

        File f = new File("./" + filepath);
        if (f.exists()) {
            long lastModified = f.lastModified();
            String ifModifiedSince = t.getRequestHeaders().getFirst("If-Modified-Since");
            if (ifModifiedSince != null) {
                long d = Date.parse(ifModifiedSince);
                if (d + 1000 >= lastModified) {
                    Headers hds = t.getResponseHeaders();
                    hds.set("Content-Type", contentType);
                    t.sendResponseHeaders(304, -1);

                    if (s_logger.isInfoEnabled())
                        s_logger.info("Sent 304 file has not been " + "modified since " + ifModifiedSince);
                    return;
                }
            }

            long length = f.length();
            Headers hds = t.getResponseHeaders();
            hds.set("Content-Type", contentType);
            hds.set("Last-Modified", new Date(lastModified).toGMTString());
            t.sendResponseHeaders(200, length);
            responseFileContent(t, f);

            if (s_logger.isInfoEnabled())
                s_logger.info("Sent file " + path + " with content type " + contentType);
        } else {
            if (s_logger.isInfoEnabled())
                s_logger.info("file does not exist" + path);
            t.sendResponseHeaders(404, -1);
        }
    }

    private static String getContentType(String extension) {
        String key = extension.toLowerCase();
        if (s_mimeTypes.containsKey(key)) {
            return s_mimeTypes.get(key);
        }
        return "application/octet-stream";
    }

    private static void responseFileContent(HttpExchange t, File f) throws Exception {
        OutputStream os = t.getResponseBody();
        FileInputStream fis = new FileInputStream(f);
        while (true) {
            byte[] b = new byte[8192];
            int n = fis.read(b);
            if (n < 0) {
                break;
            }
            os.write(b, 0, n);
        }
        fis.close();
        os.close();
    }

    private static boolean validatePath(String path) {
        int i = path.indexOf("/");
        if (i == -1) {
            if (s_logger.isInfoEnabled())
                s_logger.info("Invalid resource path: can not start at resource root");
            return false;
        }

        if (path.contains("..")) {
            if (s_logger.isInfoEnabled())
                s_logger.info("Invalid resource path: contains relative up-level navigation");

            return false;
        }

        return isValidResourceFolder(path.substring(0, i));
    }

    private static boolean isValidResourceFolder(String name) {
        return s_validResourceFolders.containsKey(name);
    }
}
