001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.workplace; 029 030import org.opencms.file.CmsObject; 031import org.opencms.i18n.CmsMessageContainer; 032import org.opencms.jsp.CmsJspActionElement; 033import org.opencms.main.CmsException; 034import org.opencms.main.CmsLog; 035import org.opencms.main.OpenCms; 036import org.opencms.report.A_CmsReportThread; 037import org.opencms.report.I_CmsReport; 038import org.opencms.util.CmsStringUtil; 039import org.opencms.util.CmsUUID; 040 041import javax.servlet.http.HttpServletRequest; 042import javax.servlet.http.HttpServletResponse; 043import javax.servlet.jsp.PageContext; 044 045import org.apache.commons.logging.Log; 046 047/** 048 * Provides an output window for a CmsReport.<p> 049 * 050 * @since 6.0.0 051 */ 052public class CmsReport extends CmsMultiDialog { 053 054 /** Request parameter key for the type of the report. */ 055 public static final String PARAM_REPORT_CONTINUEKEY = "reportcontinuekey"; 056 057 /** Request parameter key for the type of the report. */ 058 public static final String PARAM_REPORT_TYPE = "reporttype"; 059 060 /** Max. byte size of report output on client. */ 061 public static final int REPORT_UPDATE_SIZE = 512000; 062 063 /** Update time for report reloading. */ 064 public static final int REPORT_UPDATE_TIME = 2000; 065 066 /** The log object for this class. */ 067 private static final Log LOG = CmsLog.getLog(CmsReport.class); 068 069 /** Flag for refreching workplace .*/ 070 private String m_paramRefreshWorkplace; 071 072 /** The key name which contains the localized message for the continue checkbox. */ 073 private String m_paramReportContinueKey; 074 075 /** The type of this report. */ 076 private String m_paramReportType; 077 078 /** The thread to display in this report. */ 079 private CmsUUID m_paramThread; 080 081 /** The next thread to display after this report. */ 082 private String m_paramThreadHasNext; 083 084 /** 085 * Public constructor.<p> 086 * 087 * @param jsp an initialized JSP action element 088 */ 089 public CmsReport(CmsJspActionElement jsp) { 090 091 super(jsp); 092 } 093 094 /** 095 * Public constructor with JSP variables.<p> 096 * 097 * @param context the JSP page context 098 * @param req the JSP request 099 * @param res the JSP response 100 */ 101 public CmsReport(PageContext context, HttpServletRequest req, HttpServletResponse res) { 102 103 this(new CmsJspActionElement(context, req, res)); 104 } 105 106 /** 107 * Returns the style sheets for the report.<p> 108 * 109 * @param cms the current users context 110 * @return the style sheets for the report 111 */ 112 public static String generateCssStyle(CmsObject cms) { 113 114 StringBuffer result = new StringBuffer(128); 115 result.append("<style type='text/css'>\n"); 116 String contents = ""; 117 try { 118 contents = new String( 119 cms.readFile(CmsWorkplace.VFS_PATH_COMMONS + "style/report.css").getContents(), 120 OpenCms.getSystemInfo().getDefaultEncoding()); 121 } catch (Exception e) { 122 // ignore 123 } 124 if (CmsStringUtil.isEmpty(contents)) { 125 // css file not found, create default styles 126 result.append( 127 "body { box-sizing: border-box; -moz-box-sizing: border-box; padding: 2px; margin: 0; color: /*begin-color WindowText*/#000000/*end-color*/; background-color: /*begin-color Window*/#ffffff/*end-color*/; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; }\n"); 128 result.append( 129 "div.main { box-sizing: border-box; -moz-box-sizing: border-box; color: /*begin-color WindowText*/#000000/*end-color*/; white-space: nowrap; }\n"); 130 result.append("span.head { color: #000099; font-weight: bold; }\n"); 131 result.append("span.note { color: #666666; }\n"); 132 result.append("span.ok { color: #009900; }\n"); 133 result.append("span.warn { color: #990000; padding-left: 40px; }\n"); 134 result.append("span.err { color: #990000; font-weight: bold; padding-left: 40px; }\n"); 135 result.append("span.throw { color: #990000; font-weight: bold; }\n"); 136 result.append("span.link1 { color: #666666; }\n"); 137 result.append("span.link2 { color: #666666; padding-left: 40px; }\n"); 138 result.append("span.link2 { color: #990000; }\n"); 139 } else { 140 result.append(contents); 141 } 142 result.append("</style>\n"); 143 return result.toString(); 144 } 145 146 /** 147 * Generates the footer for the extended report view.<p> 148 * 149 * @return html code 150 */ 151 public static String generatePageEndExtended() { 152 153 StringBuffer result = new StringBuffer(128); 154 result.append("</div>\n"); 155 result.append("</body>\n"); 156 result.append("</html>\n"); 157 return result.toString(); 158 } 159 160 /** 161 * Generates the footer for the simple report view.<p> 162 * 163 * @return html code 164 */ 165 public static String generatePageEndSimple() { 166 167 StringBuffer result = new StringBuffer(128); 168 result.append("</td></tr>\n"); 169 result.append("</table></div>\n"); 170 result.append("</body>\n</html>"); 171 return result.toString(); 172 } 173 174 /** 175 * Generates the header for the extended report view.<p> 176 * 177 * @param cms the current users context 178 * @param encoding the encoding string 179 * 180 * @return html code 181 */ 182 public static String generatePageStartExtended(CmsObject cms, String encoding) { 183 184 StringBuffer result = new StringBuffer(128); 185 result.append("<html>\n<head>\n"); 186 result.append("<meta HTTP-EQUIV='Content-Type' CONTENT='text/html; charset="); 187 result.append(encoding); 188 result.append("'>\n"); 189 result.append(generateCssStyle(cms)); 190 result.append("</head>\n"); 191 result.append("<body style='overflow: auto;'>\n"); 192 result.append("<div class='main'>\n"); 193 return result.toString(); 194 } 195 196 /** 197 * Generates the header for the simple report view.<p> 198 * 199 * @param wp the workplace instance 200 * 201 * @return html code 202 */ 203 public static String generatePageStartSimple(CmsWorkplace wp) { 204 205 StringBuffer result = new StringBuffer(128); 206 result.append("<html>\n<head>\n"); 207 result.append("<meta HTTP-EQUIV='Content-Type' CONTENT='text/html; charset="); 208 result.append(wp.getEncoding()); 209 result.append("'>\n"); 210 result.append("<link rel='stylesheet' type='text/css' href='"); 211 result.append(wp.getStyleUri("workplace.css")); 212 result.append("'>\n"); 213 result.append(generateCssStyle(wp.getCms())); 214 result.append("</head>\n"); 215 result.append("<body style='background-color:/*begin-color Menu*/#f0f0f0/*end-color*/;'>\n"); 216 result.append("<div style='vertical-align:middle; height: 100%;'>\n"); 217 result.append("<table border='0' style='vertical-align:middle; height: 100%;'>\n"); 218 result.append("<tr><td width='40' align='center' valign='middle'><img name='report_img' src='"); 219 result.append(CmsWorkplace.getSkinUri()); 220 result.append("commons/wait.gif' width='32' height='32' alt=''></td>\n"); 221 result.append("<td valign='middle'>"); 222 return result.toString(); 223 } 224 225 /** 226 * Returns an initialized CmsReport instance that is read from the request attributes.<p> 227 * 228 * This method is used by dialog elements. 229 * The dialog elements do not initialize their own workplace class, 230 * but use the initialized instance of the "master" class. 231 * This is required to ensure that parameters of the "master" class 232 * can properly be kept on the dialog elements.<p> 233 * 234 * To prevent null pointer exceptions, an empty dialog is returned if 235 * nothing is found in the request attributes.<p> 236 * 237 * @param context the JSP page context 238 * @param req the JSP request 239 * @param res the JSP response 240 * @return an initialized CmsDialog instance that is read from the request attributes 241 */ 242 public static CmsReport initCmsReport(PageContext context, HttpServletRequest req, HttpServletResponse res) { 243 244 CmsReport wp = (CmsReport)req.getAttribute(CmsWorkplace.SESSION_WORKPLACE_CLASS); 245 if (wp == null) { 246 // ensure that we don't get null pointers if the page is directly called 247 wp = new CmsReport(new CmsJspActionElement(context, req, res)); 248 } 249 return wp; 250 } 251 252 /** 253 * Builds a button row with an "Ok", a "Cancel" and a "Details" button.<p> 254 * 255 * This row is displayed when the first report is running.<p> 256 * 257 * @param okAttrs optional attributes for the ok button 258 * @param cancelAttrs optional attributes for the cancel button 259 * @param detailsAttrs optional attributes for the details button 260 * @return the button row 261 */ 262 public String dialogButtonsContinue(String okAttrs, String cancelAttrs, String detailsAttrs) { 263 264 if (CmsStringUtil.isEmptyOrWhitespaceOnly(detailsAttrs)) { 265 detailsAttrs = ""; 266 } else { 267 detailsAttrs += " "; 268 } 269 return dialogButtons( 270 new int[] {BUTTON_OK, BUTTON_CANCEL, BUTTON_DETAILS}, 271 new String[] {okAttrs, cancelAttrs, detailsAttrs + "onclick=\"switchOutputFormat();\""}); 272 } 273 274 /** 275 * Builds a button row with an "Ok", a "Cancel" and a "Details" button.<p> 276 * 277 * This row is used when a single report is running or after the first report has finished.<p> 278 * 279 * @param okAttrs optional attributes for the ok button 280 * @param cancelAttrs optional attributes for the cancel button 281 * @param detailsAttrs optional attributes for the details button 282 * @return the button row 283 */ 284 public String dialogButtonsOkCancelDetails(String okAttrs, String cancelAttrs, String detailsAttrs) { 285 286 if (CmsStringUtil.isEmptyOrWhitespaceOnly(detailsAttrs)) { 287 detailsAttrs = ""; 288 } else { 289 detailsAttrs += " "; 290 } 291 292 if (Boolean.valueOf(getParamThreadHasNext()).booleanValue() 293 && CmsStringUtil.isNotEmpty(getParamReportContinueKey())) { 294 return dialogButtons( 295 new int[] {BUTTON_OK, BUTTON_CANCEL, BUTTON_DETAILS}, 296 new String[] {okAttrs, cancelAttrs, detailsAttrs + "onclick=\"switchOutputFormat();\""}); 297 } 298 return dialogButtons( 299 new int[] {BUTTON_OK, BUTTON_DETAILS}, 300 new String[] {okAttrs, detailsAttrs + "onclick=\"switchOutputFormat();\""}); 301 } 302 303 /** 304 * Returns if the workplace must be refreshed.<p> 305 * 306 * @return <code>"true"</code> if the workplace must be refreshed. 307 */ 308 public String getParamRefreshWorkplace() { 309 310 return m_paramRefreshWorkplace; 311 } 312 313 /** 314 * Returns the key name which contains the localized message for the continue checkbox.<p> 315 * 316 * @return the key name which contains the localized message for the continue checkbox 317 */ 318 public String getParamReportContinueKey() { 319 320 if (m_paramReportContinueKey == null) { 321 m_paramReportContinueKey = ""; 322 } 323 return m_paramReportContinueKey; 324 } 325 326 /** 327 * Returns the type of this report.<p> 328 * 329 * @return the type of this report 330 */ 331 public String getParamReportType() { 332 333 if (m_paramReportType == null) { 334 // the default report type is the simple report 335 setParamReportType(getSettings().getUserSettings().getWorkplaceReportType()); 336 } 337 338 return m_paramReportType; 339 } 340 341 /** 342 * Returns the Thread id to display in this report.<p> 343 * 344 * @return the Thread id to display in this report 345 */ 346 public String getParamThread() { 347 348 if ((m_paramThread != null) && (!m_paramThread.equals(CmsUUID.getNullUUID()))) { 349 return m_paramThread.toString(); 350 } else { 351 return null; 352 } 353 } 354 355 /** 356 * Returns if another report is following this report.<p> 357 * 358 * @return <code>"true"</code> if another report is following this report 359 */ 360 public String getParamThreadHasNext() { 361 362 if (m_paramThreadHasNext == null) { 363 m_paramThreadHasNext = ""; 364 } 365 return m_paramThreadHasNext; 366 } 367 368 /** 369 * Returns the part of the report that is ready for output.<p> 370 * 371 * @return the part of the report that is ready for output 372 */ 373 public String getReportUpdate() { 374 375 A_CmsReportThread thread = OpenCms.getThreadStore().retrieveThread(m_paramThread); 376 if (thread != null) { 377 return thread.getReportUpdate(); 378 } else { 379 return ""; 380 } 381 } 382 383 /** 384 * Returns if the report generated an error output.<p> 385 * 386 * @return true if the report generated an error, otherwise false 387 */ 388 public boolean hasError() { 389 390 A_CmsReportThread thread = OpenCms.getThreadStore().retrieveThread(m_paramThread); 391 if (thread != null) { 392 return thread.hasError(); 393 } else { 394 return false; 395 } 396 } 397 398 /** 399 * Builds the start html of the page, including setting of DOCTYPE and 400 * inserting a header with the content-type.<p> 401 * 402 * This overloads the default method of the parent class.<p> 403 * 404 * @return the start html of the page 405 */ 406 @Override 407 public String htmlStart() { 408 409 return pageHtml(HTML_START, true); 410 } 411 412 /** 413 * Builds the start html of the page, including setting of DOCTYPE and 414 * inserting a header with the content-type.<p> 415 * 416 * This overloads the default method of the parent class.<p> 417 * 418 * @param loadStyles if true, the defaul style sheet will be loaded 419 * @return the start html of the page 420 */ 421 public String htmlStart(boolean loadStyles) { 422 423 return pageHtml(HTML_START, loadStyles); 424 } 425 426 /** 427 * Returns true if the report Thread is still alive (i.e. running), false otherwise.<p> 428 * 429 * @return true if the report Thread is still alive 430 */ 431 public boolean isAlive() { 432 433 A_CmsReportThread thread = OpenCms.getThreadStore().retrieveThread(m_paramThread); 434 if (thread != null) { 435 return thread.isAlive(); 436 } else { 437 return false; 438 } 439 } 440 441 /** 442 * Checks whether this is a simple report.<p> 443 * 444 * @return true, if the type of this report is a "simple" 445 */ 446 public boolean isSimpleReport() { 447 448 return getParamReportType().equalsIgnoreCase(I_CmsReport.REPORT_TYPE_SIMPLE); 449 } 450 451 /** 452 * Builds the start html of the page, including setting of DOCTYPE and 453 * inserting a header with the content-type.<p> 454 * 455 * This overloads the default method of the parent class.<p> 456 * 457 * @param segment the HTML segment (START / END) 458 * @param loadStyles if true, the defaul style sheet will be loaded 459 * @return the start html of the page 460 */ 461 public String pageHtml(int segment, boolean loadStyles) { 462 463 if (useNewStyle()) { 464 return super.pageHtml(segment, null, getParamTitle()); 465 } 466 if (segment == HTML_START) { 467 StringBuffer result = new StringBuffer(512); 468 result.append("<!DOCTYPE html>\n"); 469 result.append("<html>\n<head>\n"); 470 result.append("<meta HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset="); 471 result.append(getEncoding()); 472 result.append("\">\n"); 473 if (loadStyles) { 474 result.append("<link rel=\"stylesheet\" type=\"text/css\" href=\""); 475 result.append(getStyleUri(getJsp(), "workplace.css")); 476 result.append("\">\n"); 477 result.append("<script >\n"); 478 result.append(dialogScriptSubmit()); 479 result.append("</script>\n"); 480 } 481 return result.toString(); 482 } else { 483 return "</html>"; 484 } 485 486 } 487 488 /** 489 * Returns an optional conclusion text to be displayed below the report output.<p> 490 * 491 * @return an optional conclusion text 492 */ 493 public String reportConclusionText() { 494 495 return ""; 496 } 497 498 /** 499 * Returns an optional introduction text to be displayed above the report output.<p> 500 * 501 * @return an optional introduction text 502 */ 503 public String reportIntroductionText() { 504 505 return ""; 506 } 507 508 /** 509 * Sets if the workplace must be refreshed.<p> 510 * 511 * @param value <code>"true"</code> (String) if the workplace must be refreshed. 512 */ 513 public void setParamRefreshWorkplace(String value) { 514 515 m_paramRefreshWorkplace = value; 516 } 517 518 /** 519 * Sets the key name which contains the localized message for the continue checkbox.<p> 520 * 521 * @param key the key name which contains the localized message for the continue checkbox 522 */ 523 public void setParamReportContinueKey(String key) { 524 525 m_paramReportContinueKey = key; 526 } 527 528 /** 529 * Sets the type of this report.<p> 530 * 531 * @param value the type of this report 532 */ 533 public void setParamReportType(String value) { 534 535 m_paramReportType = value; 536 } 537 538 /** 539 * Sets the Thread id to display in this report.<p> 540 * 541 * @param value the Thread id to display in this report 542 */ 543 public void setParamThread(String value) { 544 545 m_paramThread = CmsUUID.getNullUUID(); 546 if (value != null) { 547 try { 548 m_paramThread = new CmsUUID(value); 549 } catch (Exception e) { 550 // can usually be ignored 551 if (LOG.isInfoEnabled()) { 552 LOG.info( 553 Messages.get().getBundle().key(Messages.LOG_THREAD_CREATION_FAILED_1, Integer.valueOf(value)), 554 e); 555 } 556 } 557 } 558 } 559 560 /** 561 * Sets if another report is following this report.<p> 562 * 563 * @param value <code>"true"</code> if another report is following this report 564 */ 565 public void setParamThreadHasNext(String value) { 566 567 m_paramThreadHasNext = value; 568 } 569 570 /** 571 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 572 */ 573 @Override 574 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 575 576 // fill the parameter values in the get/set methods 577 fillParamValues(request); 578 // set the action for the JSP switch 579 if (REPORT_UPDATE.equals(getParamAction())) { 580 setAction(ACTION_REPORT_UPDATE); 581 } else { 582 setAction(ACTION_REPORT_BEGIN); 583 } 584 } 585 586 /** 587 * Returns always true and does nothing else, has to be implemented.<p> 588 * 589 * @see org.opencms.workplace.CmsMultiDialog#performDialogOperation() 590 */ 591 @Override 592 protected boolean performDialogOperation() throws CmsException { 593 594 throw new CmsException(new CmsMessageContainer(null, "")); 595 } 596}