blob: 761e8f63ca3dc51180f0cd5d01c7120fc662e810 [file] [log] [blame]
/*******************************************************************************
* 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>&nbsp;</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;
}
}