// 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.cloud.consoleproxy.util.Logger;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

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() {
	}
	
	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); 
	}
}
