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.db.CmsDbEntryNotFoundException; 031import org.opencms.db.CmsUserSettings; 032import org.opencms.file.CmsObject; 033import org.opencms.file.CmsProject; 034import org.opencms.file.CmsRequestContext; 035import org.opencms.file.CmsResource; 036import org.opencms.file.CmsResourceFilter; 037import org.opencms.file.CmsUser; 038import org.opencms.i18n.CmsEncoder; 039import org.opencms.i18n.CmsMessages; 040import org.opencms.i18n.CmsMultiMessages; 041import org.opencms.jsp.CmsJspActionElement; 042import org.opencms.lock.CmsLock; 043import org.opencms.lock.CmsLockType; 044import org.opencms.main.CmsBroadcast; 045import org.opencms.main.CmsContextInfo; 046import org.opencms.main.CmsException; 047import org.opencms.main.CmsIllegalStateException; 048import org.opencms.main.CmsLog; 049import org.opencms.main.CmsSessionInfo; 050import org.opencms.main.CmsStaticResourceHandler; 051import org.opencms.main.OpenCms; 052import org.opencms.security.CmsRole; 053import org.opencms.security.CmsRoleViolationException; 054import org.opencms.site.CmsSite; 055import org.opencms.site.CmsSiteManagerImpl; 056import org.opencms.synchronize.CmsSynchronizeSettings; 057import org.opencms.util.CmsMacroResolver; 058import org.opencms.util.CmsRequestUtil; 059import org.opencms.util.CmsStringUtil; 060import org.opencms.util.CmsUUID; 061 062import java.io.IOException; 063import java.lang.reflect.InvocationTargetException; 064import java.lang.reflect.Method; 065import java.util.ArrayList; 066import java.util.Collection; 067import java.util.HashMap; 068import java.util.Iterator; 069import java.util.List; 070import java.util.Locale; 071import java.util.Map; 072import java.util.Map.Entry; 073 074import javax.servlet.ServletException; 075import javax.servlet.http.HttpServletRequest; 076import javax.servlet.http.HttpServletResponse; 077import javax.servlet.http.HttpSession; 078import javax.servlet.jsp.PageContext; 079 080import org.apache.commons.collections.Buffer; 081import org.apache.commons.fileupload.FileItem; 082import org.apache.commons.logging.Log; 083 084/** 085 * Master class for the JSP based workplace which provides default methods and 086 * session handling for all JSP workplace classes.<p> 087 * 088 * @since 6.0.0 089 */ 090public abstract class CmsWorkplace { 091 092 /** The debug flag. */ 093 public static final boolean DEBUG = false; 094 095 /** Path to the JSP workplace frame loader file. */ 096 public static final String JSP_WORKPLACE_URI = CmsWorkplace.VFS_PATH_VIEWS + "workplace.jsp"; 097 098 /** Request parameter name for the model file. */ 099 public static final String PARAM_MODELFILE = "modelfile"; 100 101 /** Request parameter name prefix for the preferred editors. */ 102 public static final String INPUT_DEFAULT = "default"; 103 104 /** Request parameter name for the resource list. */ 105 public static final String PARAM_RESOURCELIST = "resourcelist"; 106 107 /** Request parameter name for no settings in start galleries. */ 108 public static final String INPUT_NONE = "none"; 109 110 /** Path to system folder. */ 111 public static final String VFS_PATH_SYSTEM = "/system/"; 112 113 /** Path to sites folder. */ 114 public static final String VFS_PATH_SITES = "/sites/"; 115 116 /** Path to the workplace. */ 117 public static final String VFS_PATH_WORKPLACE = VFS_PATH_SYSTEM + "workplace/"; 118 119 /** Constant for the JSP dialogs path. */ 120 public static final String PATH_DIALOGS = VFS_PATH_WORKPLACE + "commons/"; 121 122 /** Parameter for the default locale. */ 123 public static final Locale DEFAULT_LOCALE = Locale.ENGLISH; 124 125 /** Parameter for the default language. */ 126 public static final String DEFAULT_LANGUAGE = DEFAULT_LOCALE.getLanguage(); 127 128 /** Constant for the JSP common files (e.g. error page) path. */ 129 public static final String DIALOG_PATH_COMMON = PATH_DIALOGS + "includes/"; 130 131 /** Constant for the JSP common close dialog page. */ 132 public static final String FILE_DIALOG_CLOSE = DIALOG_PATH_COMMON + "closedialog.jsp"; 133 134 /** Constant for the JSP common confirmation dialog. */ 135 public static final String FILE_DIALOG_SCREEN_CONFIRM = DIALOG_PATH_COMMON + "confirmation.jsp"; 136 137 /** Constant for the JSP common error dialog. */ 138 public static final String FILE_DIALOG_SCREEN_ERROR = DIALOG_PATH_COMMON + "error.jsp"; 139 140 /** Constant for the JSP common error dialog. */ 141 public static final String FILE_DIALOG_SCREEN_ERRORPAGE = DIALOG_PATH_COMMON + "errorpage.jsp"; 142 143 /** Constant for the JSP common wait screen. */ 144 public static final String FILE_DIALOG_SCREEN_WAIT = DIALOG_PATH_COMMON + "wait.jsp"; 145 146 /** Path to workplace views. */ 147 public static final String VFS_PATH_VIEWS = VFS_PATH_WORKPLACE + "views/"; 148 149 /** Constant for the JSP explorer filelist file. */ 150 public static final String FILE_EXPLORER_FILELIST = VFS_PATH_VIEWS + "explorer/explorer_files.jsp"; 151 152 /** Constant for the JSP common report page. */ 153 public static final String FILE_REPORT_OUTPUT = DIALOG_PATH_COMMON + "report.jsp"; 154 155 /** Helper variable to deliver the html end part. */ 156 public static final int HTML_END = 1; 157 158 /** Helper variable to deliver the html start part. */ 159 public static final int HTML_START = 0; 160 161 /** The request parameter for the workplace project selection. */ 162 public static final String PARAM_WP_EXPLORER_RESOURCE = "wpExplorerResource"; 163 164 /** The request parameter for the workplace project selection. */ 165 public static final String PARAM_WP_PROJECT = "wpProject"; 166 167 /** The request parameter for the workplace site selection. */ 168 public static final String PARAM_WP_SITE = "wpSite"; 169 170 /** Constant for the JSP workplace path. */ 171 public static final String PATH_WORKPLACE = VFS_PATH_WORKPLACE; 172 173 /** Path for file type icons relative to the resources folder. */ 174 public static final String RES_PATH_FILETYPES = "filetypes/"; 175 176 /** Path to exported system image folder. */ 177 public static final String RFS_PATH_RESOURCES = "/resources/"; 178 179 /** Directory name of content default_bodies folder. */ 180 public static final String VFS_DIR_DEFAULTBODIES = "default_bodies/"; 181 182 /** Directory name of content templates folder. */ 183 public static final String VFS_DIR_TEMPLATES = "templates/"; 184 185 /** Path to commons. */ 186 public static final String VFS_PATH_COMMONS = VFS_PATH_WORKPLACE + "commons/"; 187 188 /** Path to the workplace editors. */ 189 public static final String VFS_PATH_EDITORS = VFS_PATH_WORKPLACE + "editors/"; 190 191 /** Path to the galleries. */ 192 public static final String VFS_PATH_GALLERIES = VFS_PATH_SYSTEM + "galleries/"; 193 194 /** Path to locales. */ 195 public static final String VFS_PATH_LOCALES = VFS_PATH_WORKPLACE + "locales/"; 196 197 /** Path to modules folder. */ 198 public static final String VFS_PATH_MODULES = VFS_PATH_SYSTEM + "modules/"; 199 200 /** Path to system image folder. */ 201 public static final String VFS_PATH_RESOURCES = VFS_PATH_WORKPLACE + "resources/"; 202 203 /** Constant for the direct edit view JSP. */ 204 public static final String VIEW_DIRECT_EDIT = VFS_PATH_VIEWS + "explorer/directEdit.jsp"; 205 206 /** Constant for the explorer view JSP. */ 207 public static final String VIEW_WORKPLACE = VFS_PATH_VIEWS + "explorer/explorer_fs.jsp"; 208 209 /** Constant for the admin view JSP. */ 210 public static final String VIEW_ADMIN = CmsWorkplace.VFS_PATH_VIEWS + "admin/admin-fs.jsp"; 211 212 /** Key name for the request attribute to indicate a multipart request was already parsed. */ 213 protected static final String REQUEST_ATTRIBUTE_MULTIPART = "__CmsWorkplace.MULTIPART"; 214 215 /** Key name for the request attribute to reload the folder tree view. */ 216 protected static final String REQUEST_ATTRIBUTE_RELOADTREE = "__CmsWorkplace.RELOADTREE"; 217 218 /** Key name for the session workplace class. */ 219 protected static final String SESSION_WORKPLACE_CLASS = "__CmsWorkplace.WORKPLACE_CLASS"; 220 221 /** The "explorerview" view selection. */ 222 public static final String VIEW_EXPLORER = "explorerview"; 223 224 /** The "galleryview" view selection. */ 225 public static final String VIEW_GALLERY = "galleryview"; 226 227 /** The "list" view selection. */ 228 public static final String VIEW_LIST = "listview"; 229 230 /** Request parameter name for the directpublish parameter. */ 231 public static final String PARAM_DIRECTPUBLISH = "directpublish"; 232 233 /** Request parameter name for the publishsiblings parameter. */ 234 public static final String PARAM_PUBLISHSIBLINGS = "publishsiblings"; 235 236 /** Request parameter name for the relatedresources parameter. */ 237 public static final String PARAM_RELATEDRESOURCES = "relatedresources"; 238 239 /** Request parameter name for the subresources parameter. */ 240 public static final String PARAM_SUBRESOURCES = "subresources"; 241 242 /** Default value for date last modified, the release and expire date. */ 243 public static final String DEFAULT_DATE_STRING = "-"; 244 245 /** Absolute path to the model file dialog. */ 246 public static final String VFS_PATH_MODELDIALOG = CmsWorkplace.VFS_PATH_COMMONS 247 + "newresource_xmlcontent_modelfile.jsp"; 248 249 /** Absolute path to thenew resource dialog. */ 250 public static final String VFS_PATH_NEWRESOURCEDIALOG = CmsWorkplace.VFS_PATH_COMMONS 251 + "newresource_xmlcontent.jsp"; 252 253 /** Request parameter name for the new resource type. */ 254 public static final String PARAM_NEWRESOURCETYPE = "newresourcetype"; 255 256 /** The log object for this class. */ 257 private static final Log LOG = CmsLog.getLog(CmsWorkplace.class); 258 259 /** The link to the explorer file list (cached for performance reasons). */ 260 private static String m_file_explorer_filelist; 261 262 /** The URI to the skin resources (cached for performance reasons). */ 263 private static String m_skinUri; 264 265 /** The URI to the stylesheet resources (cached for performance reasons). */ 266 private static String m_styleUri; 267 268 /** The request parameter for the workplace view selection. */ 269 public static final String PARAM_WP_VIEW = "wpView"; 270 271 /** The request parameter for the workplace start selection. */ 272 public static final String PARAM_WP_START = "wpStart"; 273 274 /** The current users OpenCms context. */ 275 private CmsObject m_cms; 276 277 /** Helper variable to store the id of the current project. */ 278 private CmsUUID m_currentProjectId; 279 280 /** Flag for indicating that request forwarded was. */ 281 private boolean m_forwarded; 282 283 /** The current JSP action element. */ 284 private CmsJspActionElement m_jsp; 285 286 /** The macro resolver, this is cached to avoid multiple instance generation. */ 287 private CmsMacroResolver m_macroResolver; 288 289 /** The currently used message bundle. */ 290 private CmsMultiMessages m_messages; 291 292 /** The list of multi part file items (if available). */ 293 private List<FileItem> m_multiPartFileItems; 294 295 /** The map of parameters read from the current request. */ 296 private Map<String, String[]> m_parameterMap; 297 298 /** The current resource URI. */ 299 private String m_resourceUri; 300 301 /** The current OpenCms users http session. */ 302 private HttpSession m_session; 303 304 /** The current OpenCms users workplace settings. */ 305 private CmsWorkplaceSettings m_settings; 306 307 /** 308 * Public constructor.<p> 309 * 310 * @param jsp the initialized JSP context 311 */ 312 public CmsWorkplace(CmsJspActionElement jsp) { 313 314 initWorkplaceMembers(jsp); 315 } 316 317 /** 318 * Constructor in case no page context is available.<p> 319 * 320 * @param cms the current user context 321 * @param session the session 322 */ 323 public CmsWorkplace(CmsObject cms, HttpSession session) { 324 325 initWorkplaceMembers(cms, session); 326 } 327 328 /** 329 * Public constructor with JSP variables.<p> 330 * 331 * @param context the JSP page context 332 * @param req the JSP request 333 * @param res the JSP response 334 */ 335 public CmsWorkplace(PageContext context, HttpServletRequest req, HttpServletResponse res) { 336 337 this(new CmsJspActionElement(context, req, res)); 338 } 339 340 /** 341 * Generates a html select box out of the provided values.<p> 342 * 343 * @param parameters a string that will be inserted into the initial select tag, 344 * if null no parameters will be inserted 345 * @param options the options 346 * @param values the option values, if null the select will have no value attributes 347 * @param selected the index of the pre-selected option, if -1 no option is pre-selected 348 * @param useLineFeed if true, adds some formatting "\n" to the output String 349 * @return a String representing a html select box 350 */ 351 public static String buildSelect( 352 String parameters, 353 List<String> options, 354 List<String> values, 355 int selected, 356 boolean useLineFeed) { 357 358 StringBuffer result = new StringBuffer(1024); 359 result.append("<select "); 360 if (parameters != null) { 361 result.append(parameters); 362 } 363 result.append(">"); 364 if (useLineFeed) { 365 result.append("\n"); 366 } 367 int length = options.size(); 368 String value = null; 369 for (int i = 0; i < length; i++) { 370 if (values != null) { 371 try { 372 value = values.get(i); 373 } catch (Exception e) { 374 // can usually be ignored 375 if (LOG.isInfoEnabled()) { 376 LOG.info(e.getLocalizedMessage()); 377 } 378 // lists are not properly initialized, just don't use the value 379 value = null; 380 } 381 } 382 if (value == null) { 383 result.append("<option"); 384 if (i == selected) { 385 result.append(" selected=\"selected\""); 386 } 387 result.append(">"); 388 result.append(options.get(i)); 389 result.append("</option>"); 390 if (useLineFeed) { 391 result.append("\n"); 392 } 393 } else { 394 result.append("<option value=\""); 395 result.append(value); 396 result.append("\""); 397 if (i == selected) { 398 result.append(" selected=\"selected\""); 399 } 400 result.append(">"); 401 result.append(options.get(i)); 402 result.append("</option>"); 403 if (useLineFeed) { 404 result.append("\n"); 405 } 406 } 407 } 408 result.append("</select>"); 409 if (useLineFeed) { 410 result.append("\n"); 411 } 412 return result.toString(); 413 } 414 415 /** 416 * Checks if permissions for roles should be editable for the current user on the resource with the given path.<p> 417 * 418 * @param cms the CMS context 419 * @param path the path of a resource 420 * 421 * @return <code>true</code> if permissions for roles should be editable for the current user on the resource with the given path 422 */ 423 public static boolean canEditPermissionsForRoles(CmsObject cms, String path) { 424 425 return OpenCms.getRoleManager().hasRoleForResource(cms, CmsRole.VFS_MANAGER, path) 426 && path.startsWith(VFS_PATH_SYSTEM); 427 } 428 429 /** 430 * Returns the style sheets for the report.<p> 431 * 432 * @param cms the current users context 433 * @return the style sheets for the report 434 */ 435 public static String generateCssStyle(CmsObject cms) { 436 437 StringBuffer result = new StringBuffer(128); 438 result.append("<style type='text/css'>\n"); 439 String contents = ""; 440 try { 441 contents = new String( 442 cms.readFile(VFS_PATH_COMMONS + "style/report.css").getContents(), 443 OpenCms.getSystemInfo().getDefaultEncoding()); 444 } catch (Exception e) { 445 // ignore 446 } 447 if (CmsStringUtil.isEmpty(contents)) { 448 // css file not found, create default styles 449 result.append( 450 "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"); 451 result.append( 452 "div.main { box-sizing: border-box; -moz-box-sizing: border-box; color: /*begin-color WindowText*/#000000/*end-color*/; white-space: nowrap; }\n"); 453 result.append("span.head { color: #000099; font-weight: bold; }\n"); 454 result.append("span.note { color: #666666; }\n"); 455 result.append("span.ok { color: #009900; }\n"); 456 result.append("span.warn { color: #990000; padding-left: 40px; }\n"); 457 result.append("span.err { color: #990000; font-weight: bold; padding-left: 40px; }\n"); 458 result.append("span.throw { color: #990000; font-weight: bold; }\n"); 459 result.append("span.link1 { color: #666666; }\n"); 460 result.append("span.link2 { color: #666666; padding-left: 40px; }\n"); 461 result.append("span.link2 { color: #990000; }\n"); 462 } else { 463 result.append(contents); 464 } 465 result.append("</style>\n"); 466 return result.toString(); 467 } 468 469 /** 470 * Generates the footer for the extended report view.<p> 471 * 472 * @return html code 473 */ 474 public static String generatePageEndExtended() { 475 476 StringBuffer result = new StringBuffer(128); 477 result.append("</div>\n"); 478 result.append("</body>\n"); 479 result.append("</html>\n"); 480 return result.toString(); 481 } 482 483 /** 484 * Generates the footer for the simple report view.<p> 485 * 486 * @return html code 487 */ 488 public static String generatePageEndSimple() { 489 490 StringBuffer result = new StringBuffer(128); 491 result.append("</td></tr>\n"); 492 result.append("</table></div>\n"); 493 result.append("</body>\n</html>"); 494 return result.toString(); 495 } 496 497 /** 498 * Generates the header for the extended report view.<p> 499 * 500 * @param cms the current users context 501 * @param encoding the encoding string 502 * 503 * @return html code 504 */ 505 public static String generatePageStartExtended(CmsObject cms, String encoding) { 506 507 StringBuffer result = new StringBuffer(128); 508 result.append("<html>\n<head>\n"); 509 result.append("<meta HTTP-EQUIV='Content-Type' CONTENT='text/html; charset="); 510 result.append(encoding); 511 result.append("'>\n"); 512 result.append(generateCssStyle(cms)); 513 result.append("</head>\n"); 514 result.append("<body style='overflow: auto;'>\n"); 515 result.append("<div class='main'>\n"); 516 return result.toString(); 517 } 518 519 /** 520 * Generates the header for the simple report view.<p> 521 * 522 * @param wp the workplace instance 523 * 524 * @return html code 525 */ 526 public static String generatePageStartSimple(CmsWorkplace wp) { 527 528 StringBuffer result = new StringBuffer(128); 529 result.append("<html>\n<head>\n"); 530 result.append("<meta HTTP-EQUIV='Content-Type' CONTENT='text/html; charset="); 531 result.append(wp.getEncoding()); 532 result.append("'>\n"); 533 result.append("<link rel='stylesheet' type='text/css' href='"); 534 result.append(wp.getStyleUri("workplace.css")); 535 result.append("'>\n"); 536 result.append(generateCssStyle(wp.getCms())); 537 result.append("</head>\n"); 538 result.append("<body style='background-color:/*begin-color Menu*/#f0f0f0/*end-color*/;'>\n"); 539 result.append("<div style='vertical-align:middle; height: 100%;'>\n"); 540 result.append("<table border='0' style='vertical-align:middle; height: 100%;'>\n"); 541 result.append("<tr><td width='40' align='center' valign='middle'><img name='report_img' src='"); 542 result.append(getSkinUri()); 543 result.append("commons/wait.gif' width='32' height='32' alt=''></td>\n"); 544 result.append("<td valign='middle'>"); 545 return result.toString(); 546 } 547 548 /** 549 * Returns the full Workplace resource path to the selected resource.<p> 550 * 551 * @param resourceName the name of the resource to get the resource path for 552 * 553 * @return the full Workplace resource path to the selected resource 554 */ 555 public static String getResourceUri(String resourceName) { 556 557 StringBuffer result = new StringBuffer(256); 558 result.append(getSkinUri()); 559 result.append(resourceName); 560 return result.toString(); 561 } 562 563 /** 564 * Returns the path to the skin resources.<p> 565 * 566 * @return the path to the skin resources 567 */ 568 public static String getSkinUri() { 569 570 if (m_skinUri == null) { 571 m_skinUri = OpenCms.getSystemInfo().getContextPath() + RFS_PATH_RESOURCES; 572 } 573 return m_skinUri; 574 } 575 576 /** 577 * Returns the start site from the given user settings.<p> 578 * 579 * @param cms the cms context 580 * @param userSettings the user settings 581 * 582 * @return the start site root 583 */ 584 public static String getStartSiteRoot(CmsObject cms, CmsUserSettings userSettings) { 585 586 String startSiteRoot = userSettings.getStartSite(); 587 if (startSiteRoot.endsWith("/")) { 588 // remove trailing slash 589 startSiteRoot = startSiteRoot.substring(0, startSiteRoot.length() - 1); 590 } 591 if (CmsStringUtil.isNotEmpty(startSiteRoot) 592 && (OpenCms.getSiteManager().getSiteForSiteRoot(startSiteRoot) == null)) { 593 // this is not the root site and the site is not in the list 594 List<CmsSite> sites = OpenCms.getSiteManager().getAvailableSites( 595 cms, 596 false, 597 cms.getRequestContext().getCurrentUser().getOuFqn()); 598 if (sites.size() == 1) { 599 startSiteRoot = sites.get(0).getSiteRoot(); 600 } else if (sites.size() > 1) { 601 String siteRoot = null; 602 String defaultSite = OpenCms.getWorkplaceManager().getDefaultUserSettings().getStartSite(); 603 // check if the default start site is available to the user 604 for (CmsSite site : sites) { 605 if (site.getSiteRoot().equals(defaultSite)) { 606 siteRoot = defaultSite; 607 break; 608 } 609 } 610 if (siteRoot == null) { 611 // list of available sites contains more than one site, but not the configured default, pick any 612 startSiteRoot = sites.get(0).getSiteRoot(); 613 } else { 614 startSiteRoot = siteRoot; 615 } 616 } 617 } 618 return startSiteRoot; 619 } 620 621 /** 622 * Returns the start site from the given workplace settings.<p> 623 * 624 * @param cms the cms context 625 * @param settings the workplace settings 626 * 627 * @return the start site root 628 */ 629 public static String getStartSiteRoot(CmsObject cms, CmsWorkplaceSettings settings) { 630 631 return getStartSiteRoot(cms, settings.getUserSettings()); 632 } 633 634 /** 635 * Returns the URI to static resources served from the class path.<p> 636 * 637 * @param resourceName the resource name 638 * 639 * @return the URI 640 */ 641 public static String getStaticResourceUri(String resourceName) { 642 643 return getStaticResourceUri(resourceName, null); 644 } 645 646 /** 647 * Returns the URI to static resources served from the class path.<p> 648 * 649 * @param resourceName the resource name 650 * @param versionInfo add an additional version info parameter to avoid browser caching issues 651 * 652 * @return the URI 653 */ 654 public static String getStaticResourceUri(String resourceName, String versionInfo) { 655 656 resourceName = CmsStaticResourceHandler.removeStaticResourcePrefix(resourceName); 657 String uri = CmsStringUtil.joinPaths(OpenCms.getSystemInfo().getStaticResourceContext(), resourceName); 658 if (versionInfo != null) { 659 uri += "?v=" + versionInfo; 660 } 661 return uri; 662 } 663 664 /** 665 * Returns the path to the cascading stylesheets.<p> 666 * 667 * @param jsp the JSP context 668 * @return the path to the cascading stylesheets 669 */ 670 public static String getStyleUri(CmsJspActionElement jsp) { 671 672 if (m_styleUri == null) { 673 674 CmsProject project = jsp.getCmsObject().getRequestContext().getCurrentProject(); 675 try { 676 jsp.getCmsObject().getRequestContext().setCurrentProject( 677 jsp.getCmsObject().readProject(CmsProject.ONLINE_PROJECT_ID)); 678 m_styleUri = jsp.link("/system/workplace/commons/style/"); 679 } catch (CmsException e) { 680 LOG.error(e.getLocalizedMessage()); 681 } finally { 682 jsp.getCmsObject().getRequestContext().setCurrentProject(project); 683 } 684 } 685 return m_styleUri; 686 } 687 688 /** 689 * Returns the path to the cascading stylesheets.<p> 690 * 691 * @param jsp the JSP context 692 * @param filename the name of the stylesheet 693 * @return the path to the cascading stylesheets 694 */ 695 public static String getStyleUri(CmsJspActionElement jsp, String filename) { 696 697 if (m_styleUri == null) { 698 CmsProject project = jsp.getCmsObject().getRequestContext().getCurrentProject(); 699 try { 700 jsp.getCmsObject().getRequestContext().setCurrentProject( 701 jsp.getCmsObject().readProject(CmsProject.ONLINE_PROJECT_ID)); 702 m_styleUri = jsp.link("/system/workplace/commons/style/"); 703 } catch (CmsException e) { 704 if (LOG.isErrorEnabled()) { 705 LOG.error(e.getLocalizedMessage(), e); 706 } 707 } finally { 708 jsp.getCmsObject().getRequestContext().setCurrentProject(project); 709 } 710 } 711 return m_styleUri + filename; 712 } 713 714 /** 715 * Returns the temporary file name for the given resource name.<p> 716 * 717 * To create a temporary file name of a resource name, the prefix char <code>'~'</code> (tilde) 718 * is added to the file name after all parent folder names have been removed.<p> 719 * 720 * @param resourceName the resource name to return the temporary file name for 721 * 722 * @return the temporary file name for the given resource name 723 * 724 * @see CmsResource#isTemporaryFileName(String) 725 * @see #isTemporaryFile(CmsResource) 726 */ 727 public static String getTemporaryFileName(String resourceName) { 728 729 if (resourceName == null) { 730 return null; 731 } 732 StringBuffer result = new StringBuffer(resourceName.length() + 2); 733 result.append(CmsResource.getFolderPath(resourceName)); 734 result.append(CmsResource.TEMP_FILE_PREFIX); 735 result.append(CmsResource.getName(resourceName)); 736 return result.toString(); 737 } 738 739 /** 740 * Creates a link for the OpenCms workplace that will reload the whole workplace, switch to the explorer view, the 741 * site of the given explorerRootPath and show the folder given in the explorerRootPath. 742 * <p> 743 * 744 * @param jsp 745 * needed for link functionality. 746 * 747 * @param explorerRootPath 748 * a root relative folder link (has to end with '/'). 749 * 750 * @return a link for the OpenCms workplace that will reload the whole workplace, switch to the explorer view, the 751 * site of the given explorerRootPath and show the folder given in the explorerRootPath. 752 */ 753 public static String getWorkplaceExplorerLink(final CmsJspActionElement jsp, final String explorerRootPath) { 754 755 return getWorkplaceExplorerLink(jsp.getCmsObject(), explorerRootPath); 756 757 } 758 759 /** 760 * Creates a link for the OpenCms workplace that will reload the whole workplace, switch to the explorer view, the 761 * site of the given explorerRootPath and show the folder given in the explorerRootPath. 762 * <p> 763 * 764 * @param cms 765 * the cms object 766 * 767 * @param explorerRootPath 768 * a root relative folder link (has to end with '/'). 769 * 770 * @return a link for the OpenCms workplace that will reload the whole workplace, switch to the explorer view, the 771 * site of the given explorerRootPath and show the folder given in the explorerRootPath. 772 */ 773 public static String getWorkplaceExplorerLink(final CmsObject cms, final String explorerRootPath) { 774 775 // split the root site: 776 String targetSiteRoot = OpenCms.getSiteManager().getSiteRoot(explorerRootPath); 777 if (targetSiteRoot == null) { 778 if (OpenCms.getSiteManager().startsWithShared(explorerRootPath)) { 779 targetSiteRoot = OpenCms.getSiteManager().getSharedFolder(); 780 } else { 781 targetSiteRoot = ""; 782 } 783 } 784 String targetVfsFolder; 785 if (explorerRootPath.startsWith(targetSiteRoot)) { 786 targetVfsFolder = explorerRootPath.substring(targetSiteRoot.length()); 787 targetVfsFolder = CmsStringUtil.joinPaths("/", targetVfsFolder); 788 } else { 789 targetVfsFolder = "/"; 790 // happens in case of the shared site 791 } 792 793 StringBuilder link2Source = new StringBuilder(); 794 link2Source.append(JSP_WORKPLACE_URI); 795 link2Source.append("?"); 796 link2Source.append(CmsWorkplace.PARAM_WP_EXPLORER_RESOURCE); 797 link2Source.append("="); 798 link2Source.append(targetVfsFolder); 799 link2Source.append("&"); 800 link2Source.append(PARAM_WP_VIEW); 801 link2Source.append("="); 802 link2Source.append( 803 OpenCms.getLinkManager().substituteLinkForUnknownTarget( 804 cms, 805 "/system/workplace/views/explorer/explorer_fs.jsp")); 806 link2Source.append("&"); 807 link2Source.append(PARAM_WP_SITE); 808 link2Source.append("="); 809 link2Source.append(targetSiteRoot); 810 811 String result = link2Source.toString(); 812 result = OpenCms.getLinkManager().substituteLinkForUnknownTarget(cms, result); 813 return result; 814 } 815 816 /** 817 * Returns the workplace settings of the current user.<p> 818 * 819 * @param cms the cms context 820 * @param req the request 821 * 822 * @return the workplace settings or <code>null</code> if the user is not logged in 823 */ 824 public static CmsWorkplaceSettings getWorkplaceSettings(CmsObject cms, HttpServletRequest req) { 825 826 HttpSession session = req.getSession(false); 827 CmsWorkplaceSettings workplaceSettings = null; 828 if (session != null) { 829 // all logged in user will have a session 830 workplaceSettings = (CmsWorkplaceSettings)session.getAttribute( 831 CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS); 832 // ensure workplace settings attribute is set 833 if (workplaceSettings == null) { 834 // creating any instance of {@link org.opencms.workplace.CmsWorkplaceSettings} and store it 835 workplaceSettings = initWorkplaceSettings(cms, null, false); 836 storeSettings(session, workplaceSettings); 837 } 838 } 839 return workplaceSettings; 840 } 841 842 /** 843 * Updates the user settings in the given workplace settings for the current user, reading the user settings 844 * from the database if required.<p> 845 * 846 * @param cms the cms object for the current user 847 * @param settings the workplace settings to update (if <code>null</code> a new instance is created) 848 * @param update flag indicating if settings are only updated (user preferences) 849 * 850 * @return the current users workplace settings 851 * 852 * @see #initWorkplaceSettings(CmsObject, CmsWorkplaceSettings, boolean) 853 */ 854 public static CmsWorkplaceSettings initUserSettings(CmsObject cms, CmsWorkplaceSettings settings, boolean update) { 855 856 if (settings == null) { 857 settings = new CmsWorkplaceSettings(); 858 } 859 860 // save current workplace user & user settings object 861 CmsUser user; 862 if (update) { 863 try { 864 // read the user from db to get the latest user information if required 865 user = cms.readUser(cms.getRequestContext().getCurrentUser().getId()); 866 } catch (CmsException e) { 867 // can usually be ignored 868 if (LOG.isInfoEnabled()) { 869 LOG.info(e.getLocalizedMessage()); 870 } 871 user = cms.getRequestContext().getCurrentUser(); 872 } 873 } else { 874 user = cms.getRequestContext().getCurrentUser(); 875 } 876 // store the user and it's settings in the Workplace settings 877 settings.setUser(user); 878 settings.setUserSettings(new CmsUserSettings(user)); 879 880 // return the result settings 881 return settings; 882 } 883 884 /** 885 * Updates the given workplace settings, also re-initializing 886 * the state of the Workplace to the users preferences (for example setting the startup site and project). 887 * 888 * The user settings will also be updated by calling <code>{@link #initUserSettings(CmsObject, CmsWorkplaceSettings, boolean)}</code> 889 * before updating the workplace project, selected site etc.<p> 890 * 891 * @param cms the cms object for the current user 892 * @param settings the workplace settings to update (if <code>null</code> a new instance is created) 893 * @param update flag indicating if settings are only updated (user preferences) 894 * 895 * @return the current users initialized workplace settings 896 * 897 * @see #initUserSettings(CmsObject, CmsWorkplaceSettings, boolean) 898 */ 899 public static synchronized CmsWorkplaceSettings initWorkplaceSettings( 900 CmsObject cms, 901 CmsWorkplaceSettings settings, 902 boolean update) { 903 904 // init the workplace user settings 905 settings = initUserSettings(cms, settings, update); 906 907 // save current project 908 settings.setProject(cms.getRequestContext().getCurrentProject().getUuid()); 909 String currentSite = cms.getRequestContext().getSiteRoot(); 910 // keep the current site 911 settings.setSite(currentSite); 912 913 // switch to users preferred site 914 String startSiteRoot = getStartSiteRoot(cms, settings); 915 916 try { 917 CmsObject cloneCms = OpenCms.initCmsObject(cms); 918 cloneCms.getRequestContext().setSiteRoot(startSiteRoot); 919 String projectName = settings.getUserSettings().getStartProject(); 920 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(projectName)) { 921 cloneCms.getRequestContext().setCurrentProject(cloneCms.readProject(projectName)); 922 } 923 // check start folder: 924 String startFolder = settings.getUserSettings().getStartFolder(); 925 if (!cloneCms.existsResource(startFolder, CmsResourceFilter.IGNORE_EXPIRATION)) { 926 // self - healing: 927 startFolder = "/"; 928 settings.getUserSettings().setStartFolder(startFolder); 929 } 930 settings.setSite(startSiteRoot); 931 settings.setExplorerResource(startFolder, cloneCms); 932 } catch (Exception e) { 933 settings.getUserSettings().setStartFolder("/"); 934 settings.setSite(startSiteRoot); 935 settings.setExplorerResource("/", null); 936 } finally { 937 settings.setSite(currentSite); 938 } 939 // get the default view from the user settings 940 settings.setViewUri(OpenCms.getLinkManager().substituteLink(cms, settings.getUserSettings().getStartView())); 941 return settings; 942 } 943 944 /** 945 * Returns <code>true</code> if the given resource is a temporary file.<p> 946 * 947 * A resource is considered a temporary file it is a file where the 948 * {@link CmsResource#FLAG_TEMPFILE} flag has been set, or if the file name (without parent folders) 949 * starts with the prefix char <code>'~'</code> (tilde).<p> 950 * 951 * @param resource the resource name to check 952 * 953 * @return <code>true</code> if the given resource name is a temporary file 954 * 955 * @see #getTemporaryFileName(String) 956 * @see CmsResource#isTemporaryFileName(String) 957 */ 958 public static boolean isTemporaryFile(CmsResource resource) { 959 960 return (resource != null) 961 && ((resource.isFile() 962 && (((resource.getFlags() & CmsResource.FLAG_TEMPFILE) > 0) 963 || (CmsResource.isTemporaryFileName(resource.getName()))))); 964 } 965 966 /** 967 * Substitutes the site title.<p> 968 * 969 * @param title the raw site title 970 * @param locale the localel 971 * 972 * @return the locale specific site title 973 */ 974 public static String substituteSiteTitleStatic(String title, Locale locale) { 975 976 if (title.equals(CmsSiteManagerImpl.SHARED_FOLDER_TITLE)) { 977 return Messages.get().getBundle(locale).key(Messages.GUI_SHARED_TITLE_0); 978 } 979 return title; 980 981 } 982 983 /** 984 * Updates the user preferences after changes have been made.<p> 985 * 986 * @param cms the current cms context 987 * @param req the current http request 988 */ 989 public static void updateUserPreferences(CmsObject cms, HttpServletRequest req) { 990 991 HttpSession session = req.getSession(false); 992 if (session == null) { 993 return; 994 } 995 CmsWorkplaceSettings settings = (CmsWorkplaceSettings)session.getAttribute( 996 CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS); 997 if (settings == null) { 998 return; 999 } 1000 // keep old synchronize settings 1001 CmsSynchronizeSettings synchronizeSettings = settings.getUserSettings().getSynchronizeSettings(); 1002 settings = CmsWorkplace.initWorkplaceSettings(cms, settings, true); 1003 settings.getUserSettings().setSynchronizeSettings(synchronizeSettings); 1004 } 1005 1006 /** 1007 * Stores the settings in the given session.<p> 1008 * 1009 * @param session the session to store the settings in 1010 * @param settings the settings 1011 */ 1012 static void storeSettings(HttpSession session, CmsWorkplaceSettings settings) { 1013 1014 // save the workplace settings in the session 1015 session.setAttribute(CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS, settings); 1016 } 1017 1018 /** 1019 * Returns all parameters of the current workplace class 1020 * as hidden field tags that can be inserted in a form.<p> 1021 * 1022 * @return all parameters of the current workplace class 1023 * as hidden field tags that can be inserted in a html form 1024 */ 1025 public String allParamsAsHidden() { 1026 1027 StringBuffer result = new StringBuffer(512); 1028 Map<String, Object> params = allParamValues(); 1029 Iterator<Entry<String, Object>> i = params.entrySet().iterator(); 1030 while (i.hasNext()) { 1031 Entry<String, Object> entry = i.next(); 1032 result.append("<input type=\"hidden\" name=\""); 1033 result.append(entry.getKey()); 1034 result.append("\" value=\""); 1035 String encoded = CmsEncoder.encode(entry.getValue().toString(), getCms().getRequestContext().getEncoding()); 1036 result.append(encoded); 1037 result.append("\">\n"); 1038 } 1039 return result.toString(); 1040 } 1041 1042 /** 1043 * Returns all present request parameters as String.<p> 1044 * 1045 * The String is formatted as a parameter String (<code>param1=val1&param2=val2</code>) with UTF-8 encoded values.<p> 1046 * 1047 * @return all present request parameters as String 1048 */ 1049 public String allParamsAsRequest() { 1050 1051 StringBuffer retValue = new StringBuffer(512); 1052 HttpServletRequest request = getJsp().getRequest(); 1053 Iterator<String> paramNames = request.getParameterMap().keySet().iterator(); 1054 while (paramNames.hasNext()) { 1055 String paramName = paramNames.next(); 1056 String paramValue = request.getParameter(paramName); 1057 retValue.append( 1058 paramName + "=" + CmsEncoder.encode(paramValue, getCms().getRequestContext().getEncoding())); 1059 if (paramNames.hasNext()) { 1060 retValue.append("&"); 1061 } 1062 } 1063 return retValue.toString(); 1064 } 1065 1066 /** 1067 * Builds the end html of the body.<p> 1068 * 1069 * @return the end html of the body 1070 */ 1071 public String bodyEnd() { 1072 1073 return pageBody(HTML_END, null, null); 1074 } 1075 1076 /** 1077 * Builds the start html of the body.<p> 1078 * 1079 * @param className optional class attribute to add to the body tag 1080 * @return the start html of the body 1081 */ 1082 public String bodyStart(String className) { 1083 1084 return pageBody(HTML_START, className, null); 1085 } 1086 1087 /** 1088 * Builds the start html of the body.<p> 1089 * 1090 * @param className optional class attribute to add to the body tag 1091 * @param parameters optional parameters to add to the body tag 1092 * @return the start html of the body 1093 */ 1094 public String bodyStart(String className, String parameters) { 1095 1096 return pageBody(HTML_START, className, parameters); 1097 } 1098 1099 /** 1100 * Generates a html select box out of the provided values.<p> 1101 * 1102 * @param parameters a string that will be inserted into the initial select tag, 1103 * if null no parameters will be inserted 1104 * @param options the options 1105 * @param values the option values, if null the select will have no value attributes 1106 * @param selected the index of the pre-selected option, if -1 no option is pre-selected 1107 * @return a formatted html String representing a html select box 1108 */ 1109 public String buildSelect(String parameters, List<String> options, List<String> values, int selected) { 1110 1111 return buildSelect(parameters, options, values, selected, true); 1112 } 1113 1114 /** 1115 * Generates a button for the OpenCms workplace.<p> 1116 * 1117 * @param href the href link for the button, if none is given the button will be disabled 1118 * @param target the href link target for the button, if none is given the target will be same window 1119 * @param image the image name for the button, skin path will be automattically added as prefix 1120 * @param label the label for the text of the button 1121 * @param type 0: image only (default), 1: image and text, 2: text only 1122 * 1123 * @return a button for the OpenCms workplace 1124 */ 1125 public String button(String href, String target, String image, String label, int type) { 1126 1127 return button(href, target, image, label, type, getSkinUri() + "buttons/"); 1128 } 1129 1130 /** 1131 * Generates a button for the OpenCms workplace.<p> 1132 * 1133 * @param href the href link for the button, if none is given the button will be disabled 1134 * @param target the href link target for the button, if none is given the target will be same window 1135 * @param image the image name for the button, skin path will be automattically added as prefix 1136 * @param label the label for the text of the button 1137 * @param type 0: image only (default), 1: image and text, 2: text only 1138 * @param imagePath the path to the image 1139 * 1140 * @return a button for the OpenCms workplace 1141 */ 1142 public String button(String href, String target, String image, String label, int type, String imagePath) { 1143 1144 StringBuffer result = new StringBuffer(256); 1145 1146 String anchorStart = "<a href=\""; 1147 if ((href != null) && href.toLowerCase().startsWith("javascript:")) { 1148 anchorStart = "<a href=\"#\" onclick=\""; 1149 } 1150 1151 result.append("<td style=\"vertical-align: top;\">"); 1152 switch (type) { 1153 case 1: 1154 // image and text 1155 if (href != null) { 1156 result.append(anchorStart); 1157 result.append(href); 1158 result.append("\" class=\"button\""); 1159 if (target != null) { 1160 result.append(" target=\""); 1161 result.append(target); 1162 result.append("\""); 1163 } 1164 result.append(">"); 1165 } 1166 result.append("<span unselectable=\"on\" "); 1167 if (href != null) { 1168 result.append( 1169 "class=\"norm\" onmouseover=\"className='over'\" onmouseout=\"className='norm'\" onmousedown=\"className='push'\" onmouseup=\"className='over'\""); 1170 } else { 1171 result.append("class=\"disabled\""); 1172 } 1173 result.append("><span unselectable=\"on\" class=\"combobutton\" "); 1174 result.append("style=\"background-image: url('"); 1175 result.append(imagePath); 1176 result.append(image); 1177 if ((image != null) && (image.indexOf('.') == -1)) { 1178 // append default suffix for button images 1179 result.append(".png"); 1180 } 1181 result.append("');\">"); 1182 result.append(shortKey(label)); 1183 result.append("</span></span>"); 1184 if (href != null) { 1185 result.append("</a>"); 1186 } 1187 break; 1188 1189 case 2: 1190 // text only 1191 if (href != null) { 1192 result.append(anchorStart); 1193 result.append(href); 1194 result.append("\" class=\"button\""); 1195 if (target != null) { 1196 result.append(" target=\""); 1197 result.append(target); 1198 result.append("\""); 1199 } 1200 result.append(">"); 1201 } 1202 result.append("<span unselectable=\"on\" "); 1203 if (href != null) { 1204 result.append( 1205 "class=\"norm\" onmouseover=\"className='over'\" onmouseout=\"className='norm'\" onmousedown=\"className='push'\" onmouseup=\"className='over'\""); 1206 } else { 1207 result.append("class=\"disabled\""); 1208 } 1209 result.append("><span unselectable=\"on\" class=\"txtbutton\">"); 1210 result.append(shortKey(label)); 1211 result.append("</span></span>"); 1212 if (href != null) { 1213 result.append("</a>"); 1214 } 1215 break; 1216 1217 default: 1218 // only image 1219 if (href != null) { 1220 result.append(anchorStart); 1221 result.append(href); 1222 result.append("\" class=\"button\""); 1223 if (target != null) { 1224 result.append(" target=\""); 1225 result.append(target); 1226 result.append("\""); 1227 } 1228 result.append(" title=\""); 1229 result.append(key(label)); 1230 result.append("\">"); 1231 } 1232 result.append("<span unselectable=\"on\" "); 1233 if (href != null) { 1234 result.append( 1235 "class=\"norm\" onmouseover=\"className='over'\" onmouseout=\"className='norm'\" onmousedown=\"className='push'\" onmouseup=\"className='over'\""); 1236 } else { 1237 result.append("class=\"disabled\""); 1238 } 1239 result.append("><img class=\"button\" src=\""); 1240 result.append(imagePath); 1241 result.append(image); 1242 if ((image != null) && (image.indexOf('.') == -1)) { 1243 // append default suffix for button images 1244 result.append(".png"); 1245 } 1246 result.append("\" alt=\""); 1247 result.append(key(label)); 1248 result.append("\">"); 1249 result.append("</span>"); 1250 if (href != null) { 1251 result.append("</a>"); 1252 } 1253 break; 1254 } 1255 result.append("</td>\n"); 1256 return result.toString(); 1257 } 1258 1259 /** 1260 * Returns the html for a button bar.<p> 1261 * 1262 * @param segment the HTML segment (START / END) 1263 * 1264 * @return a button bar html start / end segment 1265 */ 1266 public String buttonBar(int segment) { 1267 1268 return buttonBar(segment, null); 1269 } 1270 1271 /** 1272 * Returns the html for a button bar.<p> 1273 * 1274 * @param segment the HTML segment (START / END) 1275 * @param attributes optional attributes for the table tag 1276 * 1277 * @return a button bar html start / end segment 1278 */ 1279 public String buttonBar(int segment, String attributes) { 1280 1281 if (segment == HTML_START) { 1282 String result = "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\""; 1283 if (attributes != null) { 1284 result += " " + attributes; 1285 } 1286 return result + "><tr>\n"; 1287 } else { 1288 return "</tr></table>"; 1289 } 1290 } 1291 1292 /** 1293 * Generates a horizontal button bar separator line with maximum width.<p> 1294 * 1295 * @return a horizontal button bar separator line 1296 */ 1297 public String buttonBarHorizontalLine() { 1298 1299 StringBuffer result = new StringBuffer(256); 1300 result.append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"maxwidth\">\n"); 1301 result.append("<tr>\n"); 1302 result.append("\t<td class=\"horseparator\" ><img src=\""); 1303 result.append(getSkinUri()); 1304 result.append("tree/empty.gif\" border=\"0\" width=\"1\" height=\"1\" alt=\"\"></td>\n"); 1305 result.append("</tr>\n"); 1306 result.append("</table>\n"); 1307 return result.toString(); 1308 } 1309 1310 /** 1311 * Generates a button bar label.<p> 1312 * 1313 * @param label the label to show 1314 * 1315 * @return a button bar label 1316 */ 1317 public String buttonBarLabel(String label) { 1318 1319 return buttonBarLabel(label, "norm"); 1320 } 1321 1322 /** 1323 * Generates a button bar label.<p> 1324 * 1325 * @param label the label to show 1326 * @param className the css class name for the formatting 1327 * 1328 * @return a button bar label 1329 */ 1330 public String buttonBarLabel(String label, String className) { 1331 1332 StringBuffer result = new StringBuffer(128); 1333 result.append("<td><span class=\""); 1334 result.append(className); 1335 result.append("\"><span unselectable=\"on\" class=\"txtbutton\">"); 1336 result.append(key(label)); 1337 result.append("</span></span></td>\n"); 1338 return result.toString(); 1339 } 1340 1341 /** 1342 * Generates a variable button bar separator line.<p> 1343 * 1344 * @param leftPixel the amount of pixel left to the line 1345 * @param rightPixel the amount of pixel right to the line 1346 * @param className the css class name for the formatting 1347 * 1348 * @return a variable button bar separator line 1349 */ 1350 public String buttonBarLine(int leftPixel, int rightPixel, String className) { 1351 1352 StringBuffer result = new StringBuffer(512); 1353 if (leftPixel > 0) { 1354 result.append(buttonBarLineSpacer(leftPixel)); 1355 } 1356 result.append("<td><span class=\""); 1357 result.append(className); 1358 result.append("\"></span></td>\n"); 1359 if (rightPixel > 0) { 1360 result.append(buttonBarLineSpacer(rightPixel)); 1361 } 1362 return result.toString(); 1363 } 1364 1365 /** 1366 * Generates a variable button bar separator line spacer.<p> 1367 * 1368 * @param pixel the amount of pixel space 1369 * 1370 * @return a variable button bar separator line spacer 1371 */ 1372 public String buttonBarLineSpacer(int pixel) { 1373 1374 StringBuffer result = new StringBuffer(128); 1375 result.append( 1376 "<td><span class=\"norm\"><span unselectable=\"on\" class=\"txtbutton\" style=\"padding-right: 0px; padding-left: "); 1377 result.append(pixel); 1378 result.append("px;\"></span></span></td>\n"); 1379 return result.toString(); 1380 } 1381 1382 /** 1383 * Generates a button bar separator.<p> 1384 * 1385 * @param leftPixel the amount of pixel left to the separator 1386 * @param rightPixel the amount of pixel right to the separator 1387 * 1388 * @return a button bar separator 1389 */ 1390 public String buttonBarSeparator(int leftPixel, int rightPixel) { 1391 1392 return buttonBarLine(leftPixel, rightPixel, "separator"); 1393 } 1394 1395 /** 1396 * Returns the html for an invisible spacer between button bar contents like buttons, labels, etc.<p> 1397 * 1398 * @param width the width of the invisible spacer 1399 * @return the html for the invisible spacer 1400 */ 1401 public String buttonBarSpacer(int width) { 1402 1403 StringBuffer result = new StringBuffer(128); 1404 result.append("<td><span class=\"norm\"><span unselectable=\"on\" class=\"txtbutton\" style=\"width: "); 1405 result.append(width); 1406 result.append("px;\"></span></span></td>\n"); 1407 return result.toString(); 1408 } 1409 1410 /** 1411 * Generates a button bar starter tab.<p> 1412 * 1413 * @param leftPixel the amount of pixel left to the starter 1414 * @param rightPixel the amount of pixel right to the starter 1415 * 1416 * @return a button bar starter tab 1417 */ 1418 public String buttonBarStartTab(int leftPixel, int rightPixel) { 1419 1420 StringBuffer result = new StringBuffer(512); 1421 result.append(buttonBarLineSpacer(leftPixel)); 1422 result.append("<td><span class=\"starttab\"><span style=\"width:1px; height:1px\"></span></span></td>\n"); 1423 result.append(buttonBarLineSpacer(rightPixel)); 1424 return result.toString(); 1425 } 1426 1427 /** 1428 * Checks the lock state of the resource and locks it if the autolock feature is enabled.<p> 1429 * 1430 * @param resource the resource name which is checked 1431 * @throws CmsException if reading or locking the resource fails 1432 */ 1433 public void checkLock(String resource) throws CmsException { 1434 1435 checkLock(resource, CmsLockType.EXCLUSIVE); 1436 } 1437 1438 /** 1439 * Checks the lock state of the resource and locks it if the autolock feature is enabled.<p> 1440 * 1441 * @param resource the resource name which is checked 1442 * @param type indicates the mode {@link CmsLockType#EXCLUSIVE} or {@link CmsLockType#TEMPORARY} 1443 * 1444 * @throws CmsException if reading or locking the resource fails 1445 */ 1446 public void checkLock(String resource, CmsLockType type) throws CmsException { 1447 1448 CmsResource res = getCms().readResource(resource, CmsResourceFilter.ALL); 1449 CmsLock lock = getCms().getLock(res); 1450 boolean lockable = lock.isLockableBy(getCms().getRequestContext().getCurrentUser()); 1451 1452 if (OpenCms.getWorkplaceManager().autoLockResources()) { 1453 // autolock is enabled, check the lock state of the resource 1454 if (lockable) { 1455 // resource is lockable, so lock it automatically 1456 if (type == CmsLockType.TEMPORARY) { 1457 getCms().lockResourceTemporary(resource); 1458 } else { 1459 getCms().lockResource(resource); 1460 } 1461 } else { 1462 throw new CmsException(Messages.get().container(Messages.ERR_WORKPLACE_LOCK_RESOURCE_1, resource)); 1463 } 1464 } else { 1465 if (!lockable) { 1466 throw new CmsException(Messages.get().container(Messages.ERR_WORKPLACE_LOCK_RESOURCE_1, resource)); 1467 } 1468 } 1469 } 1470 1471 /** 1472 * First sets site and project in the workplace settings, then fills all class parameter values from the data 1473 * provided in the current request.<p> 1474 * 1475 * @param settings the workplace settings 1476 * @param request the current request 1477 */ 1478 public void fillParamValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 1479 1480 initSettings(settings, request); 1481 fillParamValues(request); 1482 } 1483 1484 /** 1485 * Fills all class parameter values from the data provided in the current request.<p> 1486 * 1487 * All methods that start with "setParam" are possible candidates to be 1488 * automatically filled. The remaining part of the method name is converted 1489 * to lower case. Then a parameter of this name is searched in the request parameters. 1490 * If the parameter is found, the "setParam" method is automatically invoked 1491 * by reflection with the value of the parameter.<p> 1492 * 1493 * @param request the current JSP request 1494 */ 1495 public void fillParamValues(HttpServletRequest request) { 1496 1497 m_parameterMap = null; 1498 // ensure a multipart request is parsed only once (for "forward" scenarios with reports) 1499 if (null == request.getAttribute(REQUEST_ATTRIBUTE_MULTIPART)) { 1500 // check if this is a multipart request 1501 m_multiPartFileItems = CmsRequestUtil.readMultipartFileItems(request); 1502 if (m_multiPartFileItems != null) { 1503 // this was indeed a multipart form request 1504 m_parameterMap = CmsRequestUtil.readParameterMapFromMultiPart( 1505 getCms().getRequestContext().getEncoding(), 1506 m_multiPartFileItems); 1507 request.setAttribute(REQUEST_ATTRIBUTE_MULTIPART, Boolean.TRUE); 1508 } 1509 } 1510 if (m_parameterMap == null) { 1511 // the request was a "normal" request 1512 m_parameterMap = request.getParameterMap(); 1513 } 1514 1515 List<Method> methods = paramSetMethods(); 1516 Iterator<Method> i = methods.iterator(); 1517 while (i.hasNext()) { 1518 Method m = i.next(); 1519 String name = m.getName().substring(8).toLowerCase(); 1520 String[] values = m_parameterMap.get(name); 1521 String value = null; 1522 if (values != null) { 1523 // get the parameter value from the map 1524 value = values[0]; 1525 } 1526 if (CmsStringUtil.isEmpty(value)) { 1527 value = null; 1528 } 1529 1530 // TODO: this is very dangerous since most of the dialogs does not send encoded data 1531 // and by decoding not encoded data the data will get corrupted, for instance '1+2' will become '1 2'. 1532 // we should ensure that we decode the data only if the data has been encoded 1533 value = decodeParamValue(name, value); 1534 try { 1535 if (LOG.isDebugEnabled() && (value != null)) { 1536 LOG.debug(Messages.get().getBundle().key(Messages.LOG_SET_PARAM_2, m.getName(), value)); 1537 } 1538 m.invoke(this, new Object[] {value}); 1539 } catch (InvocationTargetException ite) { 1540 // can usually be ignored 1541 if (LOG.isInfoEnabled()) { 1542 LOG.info(ite.getLocalizedMessage()); 1543 } 1544 } catch (IllegalAccessException eae) { 1545 // can usually be ignored 1546 if (LOG.isInfoEnabled()) { 1547 LOG.info(eae.getLocalizedMessage()); 1548 } 1549 } 1550 } 1551 } 1552 1553 /** 1554 * Returns the message String for the broadcast message alert of the workplace.<p> 1555 * 1556 * Caution: returns the pure message String (not escaped) or null, if no message is pending.<p> 1557 * 1558 * @return the message String for the broadcast message alert of the workplace 1559 */ 1560 public String getBroadcastMessageString() { 1561 1562 CmsSessionInfo sessionInfo = OpenCms.getSessionManager().getSessionInfo(getSession()); 1563 if (sessionInfo == null) { 1564 return null; 1565 } 1566 String sessionId = sessionInfo.getSessionId().toString(); 1567 Buffer messageQueue = OpenCms.getSessionManager().getBroadcastQueue(sessionId); 1568 if (!messageQueue.isEmpty()) { 1569 // create message String 1570 StringBuffer result = new StringBuffer(512); 1571 // the user has pending messages, display them all 1572 while (!messageQueue.isEmpty()) { 1573 CmsBroadcast message = (CmsBroadcast)messageQueue.remove(); 1574 result.append('['); 1575 result.append(getMessages().getDateTime(message.getSendTime())); 1576 result.append("] "); 1577 result.append(key(Messages.GUI_LABEL_BROADCASTMESSAGEFROM_0)); 1578 result.append(' '); 1579 if (message.getUser() != null) { 1580 result.append(message.getUser().getName()); 1581 } else { 1582 // system message 1583 result.append(key(Messages.GUI_LABEL_BROADCAST_FROM_SYSTEM_0)); 1584 } 1585 result.append(":\n"); 1586 result.append(message.getMessage()); 1587 result.append("\n\n"); 1588 } 1589 return result.toString(); 1590 } 1591 // no message pending, return null 1592 return null; 1593 } 1594 1595 /** 1596 * Returns the initialized cms object for the current user.<p> 1597 * 1598 * @return the initialized cms object for the current user 1599 */ 1600 public CmsObject getCms() { 1601 1602 return m_cms; 1603 } 1604 1605 /** 1606 * Returns the current workplace encoding.<p> 1607 * 1608 * @return the current workplace encoding 1609 */ 1610 public String getEncoding() { 1611 1612 return OpenCms.getWorkplaceManager().getEncoding(); 1613 } 1614 1615 /** 1616 * Returns the uri (including context path) to the explorer file list.<p> 1617 * 1618 * @return the uri (including context path) to the explorer file list 1619 */ 1620 public String getExplorerFileListFullUri() { 1621 1622 if (m_file_explorer_filelist != null) { 1623 return m_file_explorer_filelist; 1624 } 1625 synchronized (this) { 1626 m_file_explorer_filelist = OpenCms.getLinkManager().substituteLink(getCms(), FILE_EXPLORER_FILELIST); 1627 } 1628 return m_file_explorer_filelist; 1629 } 1630 1631 /** 1632 * Returns the html for the frame name and source and stores this information in the workplace settings.<p> 1633 * 1634 * @param frameName the name of the frame 1635 * @param uri the absolute path of the frame 1636 * @return the html for the frame name and source 1637 */ 1638 public String getFrameSource(String frameName, String uri) { 1639 1640 String frameString = "name=\"" + frameName + "\" src=\"" + uri + "\""; 1641 int paramIndex = uri.indexOf("?"); 1642 if (paramIndex != -1) { 1643 // remove request parameters from URI before putting it to Map 1644 uri = uri.substring(0, uri.indexOf("?")); 1645 } 1646 getSettings().getFrameUris().put(frameName, uri); 1647 return frameString; 1648 } 1649 1650 /** 1651 * Returns the JSP action element.<p> 1652 * 1653 * @return the JSP action element 1654 */ 1655 public CmsJspActionElement getJsp() { 1656 1657 return m_jsp; 1658 } 1659 1660 /** 1661 * Returns the current users workplace locale settings.<p> 1662 * 1663 * @return the current users workplace locale setting 1664 */ 1665 public Locale getLocale() { 1666 1667 return getSettings().getUserSettings().getLocale(); 1668 } 1669 1670 /** 1671 * Returns the current used macro resolver instance.<p> 1672 * 1673 * @return the macro resolver 1674 */ 1675 public CmsMacroResolver getMacroResolver() { 1676 1677 if (m_macroResolver == null) { 1678 // create a new macro resolver "with everything we got" 1679 m_macroResolver = CmsMacroResolver.newInstance() 1680 // initialize resolver with the objects available 1681 .setCmsObject(m_cms).setMessages(getMessages()).setJspPageContext( 1682 (m_jsp == null) ? null : m_jsp.getJspContext()); 1683 m_macroResolver.setParameterMap(m_parameterMap); 1684 } 1685 return m_macroResolver; 1686 } 1687 1688 /** 1689 * Returns the current used message object.<p> 1690 * 1691 * @return the current used message object 1692 */ 1693 public CmsMessages getMessages() { 1694 1695 return m_messages; 1696 } 1697 1698 /** 1699 * Returns a list of FileItem instances parsed from the request, in the order that they were transmitted.<p> 1700 * 1701 * This list is automatically initialized from the createParameterMapFromMultiPart(HttpServletRequest) method.<p> 1702 * 1703 * @return list of FileItem instances parsed from the request, in the order that they were transmitted 1704 */ 1705 public List<FileItem> getMultiPartFileItems() { 1706 1707 return m_multiPartFileItems; 1708 } 1709 1710 /** 1711 * Returns the path to the workplace static resources.<p> 1712 * 1713 * Workplaces static resources are images, css files etc. 1714 * These are exported during the installation of OpenCms, 1715 * and are usually only read from this exported location to 1716 * avoid the overhaead of accessing the database later.<p> 1717 * 1718 * @return the path to the workplace static resources 1719 */ 1720 public String getResourceUri() { 1721 1722 if (m_resourceUri == null) { 1723 m_resourceUri = OpenCms.getSystemInfo().getContextPath() + CmsWorkplace.RFS_PATH_RESOURCES; 1724 } 1725 return m_resourceUri; 1726 } 1727 1728 /** 1729 * Returns the current user http session.<p> 1730 * 1731 * @return the current user http session 1732 */ 1733 public HttpSession getSession() { 1734 1735 return m_session; 1736 } 1737 1738 /** 1739 * Returns the current users workplace settings.<p> 1740 * 1741 * @return the current users workplace settings 1742 */ 1743 public CmsWorkplaceSettings getSettings() { 1744 1745 return m_settings; 1746 } 1747 1748 /** 1749 * Returns the path to the cascading stylesheets.<p> 1750 * 1751 * @param filename the name of the stylesheet 1752 * @return the path to the cascading stylesheets 1753 */ 1754 public String getStyleUri(String filename) { 1755 1756 return getStyleUri(getJsp(), filename); 1757 } 1758 1759 /** 1760 * Builds the end html of the page.<p> 1761 * 1762 * @return the end html of the page 1763 */ 1764 public String htmlEnd() { 1765 1766 return pageHtml(HTML_END, null); 1767 } 1768 1769 /** 1770 * Builds the start html of the page, including setting of DOCTYPE and 1771 * inserting a header with the content-type.<p> 1772 * 1773 * @param title the content for the title tag 1774 * @return the start html of the page 1775 */ 1776 public String htmlStart(String title) { 1777 1778 return pageHtml(HTML_START, title); 1779 } 1780 1781 /** 1782 * Sets site and project in the workplace settings with the request values of parameters 1783 * <code>{@link CmsWorkplace#PARAM_WP_SITE}</code> and <code>{@link CmsWorkplace#PARAM_WP_PROJECT}</code>.<p> 1784 * 1785 * @param settings the workplace settings 1786 * @param request the current request 1787 * 1788 * @return true, if a reload of the main body frame is required 1789 */ 1790 public boolean initSettings(CmsWorkplaceSettings settings, HttpServletRequest request) { 1791 1792 // check if the user requested a project change 1793 String project = request.getParameter(PARAM_WP_PROJECT); 1794 boolean reloadRequired = false; 1795 if (project != null) { 1796 reloadRequired = true; 1797 try { 1798 getCms().readProject(new CmsUUID(project)); 1799 } catch (Exception e) { 1800 // project not found, set online project 1801 project = String.valueOf(CmsProject.ONLINE_PROJECT_ID); 1802 } 1803 try { 1804 m_cms.getRequestContext().setCurrentProject(getCms().readProject(new CmsUUID(project))); 1805 } catch (Exception e) { 1806 if (LOG.isInfoEnabled()) { 1807 LOG.info(e.getLocalizedMessage(), e); 1808 } 1809 } 1810 settings.setProject(new CmsUUID(project)); 1811 } 1812 1813 // check if the user requested a site change 1814 String site = request.getParameter(PARAM_WP_SITE); 1815 if (site != null) { 1816 reloadRequired = true; 1817 m_cms.getRequestContext().setSiteRoot(site); 1818 settings.setSite(site); 1819 } 1820 1821 // check which resource was requested 1822 String explorerResource = request.getParameter(PARAM_WP_EXPLORER_RESOURCE); 1823 if (explorerResource != null) { 1824 reloadRequired = true; 1825 settings.setExplorerResource(explorerResource, getCms()); 1826 } 1827 1828 return reloadRequired; 1829 } 1830 1831 /** 1832 * Returns the forwarded flag.<p> 1833 * 1834 * @return the forwarded flag 1835 */ 1836 public boolean isForwarded() { 1837 1838 return m_forwarded; 1839 } 1840 1841 /** 1842 * Returns true if the online help for the users current workplace language is installed.<p> 1843 * 1844 * @return true if the online help for the users current workplace language is installed 1845 */ 1846 public boolean isHelpEnabled() { 1847 1848 return false; 1849 } 1850 1851 /** 1852 * Returns true if the currently processed element is an included sub element.<p> 1853 * 1854 * @return true if the currently processed element is an included sub element 1855 */ 1856 public boolean isSubElement() { 1857 1858 return !getJsp().getRequestContext().getUri().equals(getJsp().info("opencms.request.element.uri")); 1859 } 1860 1861 /** 1862 * Returns the localized resource string for a given message key, 1863 * checking the workplace default resources and all module bundles.<p> 1864 * 1865 * If the key was not found, the return value is 1866 * <code>"??? " + keyName + " ???"</code>.<p> 1867 * 1868 * If the key starts with <code>"help."</code> and is not found, 1869 * the value <code>"index.html"</code> is returned.<p> 1870 * 1871 * @param keyName the key for the desired string 1872 * @return the resource string for the given key 1873 * 1874 * @see CmsMessages#key(String) 1875 */ 1876 public String key(String keyName) { 1877 1878 return getMessages().key(keyName); 1879 } 1880 1881 /** 1882 * Returns the localized resource string for a given message key, 1883 * with the provided replacement parameters.<p> 1884 * 1885 * If the key was found in the bundle, it will be formatted using 1886 * a <code>{@link java.text.MessageFormat}</code> using the provided parameters.<p> 1887 * 1888 * If the key was not found in the bundle, the return value is 1889 * <code>"??? " + keyName + " ???"</code>. This will also be returned 1890 * if the bundle was not properly initialized first. 1891 * 1892 * @param keyName the key for the desired string 1893 * @param params the parameters to use for formatting 1894 * @return the resource string for the given key 1895 * 1896 * @see CmsMessages#key(String) 1897 */ 1898 public String key(String keyName, Object[] params) { 1899 1900 return getMessages().key(keyName, params); 1901 } 1902 1903 /** 1904 * Returns the localized resource string for the given message key, 1905 * checking the workplace default resources and all module bundles.<p> 1906 * 1907 * If the key was not found, the provided default value 1908 * is returned.<p> 1909 * 1910 * @param keyName the key for the desired string 1911 * @param defaultValue the default value in case the key does not exist in the bundle 1912 * @return the resource string for the given key it it exists, or the given default if not 1913 * 1914 * @see CmsMessages#keyDefault(String, String) 1915 */ 1916 public String keyDefault(String keyName, String defaultValue) { 1917 1918 return getMessages().keyDefault(keyName, defaultValue); 1919 } 1920 1921 /** 1922 * Returns the empty String "" if the provided value is null, otherwise just returns 1923 * the provided value.<p> 1924 * 1925 * Use this method in forms if a getParamXXX method is used, but a String (not null) 1926 * is required. 1927 * 1928 * @param value the String to check 1929 * @return the empty String "" if the provided value is null, otherwise just returns 1930 * the provided value 1931 */ 1932 public String nullToEmpty(String value) { 1933 1934 if (value != null) { 1935 return value; 1936 } 1937 return ""; 1938 } 1939 1940 /** 1941 * Builds the html of the body.<p> 1942 * 1943 * @param segment the HTML segment (START / END) 1944 * @param className optional class attribute to add to the body tag 1945 * @param parameters optional parameters to add to the body tag 1946 * @return the html of the body 1947 */ 1948 public String pageBody(int segment, String className, String parameters) { 1949 1950 if (segment == HTML_START) { 1951 StringBuffer result = new StringBuffer(128); 1952 result.append("</head>\n<body unselectable=\"on\""); 1953 if (className != null) { 1954 result.append(" class=\""); 1955 result.append(className); 1956 result.append("\""); 1957 } 1958 if (CmsStringUtil.isNotEmpty(parameters)) { 1959 result.append(" "); 1960 result.append(parameters); 1961 } 1962 result.append(">\n"); 1963 return result.toString(); 1964 } else { 1965 return "</body>"; 1966 } 1967 } 1968 1969 /** 1970 * Returns the default html for a workplace page, including setting of DOCTYPE and 1971 * inserting a header with the content-type.<p> 1972 * 1973 * @param segment the HTML segment (START / END) 1974 * @param title the title of the page, if null no title tag is inserted 1975 * @return the default html for a workplace page 1976 */ 1977 public String pageHtml(int segment, String title) { 1978 1979 return pageHtmlStyle(segment, title, null); 1980 } 1981 1982 /** 1983 * Returns the default html for a workplace page, including setting of DOCTYPE and 1984 * inserting a header with the content-type, allowing the selection of an individual style sheet.<p> 1985 * 1986 * @param segment the HTML segment (START / END) 1987 * @param title the title of the page, if null no title tag is inserted 1988 * @param stylesheet the used style sheet, if null the default stylesheet 'workplace.css' is inserted 1989 * @return the default html for a workplace page 1990 */ 1991 public String pageHtmlStyle(int segment, String title, String stylesheet) { 1992 1993 if (segment == HTML_START) { 1994 StringBuffer result = new StringBuffer(512); 1995 result.append("<!DOCTYPE html>\n"); 1996 result.append("<html>\n<head>\n"); 1997 if (title != null) { 1998 result.append("<title>"); 1999 result.append(title); 2000 result.append("</title>\n"); 2001 } 2002 result.append("<meta HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset="); 2003 result.append(getEncoding()); 2004 result.append("\">\n"); 2005 result.append("<link rel=\"stylesheet\" type=\"text/css\" href=\""); 2006 2007 result.append(getStyleUri(getJsp(), stylesheet == null ? "workplace.css" : stylesheet)); 2008 result.append("\">\n"); 2009 return result.toString(); 2010 } else { 2011 return "</html>"; 2012 } 2013 } 2014 2015 /** 2016 * Returns all initialized parameters of the current workplace class 2017 * as hidden field tags that can be inserted in a form.<p> 2018 * 2019 * @return all initialized parameters of the current workplace class 2020 * as hidden field tags that can be inserted in a html form 2021 */ 2022 public String paramsAsHidden() { 2023 2024 return paramsAsHidden(null); 2025 } 2026 2027 /** 2028 * Returns all initialized parameters of the current workplace class 2029 * that are not in the given exclusion list as hidden field tags that can be inserted in a form.<p> 2030 * 2031 * @param excludes the parameters to exclude 2032 * 2033 * @return all initialized parameters of the current workplace class 2034 * that are not in the given exclusion list as hidden field tags that can be inserted in a form 2035 */ 2036 public String paramsAsHidden(Collection<String> excludes) { 2037 2038 StringBuffer result = new StringBuffer(512); 2039 Map<String, Object> params = paramValues(); 2040 Iterator<Entry<String, Object>> i = params.entrySet().iterator(); 2041 while (i.hasNext()) { 2042 Entry<String, Object> entry = i.next(); 2043 String param = entry.getKey(); 2044 if ((excludes == null) || (!excludes.contains(param))) { 2045 result.append("<input type=\"hidden\" name=\""); 2046 result.append(param); 2047 result.append("\" value=\""); 2048 String encoded = CmsEncoder.encode( 2049 entry.getValue().toString(), 2050 getCms().getRequestContext().getEncoding()); 2051 result.append(encoded); 2052 result.append("\">\n"); 2053 } 2054 } 2055 return result.toString(); 2056 } 2057 2058 /** 2059 * Returns all initialized parameters of the current workplace class in the 2060 * form of a parameter map, i.e. the values are arrays.<p> 2061 * 2062 * @return all initialized parameters of the current workplace class in the 2063 * form of a parameter map 2064 */ 2065 public Map<String, String[]> paramsAsParameterMap() { 2066 2067 return CmsRequestUtil.createParameterMap(paramValues()); 2068 } 2069 2070 /** 2071 * Returns all initialized parameters of the current workplace class 2072 * as request parameters, i.e. in the form <code>key1=value1&key2=value2</code> etc. 2073 * 2074 * @return all initialized parameters of the current workplace class 2075 * as request parameters 2076 */ 2077 public String paramsAsRequest() { 2078 2079 StringBuffer result = new StringBuffer(512); 2080 Map<String, Object> params = paramValues(); 2081 Iterator<Entry<String, Object>> i = params.entrySet().iterator(); 2082 while (i.hasNext()) { 2083 Entry<String, Object> entry = i.next(); 2084 result.append(entry.getKey()); 2085 result.append("="); 2086 result.append(CmsEncoder.encode(entry.getValue().toString(), getCms().getRequestContext().getEncoding())); 2087 if (i.hasNext()) { 2088 result.append("&"); 2089 } 2090 } 2091 return result.toString(); 2092 } 2093 2094 /** 2095 * Resolves the macros in the given String and replaces them by their localized keys.<p> 2096 * 2097 * The following macro contexts are available in the Workplace:<ul> 2098 * <li>Macros based on the current users OpenCms context (obtained from the current <code>{@link CmsObject}</code>).</li> 2099 * <li>Localized key macros (obtained from the current <code>{@link CmsMessages}</code>).</li> 2100 * <li>Macros from the current JSP page context (obtained by <code>{@link #getJsp()}</code>).</li> 2101 * </ul> 2102 * 2103 * @param input the input String containing the macros 2104 * @return the resolved String 2105 * 2106 * @see CmsMacroResolver#resolveMacros(String) 2107 */ 2108 public String resolveMacros(String input) { 2109 2110 // resolve the macros 2111 return getMacroResolver().resolveMacros(input); 2112 } 2113 2114 /** 2115 * Sends a http redirect to the specified URI in the OpenCms VFS.<p> 2116 * 2117 * @param location the location the response is redirected to 2118 * @throws IOException in case redirection fails 2119 */ 2120 public void sendCmsRedirect(String location) throws IOException { 2121 2122 // TOOD: IBM Websphere v5 has problems here, use forward instead (which has other problems) 2123 getJsp().getResponse().sendRedirect(OpenCms.getSystemInfo().getOpenCmsContext() + location); 2124 } 2125 2126 /** 2127 * Forwards to the specified location in the OpenCms VFS.<p> 2128 * 2129 * @param location the location the response is redirected to 2130 * @param params the map of parameters to use for the forwarded request 2131 * 2132 * @throws IOException in case the forward fails 2133 * @throws ServletException in case the forward fails 2134 */ 2135 public void sendForward(String location, Map<String, String[]> params) throws IOException, ServletException { 2136 2137 setForwarded(true); 2138 // params must be arrays of String, ensure this is the case 2139 Map<String, String[]> parameters = CmsRequestUtil.createParameterMap(params); 2140 CmsRequestUtil.forwardRequest( 2141 getJsp().link(location), 2142 parameters, 2143 getJsp().getRequest(), 2144 getJsp().getResponse()); 2145 } 2146 2147 /** 2148 * Sets the forwarded flag.<p> 2149 * 2150 * @param forwarded the forwarded flag to set 2151 */ 2152 public void setForwarded(boolean forwarded) { 2153 2154 m_forwarded = forwarded; 2155 } 2156 2157 /** 2158 * Get a localized short key value for the workplace.<p> 2159 * 2160 * @param keyName name of the key 2161 * @return a localized short key value 2162 */ 2163 public String shortKey(String keyName) { 2164 2165 String value = keyDefault(keyName + CmsMessages.KEY_SHORT_SUFFIX, (String)null); 2166 if (value == null) { 2167 // short key value not found, return "long" key value 2168 return key(keyName); 2169 } 2170 return value; 2171 } 2172 2173 /** 2174 * Auxiliary method for initialization of messages.<p> 2175 * 2176 * @param messages the {@link CmsMessages} to add 2177 */ 2178 protected void addMessages(CmsMessages messages) { 2179 2180 if (messages != null) { 2181 m_messages.addMessages(messages); 2182 } 2183 } 2184 2185 /** 2186 * Auxiliary method for initialization of messages.<p> 2187 * 2188 * @param bundleName the resource bundle name to add 2189 */ 2190 protected void addMessages(String bundleName) { 2191 2192 addMessages(new CmsMessages(bundleName, getLocale())); 2193 } 2194 2195 /** 2196 * Returns the values of all parameter methods of this workplace class instance.<p> 2197 * 2198 * @return the values of all parameter methods of this workplace class instance 2199 */ 2200 protected Map<String, Object> allParamValues() { 2201 2202 List<Method> methods = paramGetMethods(); 2203 Map<String, Object> map = new HashMap<String, Object>(methods.size()); 2204 Iterator<Method> i = methods.iterator(); 2205 while (i.hasNext()) { 2206 Method m = i.next(); 2207 Object o = null; 2208 try { 2209 o = m.invoke(this, new Object[0]); 2210 } catch (InvocationTargetException ite) { 2211 // can usually be ignored 2212 if (LOG.isInfoEnabled()) { 2213 LOG.info(ite); 2214 } 2215 } catch (IllegalAccessException eae) { 2216 // can usually be ignored 2217 if (LOG.isInfoEnabled()) { 2218 LOG.info(eae); 2219 } 2220 } 2221 if (o == null) { 2222 o = ""; 2223 } 2224 map.put(m.getName().substring(8).toLowerCase(), o); 2225 } 2226 return map; 2227 } 2228 2229 /** 2230 * Checks that the current user is a workplace user.<p> 2231 * 2232 * @throws CmsRoleViolationException if the user does not have the required role 2233 */ 2234 protected void checkRole() throws CmsRoleViolationException { 2235 2236 OpenCms.getRoleManager().checkRole(m_cms, CmsRole.WORKPLACE_USER); 2237 } 2238 2239 /** 2240 * Decodes an individual parameter value.<p> 2241 * 2242 * In special cases some parameters might require a different-from-default 2243 * encoding. This is the case if the content of the parameter was 2244 * encoded using the JavaScript encodeURIComponent() method on the client, 2245 * which always encodes in UTF-8.<p> 2246 * 2247 * @param paramName the name of the parameter 2248 * @param paramValue the unencoded value of the parameter 2249 * 2250 * @return the encoded value of the parameter 2251 */ 2252 protected String decodeParamValue(String paramName, String paramValue) { 2253 2254 if ((paramName != null) && (paramValue != null)) { 2255 return CmsEncoder.decode(paramValue, getCms().getRequestContext().getEncoding()); 2256 } else { 2257 return null; 2258 } 2259 } 2260 2261 /** 2262 * Returns the map of parameters read from the current request.<p> 2263 * 2264 * This method will also handle parameters from forms 2265 * of type <code>multipart/form-data</code>.<p> 2266 * 2267 * @return the map of parameters read from the current request 2268 */ 2269 protected Map<String, String[]> getParameterMap() { 2270 2271 return m_parameterMap; 2272 } 2273 2274 /** 2275 * Initializes the message object.<p> 2276 * 2277 * By default the {@link CmsWorkplaceMessages} are initialized.<p> 2278 * 2279 * You SHOULD override this method for setting the bundles you really need, 2280 * using the <code>{@link #addMessages(CmsMessages)}</code> or <code>{@link #addMessages(String)}</code> method.<p> 2281 */ 2282 protected void initMessages() { 2283 2284 // no bundles are added by default as all core bundles are added as part of the WorkplaceModuleMessages 2285 } 2286 2287 /** 2288 * Sets the users time warp if configured and if the current timewarp setting is different or 2289 * clears the current time warp setting if the user has no configured timewarp.<p> 2290 * 2291 * Timwarping is controlled by the session attribute 2292 * {@link CmsContextInfo#ATTRIBUTE_REQUEST_TIME} with a value of type <code>Long</code>.<p> 2293 * 2294 * @param settings the user settings which are configured via the preferences dialog 2295 * 2296 * @param session the session of the user 2297 */ 2298 protected void initTimeWarp(CmsUserSettings settings, HttpSession session) { 2299 2300 long timeWarpConf = settings.getTimeWarp(); 2301 Long timeWarpSetLong = (Long)session.getAttribute(CmsContextInfo.ATTRIBUTE_REQUEST_TIME); 2302 long timeWarpSet = (timeWarpSetLong != null) ? timeWarpSetLong.longValue() : CmsContextInfo.CURRENT_TIME; 2303 2304 if (timeWarpConf == CmsContextInfo.CURRENT_TIME) { 2305 // delete: 2306 if (timeWarpSetLong != null) { 2307 // we may come from direct_edit.jsp: don't remove attribute, this is 2308 session.removeAttribute(CmsContextInfo.ATTRIBUTE_REQUEST_TIME); 2309 } 2310 } else { 2311 // this is dominant: if configured we will use it 2312 if (timeWarpSet != timeWarpConf) { 2313 session.setAttribute(CmsContextInfo.ATTRIBUTE_REQUEST_TIME, Long.valueOf(timeWarpConf)); 2314 } 2315 } 2316 } 2317 2318 /** 2319 * Initializes this workplace class instance.<p> 2320 * 2321 * This method can be used in case there a workplace class was generated using 2322 * {@link Class#forName(java.lang.String)} to initialize the class members.<p> 2323 * 2324 * @param jsp the initialized JSP context 2325 */ 2326 protected void initWorkplaceMembers(CmsJspActionElement jsp) { 2327 2328 if (jsp != null) { 2329 m_jsp = jsp; 2330 initWorkplaceMembers(m_jsp.getCmsObject(), m_jsp.getRequest().getSession()); 2331 } 2332 } 2333 2334 /** 2335 * Initializes this workplace class instance.<p> 2336 * 2337 * @param cms the user context 2338 * @param session the session 2339 */ 2340 protected void initWorkplaceMembers(CmsObject cms, HttpSession session) { 2341 2342 m_cms = cms; 2343 m_session = session; 2344 // check role 2345 try { 2346 checkRole(); 2347 } catch (CmsRoleViolationException e) { 2348 throw new CmsIllegalStateException(e.getMessageContainer(), e); 2349 } 2350 2351 // get / create the workplace settings 2352 m_settings = (CmsWorkplaceSettings)m_session.getAttribute(CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS); 2353 2354 if (m_settings == null) { 2355 // create the settings object 2356 m_settings = new CmsWorkplaceSettings(); 2357 m_settings = initWorkplaceSettings(m_cms, m_settings, false); 2358 2359 storeSettings(m_session, m_settings); 2360 } 2361 2362 // initialize messages 2363 CmsMessages messages = OpenCms.getWorkplaceManager().getMessages(getLocale()); 2364 // generate a new multi messages object and add the messages from the workplace 2365 m_messages = new CmsMultiMessages(getLocale()); 2366 m_messages.addMessages(messages); 2367 initMessages(); 2368 2369 if (m_jsp != null) { 2370 // check request for changes in the workplace settings 2371 initWorkplaceRequestValues(m_settings, m_jsp.getRequest()); 2372 } 2373 // set cms context accordingly 2374 initWorkplaceCmsContext(m_settings, m_cms); 2375 2376 // timewarp reset logic 2377 initTimeWarp(m_settings.getUserSettings(), m_session); 2378 } 2379 2380 /** 2381 * Analyzes the request for workplace parameters and adjusts the workplace 2382 * settings accordingly.<p> 2383 * 2384 * @param settings the workplace settings 2385 * @param request the current request 2386 */ 2387 protected abstract void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request); 2388 2389 /** 2390 * Returns the values of all parameter methods of this workplace class instance.<p> 2391 * 2392 * @return the values of all parameter methods of this workplace class instance 2393 */ 2394 protected Map<String, Object> paramValues() { 2395 2396 List<Method> methods = paramGetMethods(); 2397 Map<String, Object> map = new HashMap<String, Object>(methods.size()); 2398 Iterator<Method> i = methods.iterator(); 2399 while (i.hasNext()) { 2400 Method m = i.next(); 2401 Object o = null; 2402 try { 2403 o = m.invoke(this, new Object[0]); 2404 } catch (InvocationTargetException ite) { 2405 // can usually be ignored 2406 if (LOG.isInfoEnabled()) { 2407 LOG.info(ite.getLocalizedMessage()); 2408 } 2409 } catch (IllegalAccessException eae) { 2410 // can usually be ignored 2411 if (LOG.isInfoEnabled()) { 2412 LOG.info(eae.getLocalizedMessage()); 2413 } 2414 } 2415 if (o != null) { 2416 map.put(m.getName().substring(8).toLowerCase(), o); 2417 } 2418 } 2419 return map; 2420 } 2421 2422 /** 2423 * Replaces the site title, if necessary.<p> 2424 * 2425 * @param title the site title 2426 * 2427 * @return the new site title 2428 */ 2429 protected String substituteSiteTitle(String title) { 2430 2431 return substituteSiteTitleStatic(title, getSettings().getUserSettings().getLocale()); 2432 } 2433 2434 /** 2435 * Helper method to change back from the temporary project to the current project.<p> 2436 * 2437 * @throws CmsException if switching back fails 2438 */ 2439 protected void switchToCurrentProject() throws CmsException { 2440 2441 if (m_currentProjectId != null) { 2442 // switch back to the current users project 2443 getCms().getRequestContext().setCurrentProject(getCms().readProject(m_currentProjectId)); 2444 } 2445 } 2446 2447 /** 2448 * Helper method to change the current project to the temporary file project.<p> 2449 * 2450 * The id of the old project is stored in a member variable to switch back.<p> 2451 * 2452 * @return the id of the tempfileproject 2453 * @throws CmsException if getting the tempfileproject id fails 2454 */ 2455 protected CmsUUID switchToTempProject() throws CmsException { 2456 2457 // store the current project id in member variable 2458 m_currentProjectId = getSettings().getProject(); 2459 CmsUUID tempProjectId = OpenCms.getWorkplaceManager().getTempFileProjectId(); 2460 getCms().getRequestContext().setCurrentProject(getCms().readProject(tempProjectId)); 2461 return tempProjectId; 2462 } 2463 2464 /** 2465 * Sets the cms request context and other cms related settings to the 2466 * values stored in the workplace settings.<p> 2467 * 2468 * @param settings the workplace settings 2469 * @param cms the current cms object 2470 */ 2471 private void initWorkplaceCmsContext(CmsWorkplaceSettings settings, CmsObject cms) { 2472 2473 CmsRequestContext reqCont = cms.getRequestContext(); 2474 2475 // check project setting 2476 if (!settings.getProject().equals(reqCont.getCurrentProject().getUuid())) { 2477 try { 2478 reqCont.setCurrentProject(cms.readProject(settings.getProject())); 2479 } catch (CmsDbEntryNotFoundException e) { 2480 try { 2481 // project not found, set current project and settings to online project 2482 reqCont.setCurrentProject(cms.readProject(CmsProject.ONLINE_PROJECT_ID)); 2483 settings.setProject(CmsProject.ONLINE_PROJECT_ID); 2484 } catch (CmsException ex) { 2485 // log error 2486 if (LOG.isInfoEnabled()) { 2487 LOG.info(ex.getLocalizedMessage()); 2488 } 2489 } 2490 } catch (CmsException e1) { 2491 if (LOG.isInfoEnabled()) { 2492 LOG.info(e1.getLocalizedMessage()); 2493 } 2494 } 2495 } 2496 2497 // check site setting 2498 if (!(settings.getSite().equals(reqCont.getSiteRoot()))) { 2499 // site was switched, set new site root 2500 reqCont.setSiteRoot(settings.getSite()); 2501 // removed setting explorer resource to "/" to get the stored folder 2502 } 2503 } 2504 2505 /** 2506 * Returns a list of all methods of the current class instance that 2507 * start with "getParam" and have no parameters.<p> 2508 * 2509 * @return a list of all methods of the current class instance that 2510 * start with "getParam" and have no parameters 2511 */ 2512 private List<Method> paramGetMethods() { 2513 2514 List<Method> list = new ArrayList<Method>(); 2515 Method[] methods = this.getClass().getMethods(); 2516 int length = methods.length; 2517 for (int i = 0; i < length; i++) { 2518 Method method = methods[i]; 2519 if (method.getName().startsWith("getParam") && (method.getParameterTypes().length == 0)) { 2520 if (DEBUG) { 2521 System.err.println("getMethod: " + method.getName()); 2522 } 2523 list.add(method); 2524 } 2525 } 2526 return list; 2527 } 2528 2529 /** 2530 * Returns a list of all methods of the current class instance that 2531 * start with "setParam" and have exactly one String parameter.<p> 2532 * 2533 * @return a list of all methods of the current class instance that 2534 * start with "setParam" and have exactly one String parameter 2535 */ 2536 private List<Method> paramSetMethods() { 2537 2538 List<Method> list = new ArrayList<Method>(); 2539 Method[] methods = getClass().getMethods(); 2540 int length = methods.length; 2541 for (int i = 0; i < length; i++) { 2542 Method method = methods[i]; 2543 if (method.getName().startsWith("setParam") 2544 && (method.getParameterTypes().length == 1) 2545 && (method.getParameterTypes()[0].equals(java.lang.String.class))) { 2546 if (DEBUG) { 2547 System.err.println("setMethod: " + method.getName()); 2548 } 2549 list.add(method); 2550 } 2551 } 2552 return list; 2553 } 2554}