Modified: ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/htmlreport/HtmlReport.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/htmlreport/HtmlReport.java?rev=1774165&r1=1774164&r2=1774165&view=diff ============================================================================== --- ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/htmlreport/HtmlReport.java (original) +++ ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/htmlreport/HtmlReport.java Wed Dec 14 10:16:04 2016 @@ -1,1347 +1,1347 @@ -/******************************************************************************* - * 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 org.apache.ofbiz.htmlreport; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.Serializable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.ofbiz.base.util.Debug; -import org.apache.ofbiz.base.util.FileUtil; -import org.apache.ofbiz.base.util.StringUtil; -import org.apache.ofbiz.base.util.UtilHttp; -import org.apache.ofbiz.base.util.UtilProperties; -import org.apache.ofbiz.base.util.UtilValidate; -import org.apache.ofbiz.htmlreport.util.ReportEncoder; -import org.apache.ofbiz.htmlreport.util.ReportStringUtil; - -/** - * HTML report output to be used in report.ftl.<p> - * - */ -public class HtmlReport extends AbstractReport { - - public static final String module = HtmlReport.class.getName(); - - /** The delimiter that is used in the resource list request parameter. */ - public static final String DELIMITER_RESOURCES = "|"; - - /** Request parameter name for the resource list. */ - public static final String PARAM_RESOURCELIST = "resourcelist"; - - /** Constant for a HTML linebreak with added "real" line break. */ - protected static final String LINEBREAK = "<br>"; - - /** - * Constant for a HTML linebreak with added "real" line break- - * traditional style for report threads that still use XML templates for their output. - */ - protected static final String LINEBREAK_TRADITIONAL = "<br>\n"; - - /** The list of report objects e.g. String, Exception ... */ - protected List<Serializable> content; - - /** The list of report objects e.g. String, Exception ... */ - protected List<Serializable> logContent; - - /** - * Counter to remember what is already shown, - * indicates the next index of the content list that has to be reported. - */ - protected int indexNext; - - /** Flag to indicate if an exception should be displayed long or short. */ - protected boolean showExceptionStackTrace; - - /** If set to <code>true</code> nothing is kept in memory. */ - protected boolean isTransient; - - /** Boolean flag indicating whether this report should generate HTML or JavaScript output. */ - protected boolean writeHtml; - - /** Helper variable to deliver the html end part. */ - public static final int HTML_END = 1; - - /** Helper variable to deliver the html start part. */ - public static final int HTML_START = 0; - - /** The thread to display in this report. */ - protected String paramThread; - - /** The next thread to display after this report. */ - protected String paramThreadHasNext; - - protected String paramAction; - - protected String paramTitle; - - protected String paramResource; - - /** Flag for refreching workplace .*/ - protected String paramRefreshWorkplace; - - /** Constant for the "OK" button in the build button methods. */ - public static final int BUTTON_OK = 0; - - /** Constant for the "Cancel" button in the build button methods. */ - public static final int BUTTON_CANCEL = 1; - - /** Constant for the "Close" button in the build button methods. */ - public static final int BUTTON_CLOSE = 2; - - /** Constant for the "Advanced" button in the build button methods. */ - public static final int BUTTON_ADVANCED = 3; - - /** Constant for the "Set" button in the build button methods. */ - public static final int BUTTON_SET = 4; - - /** Constant for the "Details" button in the build button methods. */ - public static final int BUTTON_DETAILS = 5; - - /** Constant for the "OK" button in the build button methods (without form submission). */ - public static final int BUTTON_OK_NO_SUBMIT = 6; - - /** Constant for the "Edit" button in the build button methods (same function as "Ok" button but different text on button. */ - public static final int BUTTON_EDIT = 7; - - /** Constant for the "Discard" button in the build button methods (same function as "Cancel" button but different text on button. */ - public static final int BUTTON_DISCARD = 8; - - /** Constant for the "Back" button in the build button methods. */ - public static final int BUTTON_BACK = 9; - - /** Constant for the "Continue" button in the build button methods. */ - public static final int BUTTON_CONTINUE = 10; - - /** Constant for the "Download" button in the build button methods. */ - public static final int BUTTON_DOWNLOAD = 11; - - /** Request parameter value for the action: back. */ - public static final String DIALOG_BACK = "back"; - - /** Request parameter value for the action: cancel. */ - public static final String DIALOG_CANCEL = "cancel"; - - /** Request parameter value for the action: continue. */ - public static final String DIALOG_CONTINUE = "continue"; - - /** Request parameter value for the action: set. */ - public static final String DIALOG_SET = "set"; - - /** The resource list parameter value. */ - protected String paramResourcelist; - - /** The list of resource names for the multi operation. */ - protected List<String> resourceList; - - /** The key name which contains the localized message for the continue checkbox. */ - protected String paramReportContinueKey; - - public static final String DIALOG_URI = "dialoguri"; - - public static final String FORM_URI = "formuri"; - - public static final String resource = "PricatUiLabels"; - - /** Log file. */ - protected File logFile; - - /** Log file name. */ - protected String logFileName; - - /** Log file output stream. */ - protected FileOutputStream logFileOutputStream; - - protected long sequenceNum = -1; - - /** - * Constructs a new report using the provided locale for the output language.<p> - * - * @param request HttpServletRequest - * @param response HttpServletResponse - */ - public HtmlReport(HttpServletRequest request, HttpServletResponse response) { - - this(request, response, false, false); - } - - /** - * Constructs a new report using the provided locale for the output language.<p> - * - * @param request HttpServletRequest - * @param response HttpServletResponse - * @param writeHtml if <code>true</code>, this report should generate HTML instead of JavaScript output - * @param isTransient If set to <code>true</code> nothing is kept in memory - */ - public HtmlReport(HttpServletRequest request, HttpServletResponse response, boolean writeHtml, boolean isTransient) { - - init(UtilHttp.getLocale(request)); - content = new ArrayList<Serializable>(256); - logContent = new ArrayList<Serializable>(256); - showExceptionStackTrace = true; - this.writeHtml = writeHtml; - this.isTransient = isTransient; - } - - public static HtmlReport getInstance(HttpServletRequest request, HttpServletResponse response) { - HtmlReport wp = (HtmlReport) request.getSession().getAttribute(SESSION_REPORT_CLASS); - if (wp == null) { - wp = new HtmlReport(request, response, true, true); - request.getSession().setAttribute(SESSION_REPORT_CLASS, wp); - } - return wp; - } - - public static HtmlReport getInstance(HttpServletRequest request, HttpServletResponse response, boolean writeHtml, boolean isTransient) { - HtmlReport wp = (HtmlReport) request.getSession().getAttribute(SESSION_REPORT_CLASS); - if (wp == null) { - wp = new HtmlReport(request, response, writeHtml, isTransient); - request.getSession().setAttribute(SESSION_REPORT_CLASS, wp); - } - return wp; - } - - public static HtmlReport getInstance(HttpServletRequest request, HttpServletResponse response, boolean writeHtml, boolean isTransient, String logFileName) { - HtmlReport wp = (HtmlReport) request.getSession().getAttribute(SESSION_REPORT_CLASS); - if (wp == null || UtilValidate.isEmpty(wp.getLogFileName()) || !wp.getLogFileName().equals(logFileName)) { - wp = new HtmlReport(request, response, writeHtml, isTransient); - request.getSession().setAttribute(SESSION_REPORT_CLASS, wp); - } - return wp; - } - - public String getParamAction(HttpServletRequest request) { - paramAction = request.getParameter("action"); - return paramAction != null ? paramAction : "reportbegin"; - } - - public void setParamAction(String action) { - paramAction = action; - } - - public void setParamThread(String name) { - paramThread = name; - } - - public synchronized String getReportUpdate() { - StringBuffer result = new StringBuffer(); - StringBuffer logResult = new StringBuffer(); - int indexEnd = content.size(); - for (int i = indexNext; i < indexEnd; i++) { - int pos = isTransient ? 0 : i; - Object obj = content.get(pos); - if ((obj instanceof String) || (obj instanceof StringBuffer)) { - result.append(obj); - } else if (obj instanceof Throwable) { - result.append(getExceptionElementJS((Throwable)obj)); - } - if (isTransient) { - content.remove(indexNext); - } - if (UtilValidate.isNotEmpty(logContent)) { - Object logObj = logContent.get(pos); - if ((logObj instanceof String) || (logObj instanceof StringBuffer)) { - logResult.append(logObj); - } else if (logObj instanceof Throwable) { - result.append(getExceptionElementHtml((Throwable) logObj)); - } - if (isTransient) { - logContent.remove(indexNext); - } - } - } - - indexNext = isTransient ? 0 : indexEnd; - - if (isTransient && logFileOutputStream != null && logResult.toString().length() > 0) { - try { - logFileOutputStream.write((logResult.toString() + "\n").getBytes()); - logFileOutputStream.flush(); - } catch (IOException e) { - Debug.logError(e.getMessage(), module); - } - } - return result.toString(); - } - - /** - * Returns if the report writes html or javascript code.<p> - * - * @return <code>true</code> if the report writes html, and <code>false</code> if the report writes javascript code - */ - public boolean isWriteHtml() { - return writeHtml; - } - - public synchronized void print(String value, int format) { - StringBuffer buf = null; - value = ReportStringUtil.escapeJavaScript(value); - switch (format) { - case FORMAT_HEADLINE: - buf = new StringBuffer(); - buf.append("aH('"); - buf.append(value); - buf.append("'); "); - break; - case FORMAT_WARNING: - buf = new StringBuffer(); - buf.append("aW('"); - buf.append(value); - buf.append("'); "); - addWarning(value); - break; - case FORMAT_ERROR: - buf = new StringBuffer(); - buf.append("aE('"); - buf.append(value); - buf.append("'); "); - addError(value); - break; - case FORMAT_NOTE: - buf = new StringBuffer(); - buf.append("aN('"); - buf.append(value); - buf.append("'); "); - break; - case FORMAT_OK: - buf = new StringBuffer(); - buf.append("aO('"); - buf.append(value); - buf.append("'); "); - break; - case FORMAT_DEFAULT: - default: - buf = new StringBuffer(); - buf.append("a('"); - buf.append(value); - buf.append("'); "); - } - if (value.trim().endsWith(getLineBreak())) { - buf.append("aB(); "); - } - content.add(buf.toString()); - - switch (format) { - case FORMAT_HEADLINE: - buf = new StringBuffer(); - buf.append("<span class='head'>"); - buf.append(value); - buf.append("</span>"); - break; - case FORMAT_WARNING: - buf = new StringBuffer(); - buf.append("<span class='warn'>"); - buf.append(value); - buf.append("</span>"); - addWarning(value); - break; - case FORMAT_ERROR: - buf = new StringBuffer(); - buf.append("<span class='err'>"); - buf.append(value); - buf.append("</span>"); - addError(value); - break; - case FORMAT_NOTE: - buf = new StringBuffer(); - buf.append("<span class='note'>"); - buf.append(value); - buf.append("</span>"); - break; - case FORMAT_OK: - buf = new StringBuffer(); - buf.append("<span class='ok'>"); - buf.append(value); - buf.append("</span>"); - break; - case FORMAT_DEFAULT: - default: - buf = new StringBuffer(value); - } - if (value.trim().endsWith(getLineBreak())) { - buf.append("\n"); - } - logContent.add(buf.toString()); - } - - public void println() { - print(getLineBreak()); - } - - public synchronized void println(Throwable t) { - addError(t.getMessage()); - content.add(getExceptionElementJS(t)); - logContent.add(getExceptionElementHtml(t)); - } - - /** - * Returns the correct line break notation depending on the output style of this report. - * - * @return the correct line break notation - */ - protected String getLineBreak() { - return writeHtml ? LINEBREAK_TRADITIONAL : LINEBREAK; - } - - /** - * Output helper method to format a reported <code>Throwable</code> element.<p> - * - * This method ensures that exception stack traces are properly escaped - * when they are added to the report.<p> - * - * There is a member variable {@link #showExceptionStackTrace} in this - * class that controls if the stack track is shown or not. - * In a later version this might be configurable on a per-user basis.<p> - * - * @param throwable the exception to format - * @return the formatted StringBuffer - */ - private StringBuffer getExceptionElementJS(Throwable throwable) { - StringBuffer buf = new StringBuffer(256); - if (showExceptionStackTrace) { - buf.append("aT('"); - buf.append(UtilProperties.getMessage(resource, "REPORT_EXCEPTION", getLocale())); - String exception = ReportEncoder.escapeXml(throwable.getLocalizedMessage()); - if (UtilValidate.isEmpty(exception)) { - exception = ReportEncoder.escapeXml(throwable.getMessage()); - } - if (UtilValidate.isNotEmpty(exception)) { - exception = exception.replaceAll("[\r\n]+", LINEBREAK); - buf.append(ReportStringUtil.escapeJavaScript(exception) + LINEBREAK); - } else { - buf.append(throwable.toString()); - } - buf.append("'); "); - } else { - buf.append("aT('"); - buf.append(UtilProperties.getMessage(resource, "REPORT_EXCEPTION", getLocale())); - buf.append(ReportStringUtil.escapeJavaScript(throwable.toString())); - buf.append("'); "); - } - return buf; - } - - private StringBuffer getExceptionElementHtml(Throwable throwable) { - StringBuffer buf = new StringBuffer(256); - if (showExceptionStackTrace) { - buf.append("<span class='throw'>"); - buf.append(UtilProperties.getMessage(resource, "REPORT_EXCEPTION", getLocale())); - String exception = ReportEncoder.escapeXml(throwable.getLocalizedMessage()); - if (UtilValidate.isEmpty(exception)) { - exception = ReportEncoder.escapeXml(throwable.getMessage()); - } - if (UtilValidate.isNotEmpty(exception)) { - exception = exception.replaceAll("[\r\n]+", LINEBREAK); - buf.append(exception); - } else { - buf.append(throwable.toString()); - } - buf.append("</span>"); - } else { - buf.append("<span class='throw'>"); - buf.append(UtilProperties.getMessage(resource, "REPORT_EXCEPTION", getLocale())); - buf.append(throwable.toString()); - buf.append("</span>"); - buf.append(getLineBreak()); - } - return buf; - } - - public void printMessageWithParam(String uiLabel, Object param) { - print(uiLabel, InterfaceReport.FORMAT_NOTE); - } - - public void printMessageWithParam(int m, int n, String uiLabel, Object param) { - print(uiLabel, InterfaceReport.FORMAT_NOTE); - } - - /** - * Builds the start html of the page, including setting of DOCTYPE and - * inserting a header with the content-type.<p> - * - * This overloads the default method of the parent class.<p> - * - * @return the start html of the page - */ - public String htmlStart() { - - return pageHtml(HTML_START, true); - } - - /** - * Builds the start html of the page, including setting of DOCTYPE and - * inserting a header with the content-type.<p> - * - * This overloads the default method of the parent class.<p> - * - * @param loadStyles if true, the defaul style sheet will be loaded - * @return the start html of the page - */ - public String htmlStart(boolean loadStyles) { - - return pageHtml(HTML_START, loadStyles); - } - - /** - * Builds the start html of the page, including setting of DOCTYPE and - * inserting a header with the content-type.<p> - * - * This overloads the default method of the parent class.<p> - * - * @param segment the HTML segment (START / END) - * @param loadStyles if true, the defaul style sheet will be loaded - * @return the start html of the page - */ - public String pageHtml(int segment, boolean loadStyles) { - if (segment == HTML_START) { - StringBuffer result = new StringBuffer(512); - result.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n"); - result.append("<html>\n<head>\n"); - result.append("<meta HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">\n"); - if (loadStyles) { - result.append("<link rel=\"stylesheet\" type=\"text/css\" href=\""); - result.append("/pricat/includes/pricat.css"); - result.append("\">\n"); - result.append("<script type=\"text/javascript\">\n"); - result.append(dialogScriptSubmit()); - result.append("</script>\n"); - } - return result.toString(); - } else { - return "</html>"; - } - } - - /** - * Builds the standard javascript for submitting the dialog.<p> - * - * @return the standard javascript for submitting the dialog - */ - public String dialogScriptSubmit() { - StringBuffer result = new StringBuffer(512); - result.append("function submitAction(actionValue, theForm, formName) {\n"); - result.append("\tif (theForm == null) {\n"); - result.append("\t\ttheForm = document.forms[formName];\n"); - result.append("\t}\n"); - result.append("\ttheForm.action.value = actionValue;\n"); - result.append("\ttheForm.submit();\n"); - result.append("\treturn false;\n"); - result.append("}\n"); - return result.toString(); - } - - /** - * Returns true if the report Thread is still alive (i.e. running), false otherwise.<p> - * - * @return true if the report Thread is still alive - */ - public boolean isAlive(HttpServletRequest request) { - ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); - int i = threadGroup.activeCount(); - Thread[] threads = new Thread[i]; - threadGroup.enumerate(threads, true); - AbstractReportThread thread = null; - for (int j=0; j<threads.length; j++) { - Thread threadInstance = threads[j]; - if (threadInstance instanceof AbstractReportThread) { - if(((AbstractReportThread)threadInstance).getUUID().toString().equals(getParamThread(request))) { - thread = (AbstractReportThread) threadInstance; - break; - } - } - } - if (thread != null) { - return thread.isAlive(); - } else { - return false; - } - } - - /** - * Returns the thread parameter value.<p> - * - * @return the thread parameter value - */ - public String getParamThread(HttpServletRequest request) { - String thread = request.getParameter("thread"); - return ReportStringUtil.isNotEmptyOrWhitespaceOnly(thread) ? thread : (paramThread == null? "" : paramThread); - } - - /** - * Returns the threadhasnext parameter value.<p> - * - * @return the threadhasnext parameter value - */ - public String getParamThreadHasNext(HttpServletRequest request) { - String threadhasnext = request.getParameter("threadhasnext"); - return ReportStringUtil.isNotEmptyOrWhitespaceOnly(threadhasnext) ? threadhasnext : "false"; - } - - /** - * Builds the start html of the body.<p> - * - * @param className optional class attribute to add to the body tag - * @param parameters optional parameters to add to the body tag - * @return the start html of the body - */ - public String bodyStart(String className, String parameters) { - return pageBody(HTML_START, className, parameters); - } - - /** - * Builds the html of the body.<p> - * - * @param segment the HTML segment (START / END) - * @param className optional class attribute to add to the body tag - * @param parameters optional parameters to add to the body tag - * @return the html of the body - */ - public String pageBody(int segment, String className, String parameters) { - if (segment == HTML_START) { - StringBuffer result = new StringBuffer(128); - result.append("</head>\n<body unselectable=\"on\""); - if (ReportStringUtil.isNotEmptyOrWhitespaceOnly(className)) { - result.append(" class=\""); - result.append(className); - result.append("\""); - } - if (ReportStringUtil.isNotEmpty(parameters)) { - result.append(" "); - result.append(parameters); - } - result.append(">\n"); - return result.toString(); - } else { - return "</body>"; - } - } - - /** - * Builds the end html of the body.<p> - * - * @return the end html of the body - */ - public String bodyEnd() { - return pageBody(HTML_END, null, null); - } - - /** - * Builds the end html of the page.<p> - * - * @return the end html of the page - */ - public String htmlEnd() { - return pageHtml(HTML_END, null); - } - - /** - * Returns the default html for a workplace page, including setting of DOCTYPE and - * inserting a header with the content-type.<p> - * - * @param segment the HTML segment (START / END) - * @param title the title of the page, if null no title tag is inserted - * @return the default html for a workplace page - */ - public String pageHtml(int segment, String title) { - return pageHtmlStyle(segment, title, null); - } - - /** - * Returns the default html for a workplace page, including setting of DOCTYPE and - * inserting a header with the content-type, allowing the selection of an individual style sheet.<p> - * - * @param segment the HTML segment (START / END) - * @param title the title of the page, if null no title tag is inserted - * @param stylesheet the used style sheet, if null the default stylesheet 'workplace.css' is inserted - * @return the default html for a workplace page - */ - public String pageHtmlStyle(int segment, String title, String stylesheet) { - if (segment == HTML_START) { - StringBuffer result = new StringBuffer(512); -// result.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n"); -// result.append("<html>\n<head>\n"); -// if (title != null) { -// result.append("<title>"); -// result.append(title); -// result.append("</title>\n"); -// } -// result.append("<meta HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">\n"); - result.append("<link rel=\"stylesheet\" type=\"text/css\" href=\""); - result.append("/pricat/includes/pricat.css"); - result.append("\">\n"); - return result.toString(); - } else { - return ""; -// return "</html>"; - } - } - - /** - * Returns the start html for the outer dialog window border. - * - * @return the start html for the outer dialog window border - */ - public String dialogStart() { - return dialog(HTML_START, null); - } - - /** - * Builds the outer dialog window border. - * - * @param segment the HTML segment (START / END) - * @param attributes optional additional attributes for the opening dialog table - * - * @return a dialog window start / end segment - */ - public String dialog(int segment, String attributes) { - if (segment == HTML_START) { - StringBuffer html = new StringBuffer(512); - html.append("<table class=\"dialog\" cellpadding=\"0\" cellspacing=\"0\""); - if (attributes != null) { - html.append(" "); - html.append(attributes); - } - html.append("><tr><td>\n<table class=\"dialogbox\" cellpadding=\"0\" cellspacing=\"0\">\n"); - html.append("<tr><td>\n"); - return html.toString(); - } else { - return "</td></tr></table>\n</td></tr></table>\n<p> </p>\n"; - } - } - - /** - * Returns the start html for the content area of the dialog window.<p> - * - * @param title the title for the dialog - * - * @return the start html for the content area of the dialog window - */ - public String dialogContentStart(String title) { - return dialogContent(HTML_START, title); - } - - /** - * Builds the content area of the dialog window.<p> - * - * @param segment the HTML segment (START / END) - * @param title the title String for the dialog window - * - * @return a content area start / end segment - */ - public String dialogContent(int segment, String title) { - if (segment == HTML_START) { - StringBuffer result = new StringBuffer(512); - // null title is ok, we always want the title headline - result.append(dialogHead(title)); - result.append("<div class=\"dialogcontent\" unselectable=\"on\">\n"); - result.append("<!-- dialogcontent start -->\n"); - return result.toString(); - } else { - return "<!-- dialogcontent end -->\n</div>\n"; - } - } - - /** - * Builds the title of the dialog window.<p> - * - * @param title the title String for the dialog window - * - * @return the HTML title String for the dialog window - */ - public String dialogHead(String title) { - return "<div class=\"dialoghead\" unselectable=\"on\">" + (title == null ? "" : title) + "</div>"; - } - - /** - * Returns the value of the title parameter, - * or null if this parameter was not provided.<p> - * - * This parameter is used to build the title - * of the dialog. It is a parameter so that the title - * can be passed to included elements.<p> - * - * @return the value of the title parameter - */ - public String getParamTitle(HttpServletRequest request) { - if (paramTitle == null) { - paramTitle = request.getParameter("title"); - } - return paramTitle != null ? paramTitle : ""; - } - - /** - * Returns all initialized parameters of the current workplace class - * as hidden field tags that can be inserted in a form.<p> - * - * @return all initialized parameters of the current workplace class - * as hidden field tags that can be inserted in a html form - */ - public String paramsAsHidden(HttpServletRequest request) { - return paramsAsHidden(request, null); - } - - /** - * Returns all initialized parameters of the current workplace class - * that are not in the given exclusion list as hidden field tags that can be inserted in a form.<p> - * - * @param excludes the parameters to exclude - * - * @return all initialized parameters of the current workplace class - * that are not in the given exclusion list as hidden field tags that can be inserted in a form - */ - public String paramsAsHidden(HttpServletRequest request, Collection<?> excludes) { - StringBuffer result = new StringBuffer(512); - Map<String, Object> params = paramValues(request); - Iterator<?> i = params.entrySet().iterator(); - while (i.hasNext()) { - Map.Entry entry = (Map.Entry)i.next(); - String param = (String)entry.getKey(); - if ((excludes == null) || (!excludes.contains(param))) { - result.append("<input type=\"hidden\" name=\""); - result.append(param); - result.append("\" value=\""); - String encoded = ReportEncoder.encode( - entry.getValue().toString(), - "UTF-8"); - result.append(encoded); - result.append("\">\n"); - } - } - - return result.toString(); - } - - /** - * Returns the values of all parameter methods of this workplace class instance.<p> - * - * @return the values of all parameter methods of this workplace class instance - */ - protected Map<String, Object> paramValues(HttpServletRequest request) { - List<Method> methods = paramGetMethods(); - Map<String, Object> map = new HashMap<String, Object>(methods.size()); - Iterator<Method> i = methods.iterator(); - while (i.hasNext()) { - Method m = (Method)i.next(); - Object o = null; - try { - o = m.invoke(this, new Object[0]); - } catch (InvocationTargetException ite) { - // can usually be ignored - } catch (IllegalAccessException eae) { - // can usually be ignored - } - if (o != null) { - map.put(m.getName().substring(8).toLowerCase(), o); - } - } - return map; - } - - /** - * Returns a list of all methods of the current class instance that - * start with "getParam" and have no parameters.<p> - * - * @return a list of all methods of the current class instance that - * start with "getParam" and have no parameters - */ - private List<Method> paramGetMethods() { - List<Method> list = new ArrayList<Method>(); - Method[] methods = this.getClass().getMethods(); - int length = methods.length; - for (int i = 0; i < length; i++) { - Method method = methods[i]; - if (method.getName().startsWith("getParam") && (method.getParameterTypes().length == 0)) { - // Debug.logInfo("getMethod: " + method.getName(), module); - list.add(method); - } - } - return list; - } - - /** - * Returns an optional introduction text to be displayed above the report output.<p> - * - * @return an optional introduction text - */ - public String reportIntroductionText() { - return ""; - } - - /** - * Returns an optional conclusion text to be displayed below the report output.<p> - * - * @return an optional conclusion text - */ - public String reportConclusionText() { - return ""; - } - - /** - * Returns the end html for the content area of the dialog window.<p> - * - * @return the end html for the content area of the dialog window - */ - public String dialogContentEnd() { - return dialogContent(HTML_END, null); - } - - /** - * Builds a button row with an "Ok" and a "Cancel" button.<p> - * - * This row is displayed when the first report is running.<p> - * - * @param okAttrs optional attributes for the ok button - * @param cancelAttrs optional attributes for the cancel button - * @return the button row - */ - public String dialogButtonsContinue(String okAttrs, String cancelAttrs) { - return dialogButtons(new int[] {BUTTON_OK, BUTTON_CANCEL}, new String[] { - okAttrs, - cancelAttrs}); - } - - /** - * Builds a button row with an "OK" and a "Cancel" button.<p> - * - * This row is used when a single report is running or after the first report has finished.<p> - * - * @param okAttrs optional attributes for the ok button - * @param cancelAttrs optional attributes for the cancel button - * @return the button row - */ - public String dialogButtonsOkCancel(HttpServletRequest request, String okAttrs, String cancelAttrs) { - if (Boolean.valueOf(getParamThreadHasNext(request)).booleanValue() - && ReportStringUtil.isNotEmpty(getParamReportContinueKey())) { - return dialogButtons(new int[] {BUTTON_OK, BUTTON_CANCEL}, new String[] { - okAttrs, - cancelAttrs}); - } - return dialogButtons(new int[] {BUTTON_OK}, new String[] {okAttrs}); - } - - /** - * Builds a button row with an "OK", a "Cancel" and a "Download" button.<p> - * - * This row is used when a single report is running or after the first report has finished.<p> - * - * @param okAttrs optional attributes for the ok button - * @param cancelAttrs optional attributes for the cancel button - * @param downloadAttrs optional attributes for the download button - * @return the button row - */ - public String dialogButtonsOkCancelDownload(HttpServletRequest request, String okAttrs, String cancelAttrs, String downloadAttrs) { - if (ReportStringUtil.isEmptyOrWhitespaceOnly(downloadAttrs)) { - downloadAttrs = ""; - } else { - downloadAttrs += " "; - } - if (Boolean.valueOf(getParamThreadHasNext(request)).booleanValue() - && ReportStringUtil.isNotEmpty(getParamReportContinueKey())) { - return dialogButtons(new int[] {BUTTON_OK, BUTTON_CANCEL, BUTTON_DOWNLOAD}, new String[] { - okAttrs, - cancelAttrs, - downloadAttrs + "onclick=\"downloadPricat(" + (sequenceNum > 0 ? sequenceNum : "") + ");\""}); - } - return dialogButtons(new int[] {BUTTON_OK, BUTTON_DOWNLOAD}, new String[] { - okAttrs, - downloadAttrs + "onclick=\"downloadPricat(" + (sequenceNum > 0 ? sequenceNum : "") + ");\""}); - } - - /** - * Builds the html for the button row under the dialog content area, including buttons.<p> - * - * @param buttons array of constants of which buttons to include in the row - * @param attributes array of Strings for additional button attributes - * - * @return the html for the button row under the dialog content area, including buttons - */ - public String dialogButtons(int[] buttons, String[] attributes) { - StringBuffer result = new StringBuffer(256); - result.append(dialogButtonRow(HTML_START)); - for (int i = 0; i < buttons.length; i++) { - dialogButtonsHtml(result, buttons[i], attributes[i]); - } - result.append(dialogButtonRow(HTML_END)); - return result.toString(); - } - - /** - * Builds the button row under the dialog content area without the buttons.<p> - * - * @param segment the HTML segment (START / END) - * - * @return the button row start / end segment - */ - public String dialogButtonRow(int segment) { - if (segment == HTML_START) { - return "<!-- button row start -->\n<div class=\"dialogbuttons\" unselectable=\"on\">\n"; - } else { - return "</div>\n<!-- button row end -->\n"; - } - } - - /** - * Renders the HTML for a single input button of a specified type.<p> - * - * @param result a string buffer where the rendered HTML gets appended to - * @param button a integer key to identify the button - * @param attribute an optional string with possible tag attributes, or null - */ - protected void dialogButtonsHtml(StringBuffer result, int button, String attribute) { - attribute = appendDelimiter(attribute); - switch (button) { - case BUTTON_OK: - result.append("<input name=\"ok\" value=\""); - result.append(UtilProperties.getMessage(resource, "DIALOG_BUTTON_OK", getLocale()) + "\""); - if (attribute.toLowerCase().indexOf("onclick") == -1) { - result.append(" type=\"submit\""); - } else { - result.append(" type=\"button\""); - } - result.append(" class=\"dialogbutton\""); - result.append(attribute); - result.append(">\n"); - break; - case BUTTON_CANCEL: - result.append("<input name=\"cancel\" type=\"button\" value=\""); - result.append(UtilProperties.getMessage(resource, "DIALOG_BUTTON_CANCEL", getLocale()) + "\""); - if (attribute.toLowerCase().indexOf("onclick") == -1) { - result.append(" onclick=\"submitAction('" + DIALOG_CANCEL + "', form);\""); - } - result.append(" class=\"dialogbutton\""); - result.append(attribute); - result.append(">\n"); - break; - case BUTTON_EDIT: - result.append("<input name=\"ok\" value=\""); - result.append(UtilProperties.getMessage(resource, "DIALOG_BUTTON_EDIT", getLocale()) + "\""); - if (attribute.toLowerCase().indexOf("onclick") == -1) { - result.append(" type=\"submit\""); - } else { - result.append(" type=\"button\""); - } - result.append(" class=\"dialogbutton\""); - result.append(attribute); - result.append(">\n"); - break; - case BUTTON_DISCARD: - result.append("<input name=\"cancel\" type=\"button\" value=\""); - result.append(UtilProperties.getMessage(resource, "DIALOG_BUTTON_DISCARD", getLocale()) + "\""); - if (attribute.toLowerCase().indexOf("onclick") == -1) { - result.append(" onclick=\"submitAction('" + DIALOG_CANCEL + "', form);\""); - } - result.append(" class=\"dialogbutton\""); - result.append(attribute); - result.append(">\n"); - break; - case BUTTON_CLOSE: - result.append("<input name=\"close\" type=\"button\" value=\""); - result.append(UtilProperties.getMessage(resource, "DIALOG_BUTTON_CLOSE", getLocale()) + "\""); - if (attribute.toLowerCase().indexOf("onclick") == -1) { - result.append(" onclick=\"submitAction('" + DIALOG_CANCEL + "', form);\""); - } - result.append(" class=\"dialogbutton\""); - result.append(attribute); - result.append(">\n"); - break; - case BUTTON_ADVANCED: - result.append("<input name=\"advanced\" type=\"button\" value=\""); - result.append(UtilProperties.getMessage(resource, "DIALOG_BUTTON_ADVANCE", getLocale()) + "\""); - result.append(" class=\"dialogbutton\""); - result.append(attribute); - result.append(">\n"); - break; - case BUTTON_SET: - result.append("<input name=\"set\" type=\"button\" value=\""); - result.append(UtilProperties.getMessage(resource, "DIALOG_BUTTON_SET", getLocale()) + "\""); - if (attribute.toLowerCase().indexOf("onclick") == -1) { - result.append(" onclick=\"submitAction('" + DIALOG_SET + "', form);\""); - } - result.append(" class=\"dialogbutton\""); - result.append(attribute); - result.append(">\n"); - break; - case BUTTON_BACK: - result.append("<input name=\"set\" type=\"button\" value=\""); - result.append(UtilProperties.getMessage(resource, "DIALOG_BUTTON_BACK", getLocale()) + "\""); - if (attribute.toLowerCase().indexOf("onclick") == -1) { - result.append(" onclick=\"submitAction('" + DIALOG_BACK + "', form);\""); - } - result.append(" class=\"dialogbutton\""); - result.append(attribute); - result.append(">\n"); - break; - case BUTTON_CONTINUE: - result.append("<input name=\"set\" type=\"button\" value=\""); - result.append(UtilProperties.getMessage(resource, "DIALOG_BUTTON_CONTINUE", getLocale()) + "\""); - if (attribute.toLowerCase().indexOf("onclick") == -1) { - result.append(" onclick=\"submitAction('" + DIALOG_CONTINUE + "', form);\""); - } - result.append(" class=\"dialogbutton\""); - result.append(attribute); - result.append(">\n"); - break; - case BUTTON_DETAILS: - result.append("<input name=\"details\" type=\"button\" value=\""); - result.append(UtilProperties.getMessage(resource, "DIALOG_BUTTON_DETAIL", getLocale()) + "\""); - result.append(" class=\"dialogbutton\""); - result.append(attribute); - result.append(">\n"); - break; - case BUTTON_DOWNLOAD: - result.append("<input name=\"download\" type=\"button\" value=\""); - result.append(UtilProperties.getMessage(resource, "DIALOG_BUTTON_DOWNLOAD", getLocale()) + "\""); - result.append(" class=\"dialogbutton\""); - result.append(attribute); - result.append(">\n"); - break; - default: - // not a valid button code, just insert a warning in the HTML - result.append("<!-- invalid button code: "); - result.append(button); - result.append(" -->\n"); - } - } - - /** - * Appends a space char. between tag attributes.<p> - * - * @param attribute a tag attribute - * - * @return the tag attribute with a leading space char - */ - protected String appendDelimiter(String attribute) { - if (ReportStringUtil.isNotEmpty(attribute)) { - if (!attribute.startsWith(" ")) { - // add a delimiter space between the beginning button HTML and the button tag attributes - return " " + attribute; - } else { - return attribute; - } - } - return ""; - } - - /** - * Returns true if the dialog operation has to be performed on multiple resources.<p> - * - * @return true if the dialog operation has to be performed on multiple resources, otherwise false - */ - public boolean isMultiOperation(HttpServletRequest request) { - return (getResourceList(request).size() > 1); - } - - /** - * Returns the resources that are defined for the dialog operation. - * - * For single resource operations, the list contains one item: the resource name found - * in the request parameter value of the "resource" parameter. - * - * @return the resources that are defined for the dialog operation - */ - public List<String> getResourceList(HttpServletRequest request) { - if (resourceList == null) { - // use lazy initializing - if (getParamResourcelist(request) != null) { - // found the resourcelist parameter - resourceList = StringUtil.split(getParamResourcelist(request), DELIMITER_RESOURCES); - Collections.sort(resourceList); - } else { - // this is a single resource operation, create list containing the resource name - resourceList = new ArrayList<String>(1); - String resource = getParamResource(request); - if (ReportStringUtil.isNotEmptyOrWhitespaceOnly(resource)) { - resourceList.add(resource); - } else { - resourceList.add(""); - } - } - } - return resourceList; - } - - /** - * Returns the value of the resource list parameter, or null if the parameter is not provided.<p> - * - * This parameter selects the resources to perform operations on.<p> - * - * @return the value of the resource list parameter or null, if the parameter is not provided - */ - public String getParamResourcelist(HttpServletRequest request) { - if (ReportStringUtil.isNotEmpty(paramResourcelist) && !"null".equals(paramResourcelist)) { - return paramResourcelist; - } else { - return null; - } - } - - /** - * Returns the value of the file parameter, - * or null if this parameter was not provided.<p> - * - * The file parameter selects the file on which the dialog action - * is to be performed.<p> - * - * @return the value of the file parameter - */ - public String getParamResource(HttpServletRequest request) { - paramResource = request.getParameter("resource"); - if ((paramResource != null) && !"null".equals(paramResource)) { - return paramResource; - } else { - return null; - } - } - - /** - * Returns if the workplace must be refreshed.<p> - * - * @return <code>"true"</code> if the workplace must be refreshed. - */ - public String getParamRefreshWorkplace() { - return paramRefreshWorkplace; - } - - /** - * Returns the key name which contains the localized message for the continue checkbox.<p> - * - * @return the key name which contains the localized message for the continue checkbox - */ - public String getParamReportContinueKey() { - if (paramReportContinueKey == null) { - paramReportContinueKey = ""; - } - return paramReportContinueKey; - } - - /** - * Returns the value of the resourcelist parameter in form of a String separated - * with {@link #DELIMITER_RESOURCES}, or the value of the resource parameter if the - * first parameter is not provided (no multiple choice has been done.<p> - * - * This may be used for jsps as value for the parameter for resources {@link #PARAM_RESOURCELIST}.<p> - * - * @return the value of the resourcelist parameter or null, if the parameter is not provided - */ - public String getResourceListAsParam(HttpServletRequest request) { - String result = getParamResourcelist(request); - if (ReportStringUtil.isEmptyOrWhitespaceOnly(result)) { - result = getParamResource(request); - } - return result; - } - - /** - * Returns the end html for the outer dialog window border.<p> - * - * @return the end html for the outer dialog window border - */ - public String dialogEnd() { - return dialog(HTML_END, null); - } - - /** - * Returns the http URI of the current dialog, to be used - * as value for the "action" attribute of a html form.<p> - * - * This URI is the real one.<p> - * - * @return the http URI of the current dialog - */ - public String getDialogRealUri(HttpServletRequest request) { - return String.valueOf(request.getAttribute(DIALOG_URI)); - } - - /** - * Set the report form uri. - * - * @param request - * @param formUri - */ - public void setFormRealUri(HttpServletRequest request, String formUri) { - request.setAttribute(FORM_URI, formUri); - } - - /** - * Get the report form uri. - * - * @param request - * @return - */ - public String getFormRealUri(HttpServletRequest request) { - return (String) request.getAttribute(FORM_URI); - } - - public void addLogFile(String logFileName) { - if (logFile == null || logFileOutputStream == null) { - this.logFileName = logFileName; - logFile = FileUtil.getFile(logFileName); - try { - logFileOutputStream = new FileOutputStream(logFile); - } catch (FileNotFoundException e) { - // do nothing - } - } - } - - public String closeLogFile() { - if (logFileOutputStream != null) { - try { - logFileOutputStream.flush(); - } catch (IOException e) { - // do nothing - } finally { - if (logFileOutputStream != null) { - try { - logFileOutputStream.close(); - } catch (IOException e) { - // do nothing - Debug.logError(e, HtmlReport.module); - } - } - } - } - return logFileName; - } - - public String getLogFileName() { - return logFileName; - } - - public long getSequenceNum() { - return sequenceNum; - } - - public void setSequenceNum(long sequenceNum) { - this.sequenceNum = sequenceNum; - } -} +/******************************************************************************* + * 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 org.apache.ofbiz.htmlreport; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.ofbiz.base.util.Debug; +import org.apache.ofbiz.base.util.FileUtil; +import org.apache.ofbiz.base.util.StringUtil; +import org.apache.ofbiz.base.util.UtilHttp; +import org.apache.ofbiz.base.util.UtilProperties; +import org.apache.ofbiz.base.util.UtilValidate; +import org.apache.ofbiz.htmlreport.util.ReportEncoder; +import org.apache.ofbiz.htmlreport.util.ReportStringUtil; + +/** + * HTML report output to be used in report.ftl.<p> + * + */ +public class HtmlReport extends AbstractReport { + + public static final String module = HtmlReport.class.getName(); + + /** The delimiter that is used in the resource list request parameter. */ + public static final String DELIMITER_RESOURCES = "|"; + + /** Request parameter name for the resource list. */ + public static final String PARAM_RESOURCELIST = "resourcelist"; + + /** Constant for a HTML linebreak with added "real" line break. */ + protected static final String LINEBREAK = "<br>"; + + /** + * Constant for a HTML linebreak with added "real" line break- + * traditional style for report threads that still use XML templates for their output. + */ + protected static final String LINEBREAK_TRADITIONAL = "<br>\n"; + + /** The list of report objects e.g. String, Exception ... */ + protected List<Serializable> content; + + /** The list of report objects e.g. String, Exception ... */ + protected List<Serializable> logContent; + + /** + * Counter to remember what is already shown, + * indicates the next index of the content list that has to be reported. + */ + protected int indexNext; + + /** Flag to indicate if an exception should be displayed long or short. */ + protected boolean showExceptionStackTrace; + + /** If set to <code>true</code> nothing is kept in memory. */ + protected boolean isTransient; + + /** Boolean flag indicating whether this report should generate HTML or JavaScript output. */ + protected boolean writeHtml; + + /** Helper variable to deliver the html end part. */ + public static final int HTML_END = 1; + + /** Helper variable to deliver the html start part. */ + public static final int HTML_START = 0; + + /** The thread to display in this report. */ + protected String paramThread; + + /** The next thread to display after this report. */ + protected String paramThreadHasNext; + + protected String paramAction; + + protected String paramTitle; + + protected String paramResource; + + /** Flag for refreching workplace .*/ + protected String paramRefreshWorkplace; + + /** Constant for the "OK" button in the build button methods. */ + public static final int BUTTON_OK = 0; + + /** Constant for the "Cancel" button in the build button methods. */ + public static final int BUTTON_CANCEL = 1; + + /** Constant for the "Close" button in the build button methods. */ + public static final int BUTTON_CLOSE = 2; + + /** Constant for the "Advanced" button in the build button methods. */ + public static final int BUTTON_ADVANCED = 3; + + /** Constant for the "Set" button in the build button methods. */ + public static final int BUTTON_SET = 4; + + /** Constant for the "Details" button in the build button methods. */ + public static final int BUTTON_DETAILS = 5; + + /** Constant for the "OK" button in the build button methods (without form submission). */ + public static final int BUTTON_OK_NO_SUBMIT = 6; + + /** Constant for the "Edit" button in the build button methods (same function as "Ok" button but different text on button. */ + public static final int BUTTON_EDIT = 7; + + /** Constant for the "Discard" button in the build button methods (same function as "Cancel" button but different text on button. */ + public static final int BUTTON_DISCARD = 8; + + /** Constant for the "Back" button in the build button methods. */ + public static final int BUTTON_BACK = 9; + + /** Constant for the "Continue" button in the build button methods. */ + public static final int BUTTON_CONTINUE = 10; + + /** Constant for the "Download" button in the build button methods. */ + public static final int BUTTON_DOWNLOAD = 11; + + /** Request parameter value for the action: back. */ + public static final String DIALOG_BACK = "back"; + + /** Request parameter value for the action: cancel. */ + public static final String DIALOG_CANCEL = "cancel"; + + /** Request parameter value for the action: continue. */ + public static final String DIALOG_CONTINUE = "continue"; + + /** Request parameter value for the action: set. */ + public static final String DIALOG_SET = "set"; + + /** The resource list parameter value. */ + protected String paramResourcelist; + + /** The list of resource names for the multi operation. */ + protected List<String> resourceList; + + /** The key name which contains the localized message for the continue checkbox. */ + protected String paramReportContinueKey; + + public static final String DIALOG_URI = "dialoguri"; + + public static final String FORM_URI = "formuri"; + + public static final String resource = "PricatUiLabels"; + + /** Log file. */ + protected File logFile; + + /** Log file name. */ + protected String logFileName; + + /** Log file output stream. */ + protected FileOutputStream logFileOutputStream; + + protected long sequenceNum = -1; + + /** + * Constructs a new report using the provided locale for the output language.<p> + * + * @param request HttpServletRequest + * @param response HttpServletResponse + */ + public HtmlReport(HttpServletRequest request, HttpServletResponse response) { + + this(request, response, false, false); + } + + /** + * Constructs a new report using the provided locale for the output language.<p> + * + * @param request HttpServletRequest + * @param response HttpServletResponse + * @param writeHtml if <code>true</code>, this report should generate HTML instead of JavaScript output + * @param isTransient If set to <code>true</code> nothing is kept in memory + */ + public HtmlReport(HttpServletRequest request, HttpServletResponse response, boolean writeHtml, boolean isTransient) { + + init(UtilHttp.getLocale(request)); + content = new ArrayList<Serializable>(256); + logContent = new ArrayList<Serializable>(256); + showExceptionStackTrace = true; + this.writeHtml = writeHtml; + this.isTransient = isTransient; + } + + public static HtmlReport getInstance(HttpServletRequest request, HttpServletResponse response) { + HtmlReport wp = (HtmlReport) request.getSession().getAttribute(SESSION_REPORT_CLASS); + if (wp == null) { + wp = new HtmlReport(request, response, true, true); + request.getSession().setAttribute(SESSION_REPORT_CLASS, wp); + } + return wp; + } + + public static HtmlReport getInstance(HttpServletRequest request, HttpServletResponse response, boolean writeHtml, boolean isTransient) { + HtmlReport wp = (HtmlReport) request.getSession().getAttribute(SESSION_REPORT_CLASS); + if (wp == null) { + wp = new HtmlReport(request, response, writeHtml, isTransient); + request.getSession().setAttribute(SESSION_REPORT_CLASS, wp); + } + return wp; + } + + public static HtmlReport getInstance(HttpServletRequest request, HttpServletResponse response, boolean writeHtml, boolean isTransient, String logFileName) { + HtmlReport wp = (HtmlReport) request.getSession().getAttribute(SESSION_REPORT_CLASS); + if (wp == null || UtilValidate.isEmpty(wp.getLogFileName()) || !wp.getLogFileName().equals(logFileName)) { + wp = new HtmlReport(request, response, writeHtml, isTransient); + request.getSession().setAttribute(SESSION_REPORT_CLASS, wp); + } + return wp; + } + + public String getParamAction(HttpServletRequest request) { + paramAction = request.getParameter("action"); + return paramAction != null ? paramAction : "reportbegin"; + } + + public void setParamAction(String action) { + paramAction = action; + } + + public void setParamThread(String name) { + paramThread = name; + } + + public synchronized String getReportUpdate() { + StringBuffer result = new StringBuffer(); + StringBuffer logResult = new StringBuffer(); + int indexEnd = content.size(); + for (int i = indexNext; i < indexEnd; i++) { + int pos = isTransient ? 0 : i; + Object obj = content.get(pos); + if ((obj instanceof String) || (obj instanceof StringBuffer)) { + result.append(obj); + } else if (obj instanceof Throwable) { + result.append(getExceptionElementJS((Throwable)obj)); + } + if (isTransient) { + content.remove(indexNext); + } + if (UtilValidate.isNotEmpty(logContent)) { + Object logObj = logContent.get(pos); + if ((logObj instanceof String) || (logObj instanceof StringBuffer)) { + logResult.append(logObj); + } else if (logObj instanceof Throwable) { + result.append(getExceptionElementHtml((Throwable) logObj)); + } + if (isTransient) { + logContent.remove(indexNext); + } + } + } + + indexNext = isTransient ? 0 : indexEnd; + + if (isTransient && logFileOutputStream != null && logResult.toString().length() > 0) { + try { + logFileOutputStream.write((logResult.toString() + "\n").getBytes()); + logFileOutputStream.flush(); + } catch (IOException e) { + Debug.logError(e.getMessage(), module); + } + } + return result.toString(); + } + + /** + * Returns if the report writes html or javascript code.<p> + * + * @return <code>true</code> if the report writes html, and <code>false</code> if the report writes javascript code + */ + public boolean isWriteHtml() { + return writeHtml; + } + + public synchronized void print(String value, int format) { + StringBuffer buf = null; + value = ReportStringUtil.escapeJavaScript(value); + switch (format) { + case FORMAT_HEADLINE: + buf = new StringBuffer(); + buf.append("aH('"); + buf.append(value); + buf.append("'); "); + break; + case FORMAT_WARNING: + buf = new StringBuffer(); + buf.append("aW('"); + buf.append(value); + buf.append("'); "); + addWarning(value); + break; + case FORMAT_ERROR: + buf = new StringBuffer(); + buf.append("aE('"); + buf.append(value); + buf.append("'); "); + addError(value); + break; + case FORMAT_NOTE: + buf = new StringBuffer(); + buf.append("aN('"); + buf.append(value); + buf.append("'); "); + break; + case FORMAT_OK: + buf = new StringBuffer(); + buf.append("aO('"); + buf.append(value); + buf.append("'); "); + break; + case FORMAT_DEFAULT: + default: + buf = new StringBuffer(); + buf.append("a('"); + buf.append(value); + buf.append("'); "); + } + if (value.trim().endsWith(getLineBreak())) { + buf.append("aB(); "); + } + content.add(buf.toString()); + + switch (format) { + case FORMAT_HEADLINE: + buf = new StringBuffer(); + buf.append("<span class='head'>"); + buf.append(value); + buf.append("</span>"); + break; + case FORMAT_WARNING: + buf = new StringBuffer(); + buf.append("<span class='warn'>"); + buf.append(value); + buf.append("</span>"); + addWarning(value); + break; + case FORMAT_ERROR: + buf = new StringBuffer(); + buf.append("<span class='err'>"); + buf.append(value); + buf.append("</span>"); + addError(value); + break; + case FORMAT_NOTE: + buf = new StringBuffer(); + buf.append("<span class='note'>"); + buf.append(value); + buf.append("</span>"); + break; + case FORMAT_OK: + buf = new StringBuffer(); + buf.append("<span class='ok'>"); + buf.append(value); + buf.append("</span>"); + break; + case FORMAT_DEFAULT: + default: + buf = new StringBuffer(value); + } + if (value.trim().endsWith(getLineBreak())) { + buf.append("\n"); + } + logContent.add(buf.toString()); + } + + public void println() { + print(getLineBreak()); + } + + public synchronized void println(Throwable t) { + addError(t.getMessage()); + content.add(getExceptionElementJS(t)); + logContent.add(getExceptionElementHtml(t)); + } + + /** + * Returns the correct line break notation depending on the output style of this report. + * + * @return the correct line break notation + */ + protected String getLineBreak() { + return writeHtml ? LINEBREAK_TRADITIONAL : LINEBREAK; + } + + /** + * Output helper method to format a reported <code>Throwable</code> element.<p> + * + * This method ensures that exception stack traces are properly escaped + * when they are added to the report.<p> + * + * There is a member variable {@link #showExceptionStackTrace} in this + * class that controls if the stack track is shown or not. + * In a later version this might be configurable on a per-user basis.<p> + * + * @param throwable the exception to format + * @return the formatted StringBuffer + */ + private StringBuffer getExceptionElementJS(Throwable throwable) { + StringBuffer buf = new StringBuffer(256); + if (showExceptionStackTrace) { + buf.append("aT('"); + buf.append(UtilProperties.getMessage(resource, "REPORT_EXCEPTION", getLocale())); + String exception = ReportEncoder.escapeXml(throwable.getLocalizedMessage()); + if (UtilValidate.isEmpty(exception)) { + exception = ReportEncoder.escapeXml(throwable.getMessage()); + } + if (UtilValidate.isNotEmpty(exception)) { + exception = exception.replaceAll("[\r\n]+", LINEBREAK); + buf.append(ReportStringUtil.escapeJavaScript(exception) + LINEBREAK); + } else { + buf.append(throwable.toString()); + } + buf.append("'); "); + } else { + buf.append("aT('"); + buf.append(UtilProperties.getMessage(resource, "REPORT_EXCEPTION", getLocale())); + buf.append(ReportStringUtil.escapeJavaScript(throwable.toString())); + buf.append("'); "); + } + return buf; + } + + private StringBuffer getExceptionElementHtml(Throwable throwable) { + StringBuffer buf = new StringBuffer(256); + if (showExceptionStackTrace) { + buf.append("<span class='throw'>"); + buf.append(UtilProperties.getMessage(resource, "REPORT_EXCEPTION", getLocale())); + String exception = ReportEncoder.escapeXml(throwable.getLocalizedMessage()); + if (UtilValidate.isEmpty(exception)) { + exception = ReportEncoder.escapeXml(throwable.getMessage()); + } + if (UtilValidate.isNotEmpty(exception)) { + exception = exception.replaceAll("[\r\n]+", LINEBREAK); + buf.append(exception); + } else { + buf.append(throwable.toString()); + } + buf.append("</span>"); + } else { + buf.append("<span class='throw'>"); + buf.append(UtilProperties.getMessage(resource, "REPORT_EXCEPTION", getLocale())); + buf.append(throwable.toString()); + buf.append("</span>"); + buf.append(getLineBreak()); + } + return buf; + } + + public void printMessageWithParam(String uiLabel, Object param) { + print(uiLabel, InterfaceReport.FORMAT_NOTE); + } + + public void printMessageWithParam(int m, int n, String uiLabel, Object param) { + print(uiLabel, InterfaceReport.FORMAT_NOTE); + } + + /** + * Builds the start html of the page, including setting of DOCTYPE and + * inserting a header with the content-type.<p> + * + * This overloads the default method of the parent class.<p> + * + * @return the start html of the page + */ + public String htmlStart() { + + return pageHtml(HTML_START, true); + } + + /** + * Builds the start html of the page, including setting of DOCTYPE and + * inserting a header with the content-type.<p> + * + * This overloads the default method of the parent class.<p> + * + * @param loadStyles if true, the defaul style sheet will be loaded + * @return the start html of the page + */ + public String htmlStart(boolean loadStyles) { + + return pageHtml(HTML_START, loadStyles); + } + + /** + * Builds the start html of the page, including setting of DOCTYPE and + * inserting a header with the content-type.<p> + * + * This overloads the default method of the parent class.<p> + * + * @param segment the HTML segment (START / END) + * @param loadStyles if true, the defaul style sheet will be loaded + * @return the start html of the page + */ + public String pageHtml(int segment, boolean loadStyles) { + if (segment == HTML_START) { + StringBuffer result = new StringBuffer(512); + result.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n"); + result.append("<html>\n<head>\n"); + result.append("<meta HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">\n"); + if (loadStyles) { + result.append("<link rel=\"stylesheet\" type=\"text/css\" href=\""); + result.append("/pricat/includes/pricat.css"); + result.append("\">\n"); + result.append("<script type=\"text/javascript\">\n"); + result.append(dialogScriptSubmit()); + result.append("</script>\n"); + } + return result.toString(); + } else { + return "</html>"; + } + } + + /** + * Builds the standard javascript for submitting the dialog.<p> + * + * @return the standard javascript for submitting the dialog + */ + public String dialogScriptSubmit() { + StringBuffer result = new StringBuffer(512); + result.append("function submitAction(actionValue, theForm, formName) {\n"); + result.append("\tif (theForm == null) {\n"); + result.append("\t\ttheForm = document.forms[formName];\n"); + result.append("\t}\n"); + result.append("\ttheForm.action.value = actionValue;\n"); + result.append("\ttheForm.submit();\n"); + result.append("\treturn false;\n"); + result.append("}\n"); + return result.toString(); + } + + /** + * Returns true if the report Thread is still alive (i.e. running), false otherwise.<p> + * + * @return true if the report Thread is still alive + */ + public boolean isAlive(HttpServletRequest request) { + ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); + int i = threadGroup.activeCount(); + Thread[] threads = new Thread[i]; + threadGroup.enumerate(threads, true); + AbstractReportThread thread = null; + for (int j=0; j<threads.length; j++) { + Thread threadInstance = threads[j]; + if (threadInstance instanceof AbstractReportThread) { + if(((AbstractReportThread)threadInstance).getUUID().toString().equals(getParamThread(request))) { + thread = (AbstractReportThread) threadInstance; + break; + } + } + } + if (thread != null) { + return thread.isAlive(); + } else { + return false; + } + } + + /** + * Returns the thread parameter value.<p> + * + * @return the thread parameter value + */ + public String getParamThread(HttpServletRequest request) { + String thread = request.getParameter("thread"); + return ReportStringUtil.isNotEmptyOrWhitespaceOnly(thread) ? thread : (paramThread == null? "" : paramThread); + } + + /** + * Returns the threadhasnext parameter value.<p> + * + * @return the threadhasnext parameter value + */ + public String getParamThreadHasNext(HttpServletRequest request) { + String threadhasnext = request.getParameter("threadhasnext"); + return ReportStringUtil.isNotEmptyOrWhitespaceOnly(threadhasnext) ? threadhasnext : "false"; + } + + /** + * Builds the start html of the body.<p> + * + * @param className optional class attribute to add to the body tag + * @param parameters optional parameters to add to the body tag + * @return the start html of the body + */ + public String bodyStart(String className, String parameters) { + return pageBody(HTML_START, className, parameters); + } + + /** + * Builds the html of the body.<p> + * + * @param segment the HTML segment (START / END) + * @param className optional class attribute to add to the body tag + * @param parameters optional parameters to add to the body tag + * @return the html of the body + */ + public String pageBody(int segment, String className, String parameters) { + if (segment == HTML_START) { + StringBuffer result = new StringBuffer(128); + result.append("</head>\n<body unselectable=\"on\""); + if (ReportStringUtil.isNotEmptyOrWhitespaceOnly(className)) { + result.append(" class=\""); + result.append(className); + result.append("\""); + } + if (ReportStringUtil.isNotEmpty(parameters)) { + result.append(" "); + result.append(parameters); + } + result.append(">\n"); + return result.toString(); + } else { + return "</body>"; + } + } + + /** + * Builds the end html of the body.<p> + * + * @return the end html of the body + */ + public String bodyEnd() { + return pageBody(HTML_END, null, null); + } + + /** + * Builds the end html of the page.<p> + * + * @return the end html of the page + */ + public String htmlEnd() { + return pageHtml(HTML_END, null); + } + + /** + * Returns the default html for a workplace page, including setting of DOCTYPE and + * inserting a header with the content-type.<p> + * + * @param segment the HTML segment (START / END) + * @param title the title of the page, if null no title tag is inserted + * @return the default html for a workplace page + */ + public String pageHtml(int segment, String title) { + return pageHtmlStyle(segment, title, null); + } + + /** + * Returns the default html for a workplace page, including setting of DOCTYPE and + * inserting a header with the content-type, allowing the selection of an individual style sheet.<p> + * + * @param segment the HTML segment (START / END) + * @param title the title of the page, if null no title tag is inserted + * @param stylesheet the used style sheet, if null the default stylesheet 'workplace.css' is inserted + * @return the default html for a workplace page + */ + public String pageHtmlStyle(int segment, String title, String stylesheet) { + if (segment == HTML_START) { + StringBuffer result = new StringBuffer(512); +// result.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n"); +// result.append("<html>\n<head>\n"); +// if (title != null) { +// result.append("<title>"); +// result.append(title); +// result.append("</title>\n"); +// } +// result.append("<meta HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">\n"); + result.append("<link rel=\"stylesheet\" type=\"text/css\" href=\""); + result.append("/pricat/includes/pricat.css"); + result.append("\">\n"); + return result.toString(); + } else { + return ""; +// return "</html>"; + } + } + + /** + * Returns the start html for the outer dialog window border. + * + * @return the start html for the outer dialog window border + */ + public String dialogStart() { + return dialog(HTML_START, null); + } + + /** + * Builds the outer dialog window border. + * + * @param segment the HTML segment (START / END) + * @param attributes optional additional attributes for the opening dialog table + * + * @return a dialog window start / end segment + */ + public String dialog(int segment, String attributes) { + if (segment == HTML_START) { + StringBuffer html = new StringBuffer(512); + html.append("<table class=\"dialog\" cellpadding=\"0\" cellspacing=\"0\""); + if (attributes != null) { + html.append(" "); + html.append(attributes); + } + html.append("><tr><td>\n<table class=\"dialogbox\" cellpadding=\"0\" cellspacing=\"0\">\n"); + html.append("<tr><td>\n"); + return html.toString(); + } else { + return "</td></tr></table>\n</td></tr></table>\n<p> </p>\n"; + } + } + + /** + * Returns the start html for the content area of the dialog window.<p> + * + * @param title the title for the dialog + * + * @return the start html for the content area of the dialog window + */ + public String dialogContentStart(String title) { + return dialogContent(HTML_START, title); + } + + /** + * Builds the content area of the dialog window.<p> + * + * @param segment the HTML segment (START / END) + * @param title the title String for the dialog window + * + * @return a content area start / end segment + */ + public String dialogContent(int segment, String title) { + if (segment == HTML_START) { + StringBuffer result = new StringBuffer(512); + // null title is ok, we always want the title headline + result.append(dialogHead(title)); + result.append("<div class=\"dialogcontent\" unselectable=\"on\">\n"); + result.append("<!-- dialogcontent start -->\n"); + return result.toString(); + } else { + return "<!-- dialogcontent end -->\n</div>\n"; + } + } + + /** + * Builds the title of the dialog window.<p> + * + * @param title the title String for the dialog window + * + * @return the HTML title String for the dialog window + */ + public String dialogHead(String title) { + return "<div class=\"dialoghead\" unselectable=\"on\">" + (title == null ? "" : title) + "</div>"; + } + + /** + * Returns the value of the title parameter, + * or null if this parameter was not provided.<p> + * + * This parameter is used to build the title + * of the dialog. It is a parameter so that the title + * can be passed to included elements.<p> + * + * @return the value of the title parameter + */ + public String getParamTitle(HttpServletRequest request) { + if (paramTitle == null) { + paramTitle = request.getParameter("title"); + } + return paramTitle != null ? paramTitle : ""; + } + + /** + * Returns all initialized parameters of the current workplace class + * as hidden field tags that can be inserted in a form.<p> + * + * @return all initialized parameters of the current workplace class + * as hidden field tags that can be inserted in a html form + */ + public String paramsAsHidden(HttpServletRequest request) { + return paramsAsHidden(request, null); + } + + /** + * Returns all initialized parameters of the current workplace class + * that are not in the given exclusion list as hidden field tags that can be inserted in a form.<p> + * + * @param excludes the parameters to exclude + * + * @return all initialized parameters of the current workplace class + * that are not in the given exclusion list as hidden field tags that can be inserted in a form + */ + public String paramsAsHidden(HttpServletRequest request, Collection<?> excludes) { + StringBuffer result = new StringBuffer(512); + Map<String, Object> params = paramValues(request); + Iterator<?> i = params.entrySet().iterator(); + while (i.hasNext()) { + Map.Entry entry = (Map.Entry)i.next(); + String param = (String)entry.getKey(); + if ((excludes == null) || (!excludes.contains(param))) { + result.append("<input type=\"hidden\" name=\""); + result.append(param); + result.append("\" value=\""); + String encoded = ReportEncoder.encode( + entry.getValue().toString(), + "UTF-8"); + result.append(encoded); + result.append("\">\n"); + } + } + + return result.toString(); + } + + /** + * Returns the values of all parameter methods of this workplace class instance.<p> + * + * @return the values of all parameter methods of this workplace class instance + */ + protected Map<String, Object> paramValues(HttpServletRequest request) { + List<Method> methods = paramGetMethods(); + Map<String, Object> map = new HashMap<String, Object>(methods.size()); + Iterator<Method> i = methods.iterator(); + while (i.hasNext()) { + Method m = (Method)i.next(); + Object o = null; + try { + o = m.invoke(this, new Object[0]); + } catch (InvocationTargetException ite) { + // can usually be ignored + } catch (IllegalAccessException eae) { + // can usually be ignored + } + if (o != null) { + map.put(m.getName().substring(8).toLowerCase(), o); + } + } + return map; + } + + /** + * Returns a list of all methods of the current class instance that + * start with "getParam" and have no parameters.<p> + * + * @return a list of all methods of the current class instance that + * start with "getParam" and have no parameters + */ + private List<Method> paramGetMethods() { + List<Method> list = new ArrayList<Method>(); + Method[] methods = this.getClass().getMethods(); + int length = methods.length; + for (int i = 0; i < length; i++) { + Method method = methods[i]; + if (method.getName().startsWith("getParam") && (method.getParameterTypes().length == 0)) { + // Debug.logInfo("getMethod: " + method.getName(), module); + list.add(method); + } + } + return list; + } + + /** + * Returns an optional introduction text to be displayed above the report output.<p> + * + * @return an optional introduction text + */ + public String reportIntroductionText() { + return ""; + } + + /** + * Returns an optional conclusion text to be displayed below the report output.<p> + * + * @return an optional conclusion text + */ + public String reportConclusionText() { + return ""; + } + + /** + * Returns the end html for the content area of the dialog window.<p> + * + * @return the end html for the content area of the dialog window + */ + public String dialogContentEnd() { + return dialogContent(HTML_END, null); + } + + /** + * Builds a button row with an "Ok" and a "Cancel" button.<p> + * [... 429 lines stripped ...] |
Free forum by Nabble | Edit this page |