import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.*;

import jet.cs.util.*;
import jet.server.api.*;
import jet.server.api.http.*;

/**
 * This is a servlet Demo of viewing report as html pipeline format.
 * To run the Demo, it is necessary to update servlet.properties and mapping.properties under bin folder, e.g, 
 * "servlet.viewrpt.code=ViewHtmlPipelineServlet" in servlet.properties,
 * and "/viewrpt=viewrpt" in mapping.properties.
 * When viewing the report in browser, the url should be: http://localhost:8888/viewrpt.
 */
public class ViewHtmlPipelineServlet extends HttpServlet {
    
	private HttpRptServer httpRptServer = null;
	private String user = null;

	public void init(ServletConfig conf) throws ServletException {
        try {
			super.init(conf);
			//creates instance of RptServer
		    HttpUtil.initEnv(System.getProperties());
        } catch (ServletException se) {
			throw se;
        } catch (Throwable t) {
			t.printStackTrace();
        }
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
		// inits the RptServer
		httpRptServer = HttpUtil.getHttpRptServer(); 

		//set report properties
		Properties ht = new Properties(); 
		user = HttpUtil.getUser(request);
		if(user == null) user = "admin";
		if(user.length() == 0) user = "admin";
		String cat = "/SampleReports/SampleReports.cat"; 
		String rptName = "/SampleReports/EmployeeInformation.cls"; 
		int rstType = APIConst.HTML; 
		File rstFile = null;
		String rst = null; 
		String rstBase = null;

		try {
			// gets path information
			String path = request.getPathInfo();
		    if (path == null || path.length() == 0) {
			    path = "/";
			} else {
			    path = HttpUtil.decodeEsc(path);
			}
			
			ht = HttpUtil.getParameters(request);
			String cmd = (String)ht.get(APIConst.TAG_CMD);

			if (cmd != null && cmd.length() > 0) {
			    cmd = cmd.trim().toLowerCase();
			    if (cmd.equalsIgnoreCase(APIConst.CMD_OPEN_PIPELINE_HTML)) {
					rstBase = HttpUtil.getQueryBase(request, true);
			        int index = APIUtil.parseInt((String)ht.get("pgnum"), -1);
					String name = rstBase.substring(rstBase.lastIndexOf("/") + 1);
		            rstBase = rstBase.substring(0, rstBase.lastIndexOf("/") + 1);
		            String filename = httpRptServer.getFilenames(name, index);
					// get the path of request, such as 
					// "/viewrpt/SampleReports/SampleReports.cat/CustomerAnalysis.cls/result/14014655730_2.html", etc
		            rstBase += filename;
			        redirect(request, response, rstBase);
				} else if (cmd.equalsIgnoreCase(APIConst.CMD_AUTO_REFRESH_PAGE)) {
					// auto-refresh pipeline html
					responseAutoRefresh(request, response, ht);
				}
			} else {
				if (responsePaths(path, ht, request, response)) {
			        return;
				}
				// set catalog 
				ht.put(APIConst.TAG_CATALOG, cat);
				// set report file
			    ht.put(APIConst.TAG_REPORT, rptName);
				// set result type as .html format.
			    ht.put(APIConst.TAG_RESULT_TYPE, String.valueOf(rstType));
                ht.put(APIConst.TAG_IS_MULTI_FILES, String.valueOf("true"));
 
                // run report
    			rst = httpRptServer.runReportWithTimeouts(user, cat, rptName, ht, HttpUtil.getReportWaitTimeouts());
	    		if (rst != null) {
		     		rstFile = new File(rst);
					// register the result owner to pass security check
			        httpRptServer.getTempResultOwnerManager().registerOwner(user,
				    	HttpUtil.getTempResultKey(rstFile.getName())); 
				}

				// get the path of request, such as 
				// "/viewrpt/SampleReports/SampleReports.cat/CustomerAnalysis.cls/result/14014655730_1.html"
				String newRpt = rptName.substring(rptName.lastIndexOf("/") + 1, rptName.length());
		        rstBase = HttpUtil.getQueryBase(request, true) + cat + "/" + newRpt +
			    	APIConst.RESULT_PATH + HttpUtil.encodeEsc(rstFile.getName());
				redirect(request, response, rstBase);
			}
        } catch (Exception e) {
			e.printStackTrace();
		} catch (Throwable t) {
			t.printStackTrace();
		}
    } 

	/**
	 * redirect the request
	 */
	public void redirect(HttpServletRequest req, HttpServletResponse res, String location) throws Exception {
		String base = HttpUtil.getQueryBase(req, false);

        StringBuffer sb = new StringBuffer();
		println(sb, "<html>");
		println(sb, "<head>");
		println(sb, "<title>" + "viewrpt" + "</title>");
        println(sb, "</head>");

		println(sb, "<frameset framespacing=\"0\" border=\"false\" frameborder=\"0\" rows=\"1,*\">");
		println(sb, "  <frame name=\"hideframe\" scrolling=\"no\" noresize src=\"");
		println(sb, base + "?" + APIConst.TAG_CMD + "=" + 
                       APIConst.CMD_AUTO_REFRESH_PAGE + "&html=" + location + "\"");
		println(sb, " marginwidth=\"0\"");
		println(sb, " marginheight=\"0\">");
		println(sb, "  <frame name=\"clientarea\" src=\"" + location + "\"");
        println(sb, "  marginwidth=\"0\" marginheight=\"0\"");
		println(sb, "	noresize>");
        println(sb, "</frameset>");
		println(sb, "</html>");

		res.setContentType("text/html");
		res.setContentLength (sb.length());

		Writer writer = res.getWriter();
		writer.write(sb.toString());
		writer.close();
    }

	/**
	 * Judge the path validity, return true if the path is a valid one.
	 */
	private boolean responsePaths(String path, Properties ht, HttpServletRequest req, 
						   HttpServletResponse res) throws Throwable {
        boolean ret = true;
		String lcpath = path.toLowerCase();
		int ndx = lcpath.indexOf(APIConst.RESULT_PATH);
		if (ndx >= 0) {
			String rptPath = path.substring(0, ndx);
			String rptPath1 = rptPath.substring(rptPath.lastIndexOf("/") + 1, rptPath.length());
			String rptPath2 = rptPath.substring(0, rptPath.lastIndexOf("/"));
			if (rptPath2.length() == 0) {
				rptPath2 = "/";
			}
			if(httpRptServer.getResourceManager().getPathInfo(user, rptPath2).isCatalog()){
				rptPath2 = rptPath2.substring(0, rptPath2.lastIndexOf("/") + 1) + rptPath1;
			}else{
                rptPath2 = rptPath;
			}
            PathInfo pathInfo = httpRptServer.getResourceManager().getPathInfo(user, rptPath2); 
			if (pathInfo.isReport() || pathInfo.isResult()) {
				ht.put(APIConst.TAG_FILE, path.substring(ndx + APIConst.RESULT_PATH.length()));
				String sfile = (String)ht.get(APIConst.TAG_FILE);
				httpRptServer.getResourceManager().getTempDir();
                File file = new File(httpRptServer.getResourceManager().getTempDir() + sfile);
				sendFile(req, res, file);
			} else {
				ret = false;
			}
		} else {
			ret = false;
		}
		return ret;
	}

	public void sendFile(HttpServletRequest req, HttpServletResponse res, File rst) throws Exception {
        FileInputStream in = new FileInputStream(rst);

        byte buff[] = new byte[8192];
        try {
			int len = in.read(buff);
			if (len <= 0) {
				return;
			} else {
				res.setStatus(HttpServletResponse.SC_OK) ;
				res.setContentLength((int)rst.length());
				OutputStream out = res.getOutputStream();
				while (len > 0) {
					out.write(buff, 0, len);
					len = in.read(buff);
				}
				out.close();
			}
		} catch (Throwable t) {
			t.printStackTrace();
		}
		in.close();
	}

	/**
	 * auto-refresh the current html web page
	 */
	public void responseAutoRefresh(HttpServletRequest req, HttpServletResponse res, Properties ht) throws Exception {
        res.setStatus(HttpServletResponse.SC_OK);
		String html = (String)ht.get("html");
		int index = html.lastIndexOf("/");
		html = html.substring(index + 1);
		index = html.indexOf("_");
		if (index > 0) {
			html = html.substring(0, index);
		}

        StringBuffer sb = new StringBuffer();
        println(sb, "<html>");
	    println(sb, "<meta http-equiv=refresh content=20>");
		if (httpRptServer.canAutoRefresh(html)) {
			// if the html can be refreshed automatically, do it
			httpRptServer.setRefreshed(html, true);
			println(sb, "<body onload=\"parent.clientarea.location=parent.clientarea.location\">");
		} else {
			println(sb, "<body>");
		}
		println(sb, "</body>");
        println(sb, "</html>");

        res.setContentType("text/html");
		res.setContentLength (sb.length());

		Writer writer = res.getWriter();
		writer.write(sb.toString());
		writer.close();
	}

	private static void println(StringBuffer sb, String s) {
		sb.append(s).append("\n");
	}

	/**
	 *  The RptServer should be shut down when http server is shut down.
	 */
	public void destroy() {
	    httpRptServer = HttpUtil.getHttpRptServer(); 
		if (httpRptServer != null) {
			// shuts down the RptServer
			httpRptServer.shutdown();
		}
	}
}
