// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
// 
// Automatically generated by addcopyright.py at 04/03/2012
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); 
	}
}
