001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://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.explorer; 029 030import org.opencms.db.CmsResourceState; 031import org.opencms.file.CmsFolder; 032import org.opencms.file.CmsObject; 033import org.opencms.file.CmsProject; 034import org.opencms.file.CmsProperty; 035import org.opencms.file.CmsPropertyDefinition; 036import org.opencms.file.CmsResource; 037import org.opencms.file.CmsResourceFilter; 038import org.opencms.file.types.CmsResourceTypePlain; 039import org.opencms.file.types.I_CmsResourceType; 040import org.opencms.i18n.CmsMessages; 041import org.opencms.jsp.CmsJspActionElement; 042import org.opencms.loader.CmsLoaderException; 043import org.opencms.main.CmsException; 044import org.opencms.main.CmsLog; 045import org.opencms.main.OpenCms; 046import org.opencms.site.CmsSite; 047import org.opencms.util.CmsStringUtil; 048import org.opencms.workplace.CmsWorkplace; 049import org.opencms.workplace.CmsWorkplaceSettings; 050 051import java.util.ArrayList; 052import java.util.Iterator; 053import java.util.List; 054import java.util.Locale; 055import java.util.StringTokenizer; 056 057import org.apache.commons.logging.Log; 058 059import jakarta.servlet.http.HttpServletRequest; 060 061/** 062 * Generates the tree view for the OpenCms Workplace.<p> 063 * 064 * The following Workplace files use this class: 065 * <ul> 066 * <li>/views/explorer/tree_fs.jsp 067 * <li>/views/explorer/tree_files.jsp 068 * </ul> 069 * <p> 070 * 071 * @since 6.0.0 072 */ 073public class CmsTree extends CmsWorkplace { 074 075 /** Request parameter name for the includesfiles parameter. */ 076 public static final String PARAM_INCLUDEFILES = "includefiles"; 077 078 /** Request parameter name for the lastknown parameter. */ 079 public static final String PARAM_LASTKNOWN = "lastknown"; 080 081 /** Request parameter name for the projectaware parameter. */ 082 public static final String PARAM_PROJECTAWARE = "projectaware"; 083 084 /** Request parameter name for the resource parameter. */ 085 public static final String PARAM_RESOURCE = "resource"; 086 087 /** Request parameter name for the rootloaded parameter. */ 088 public static final String PARAM_ROOTLOADED = "rootloaded"; 089 090 /** Request parameter name for the showsiteselector parameter. */ 091 public static final String PARAM_SHOWSITESELECTOR = "showsiteselector"; 092 093 /** Request parameter name for the integrator parameter. */ 094 public static final String PARAM_INTEGRATOR = "integrator"; 095 096 /** Request parameter name for the treesite parameter. */ 097 public static final String PARAM_TREESITE = "treesite"; 098 099 /** Request parameter name for the type parameter. */ 100 public static final String PARAM_TYPE = "type"; 101 102 /** The log object for this class. */ 103 private static final Log LOG = CmsLog.getLog(CmsTree.class); 104 105 /** Type name for showing the tree when copying resources. */ 106 private static final String TYPE_COPY = "copy"; 107 108 /** Type name for showing the tree when creating page links in the editor. */ 109 private static final String TYPE_PAGELINK = "pagelink"; 110 111 /** Type name for showing the tree in preferences dialog. */ 112 private static final String TYPE_PREFERENCES = "preferences"; 113 114 /** Type name for showing the tree when creating siblings. */ 115 private static final String TYPE_SIBLING = "sibling"; 116 117 /** Type name for showing the tree in a widget dialog. */ 118 private static final String TYPE_VFSWIDGET = "vfswidget"; 119 120 /** Indicates if only folders or files and folders should be included in the tree. */ 121 private boolean m_includeFiles; 122 123 /** Indicates if a complete new tree should be created. */ 124 private boolean m_newTree; 125 126 /** Indicates project awareness, ie. if resources outside of the current project should be displayed as normal. */ 127 private boolean m_projectAware = true; 128 129 /** The name of the root folder to display the tree from, usually "/". */ 130 private String m_rootFolder; 131 132 /** Flag to indicate if the site selector should be shown in popup tree window. */ 133 private boolean m_showSiteSelector; 134 135 /** The name of the start folder (or "last known" folder) to be loaded. */ 136 private String m_startFolder; 137 138 /** The name of the target folder to be loaded. */ 139 private String m_targetFolder; 140 141 /** The type of the tree (e.g. "copy", "project" etc.). */ 142 private String m_treeType; 143 144 /** 145 * Public constructor.<p> 146 * 147 * @param jsp an initialized JSP action element 148 */ 149 public CmsTree(CmsJspActionElement jsp) { 150 151 super(jsp); 152 } 153 154 /** 155 * Returns the HTML for the tree initialization.<p> 156 * 157 * @param cms the CmsObject 158 * @param encoding the current encoding 159 * @param skinUri the current skin URI 160 * @return the HTML for the tree initialization 161 */ 162 public static String initTree(CmsObject cms, String encoding, String skinUri) { 163 164 StringBuffer retValue = new StringBuffer(512); 165 String servletUrl = OpenCms.getSystemInfo().getOpenCmsContext(); 166 167 // get the localized workplace messages 168 // TODO: Why a new message object, can it not be obtained from session? 169 Locale locale = cms.getRequestContext().getLocale(); 170 CmsMessages messages = OpenCms.getWorkplaceManager().getMessages(locale); 171 172 retValue.append("function initTreeResources() {\n"); 173 retValue.append("\tinitResources(\""); 174 retValue.append(encoding); 175 retValue.append("\", \""); 176 retValue.append(PATH_WORKPLACE); 177 retValue.append("\", \""); 178 retValue.append(skinUri); 179 retValue.append("\", \""); 180 retValue.append(servletUrl); 181 retValue.append("\");\n"); 182 183 // get all available resource types 184 List<I_CmsResourceType> allResTypes = OpenCms.getResourceManager().getResourceTypes(); 185 for (int i = 0; i < allResTypes.size(); i++) { 186 // loop through all types 187 I_CmsResourceType type = allResTypes.get(i); 188 int curTypeId = type.getTypeId(); 189 String curTypeName = type.getTypeName(); 190 // get the settings for the resource type 191 CmsExplorerTypeSettings settings = OpenCms.getWorkplaceManager().getExplorerTypeSetting(curTypeName); 192 if (settings == null) { 193 if (LOG.isWarnEnabled()) { 194 LOG.warn(Messages.get().getBundle().key(Messages.LOG_MISSING_SETTINGS_ENTRY_1, curTypeName)); 195 } 196 settings = OpenCms.getWorkplaceManager().getExplorerTypeSetting( 197 CmsResourceTypePlain.getStaticTypeName()); 198 } 199 retValue.append("\taddResourceType("); 200 retValue.append(curTypeId); 201 retValue.append(", \""); 202 retValue.append(curTypeName); 203 retValue.append("\",\t\""); 204 retValue.append(messages.key(settings.getKey())); 205 retValue.append("\",\t\"" + CmsWorkplace.RES_PATH_FILETYPES); 206 retValue.append(settings.getIcon()); 207 retValue.append("\");\n"); 208 } 209 210 retValue.append("}\n\n"); 211 retValue.append("initTreeResources();\n"); 212 String sharedFolder = OpenCms.getSiteManager().getSharedFolder(); 213 if (sharedFolder != null) { 214 retValue.append("sharedFolderName = '" + sharedFolder + "';"); 215 } 216 return retValue.toString(); 217 } 218 219 /** 220 * Determines the root folder of the current tree dependent on users setting of explorer view restriction.<p> 221 * 222 * @return the root folder resource name to display 223 */ 224 public String getRootFolder() { 225 226 if (m_rootFolder == null) { 227 String folder = "/"; 228 if ((getTreeType() == null) && getSettings().getUserSettings().getRestrictExplorerView()) { 229 folder = getSettings().getUserSettings().getStartFolder(); 230 } 231 try { 232 getCms().readFolder(folder, CmsResourceFilter.IGNORE_EXPIRATION); 233 } catch (CmsException e) { 234 if (LOG.isInfoEnabled()) { 235 LOG.info(e.getLocalizedMessage(), e); 236 } 237 folder = "/"; 238 } 239 m_rootFolder = folder; 240 } 241 return m_rootFolder; 242 } 243 244 /** 245 * Returns the HTML for the site selector box for the explorer tree window.<p> 246 * 247 * @param htmlAttributes optional attributes for the <select> tag 248 * @return HTML code for the site selector box 249 */ 250 public String getSiteSelector(String htmlAttributes) { 251 252 List<String> options = new ArrayList<String>(); 253 List<String> values = new ArrayList<String>(); 254 int selectedIndex = 0; 255 String preSelection = getSettings().getTreeSite(getTreeType()); 256 if (preSelection == null) { 257 if ("".equals(getCms().getRequestContext().getSiteRoot())) { 258 // we are in the root site, getCurrentSite(CmsObject) includes NOT the root site 259 preSelection = ""; 260 } else { 261 // get the site root of the current site 262 preSelection = OpenCms.getSiteManager().getCurrentSite(getCms()).getSiteRoot(); 263 } 264 // set the tree site to avoid discrepancies between selector and tree 265 getSettings().setTreeSite(getTreeType(), preSelection); 266 } 267 268 boolean includeRootSite = true; 269 boolean showSiteUrls = false; 270 if (TYPE_PAGELINK.equals(getTreeType())) { 271 // in wysiwyg editor link dialog, don't show root site, but show site URLs 272 includeRootSite = false; 273 showSiteUrls = true; 274 } 275 List<CmsSite> sites = OpenCms.getSiteManager().getAvailableSites( 276 getCms(), 277 includeRootSite, 278 true, 279 getCms().getRequestContext().getOuFqn()); 280 281 Iterator<CmsSite> i = sites.iterator(); 282 int pos = 0; 283 while (i.hasNext()) { 284 CmsSite site = i.next(); 285 values.add(site.getSiteRoot()); 286 String curOption = substituteSiteTitle(site.getTitle()); 287 if (showSiteUrls && (site.getSiteMatcher() != null)) { 288 // show the site URL in editor link dialog tree 289 curOption = site.getUrl() + " (" + curOption + ")"; 290 if (getCms().getRequestContext().getSiteRoot().equals(site.getSiteRoot())) { 291 // mark the current workplace site in selector 292 curOption = "*" + curOption; 293 } 294 } 295 296 if (site.getSiteRoot().equals(preSelection)) { 297 // this is the user's currently selected site 298 selectedIndex = pos; 299 } 300 options.add(curOption); 301 pos++; 302 } 303 304 return buildSelect(htmlAttributes, options, values, selectedIndex); 305 } 306 307 /** 308 * Returns the html for the explorer tree.<p> 309 * 310 * @return the html for the explorer tree 311 */ 312 public String getTree() { 313 314 StringBuffer result = new StringBuffer(2048); 315 316 List<String> targetFolderList = new ArrayList<String>(); 317 if (getTargetFolder() != null) { 318 // check if there is more than one folder to update (e.g. move operation) 319 StringTokenizer T = new StringTokenizer(getTargetFolder(), "|"); 320 while (T.hasMoreTokens()) { 321 String currentFolder = T.nextToken().trim(); 322 // if (OpenCms.getSiteManager().startsWithShared(currentFolder)) { 323 // currentFolder = OpenCms.getSiteManager().cutShared(currentFolder); 324 // } 325 targetFolderList.add(currentFolder); 326 } 327 } else { 328 targetFolderList.add(null); 329 } 330 331 String storedSiteRoot = null; 332 try { 333 CmsFolder folder = null; 334 List<CmsResource> resources = new ArrayList<CmsResource>(); 335 String oldSiteRoot = getCms().getRequestContext().getSiteRoot(); 336 337 Iterator<String> targets = targetFolderList.iterator(); 338 while (targets.hasNext()) { 339 // iterate over all given target folders 340 String currentTargetFolder = targets.next(); 341 342 if (getSettings().getTreeSite(getTreeType()) != null) { 343 // change the site root for popup window with site selector 344 storedSiteRoot = getCms().getRequestContext().getSiteRoot(); 345 if (newTree() && (currentTargetFolder == null)) { 346 currentTargetFolder = "/"; 347 } 348 getCms().getRequestContext().setSiteRoot(getSettings().getTreeSite(getTreeType())); 349 try { 350 // check presence of target folder 351 getCms().readFolder(currentTargetFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 352 } catch (CmsException e) { 353 // target folder not found, set it to "/" 354 if (LOG.isInfoEnabled()) { 355 LOG.info(e.getLocalizedMessage(), e); 356 } 357 currentTargetFolder = "/"; 358 } 359 } 360 361 // read the selected folder 362 try { 363 folder = getCms().readFolder(currentTargetFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 364 } catch (CmsException e) { 365 // return with error 366 return printError(e); 367 } 368 369 String startFolder = getStartFolder(); 370 String rcSite = getCms().getRequestContext().getSiteRoot(); 371 if (OpenCms.getSiteManager().startsWithShared(currentTargetFolder) 372 && OpenCms.getSiteManager().startsWithShared(rcSite)) { 373 currentTargetFolder = currentTargetFolder.substring( 374 OpenCms.getSiteManager().getSharedFolder().length() - 1); 375 } 376 if ((startFolder == null) || (!currentTargetFolder.startsWith(startFolder))) { 377 // no (valid) start folder given, just load current folder 378 try { 379 if (includeFiles()) { 380 resources.addAll( 381 getCms().getResourcesInFolder( 382 currentTargetFolder, 383 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)); 384 } else { 385 resources.addAll( 386 getCms().getSubFolders(currentTargetFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)); 387 } 388 } catch (CmsException e) { 389 // return with error 390 return printError(e); 391 } 392 } else { 393 // valid start folder given, load all folders between start and current folder 394 try { 395 if (includeFiles()) { 396 resources.addAll( 397 getCms().getResourcesInFolder(startFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)); 398 } else { 399 resources.addAll( 400 getCms().getSubFolders(startFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)); 401 } 402 StringTokenizer tok = new StringTokenizer( 403 currentTargetFolder.substring(startFolder.length()), 404 "/"); 405 while (tok.hasMoreTokens()) { 406 startFolder += tok.nextToken() + "/"; 407 if (includeFiles()) { 408 resources.addAll( 409 getCms().getResourcesInFolder( 410 startFolder, 411 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)); 412 } else { 413 resources.addAll( 414 getCms().getSubFolders(startFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)); 415 } 416 } 417 } catch (CmsException e) { 418 // return with error 419 return printError(e); 420 } 421 } 422 } 423 424 result.append("function init() {\n"); 425 426 if (newTree()) { 427 // new tree must be reloaded 428 result.append("parent.initTree();\n"); 429 result.append(getRootNode()); 430 } 431 432 // read the list of project resource to select which resource is "inside" or "outside" 433 List<String> projectResources = new ArrayList<String>(); 434 if (isProjectAware()) { 435 try { 436 projectResources = getCms().readProjectResources(getCms().getRequestContext().getCurrentProject()); 437 } catch (CmsException e) { 438 // use an empty list (all resources are "outside") 439 if (LOG.isInfoEnabled()) { 440 LOG.info(e.getLocalizedMessage(), e); 441 } 442 } 443 } 444 445 // now output all the tree nodes 446 Iterator<CmsResource> i = resources.iterator(); 447 while (i.hasNext()) { 448 CmsResource resource = i.next(); 449 boolean grey = false; 450 if (isProjectAware()) { 451 grey = !CmsProject.isInsideProject(projectResources, resource); 452 } 453 if (!grey) { 454 try { 455 OpenCms.getResourceManager().getResourceType(resource.getTypeId()); 456 } catch (CmsLoaderException e) { 457 // if resource type is not found 458 grey = true; 459 } 460 } 461 462 result.append( 463 getNode( 464 resource.getRootPath(), 465 resource.getName(), 466 resource.getTypeId(), 467 resource.isFolder(), 468 resource.getState(), 469 grey)); 470 } 471 472 if (includeFiles()) { 473 result.append("parent.setIncludeFiles(true);\n"); 474 } 475 result.append("parent.setProjectAware(").append(isProjectAware()).append(");\n"); 476 if (getTreeType() != null) { 477 // this is a popup window tree 478 result.append("parent.setTreeType(\""); 479 result.append(getTreeType()); 480 result.append("\");\n"); 481 String curSite = getSettings().getTreeSite(getTreeType()); 482 if (curSite != null) { 483 // add the current site as prefix if present 484 result.append("parent.setSitePrefix(\""); 485 result.append(getSitePrefix(curSite, oldSiteRoot)); 486 result.append("\");\n"); 487 } 488 } 489 // set the root folder in javascript 490 result.append("parent.setRootFolder(\""); 491 result.append(getRootFolder()); 492 result.append("\");\n"); 493 494 if (folder != null) { 495 if (newTree()) { 496 // new tree 497 result.append("parent.showTree(parent.tree_display.document, \""); 498 result.append(folder.getRootPath().hashCode()); 499 result.append("\");\n"); 500 } else { 501 // update the current tree with the children of the selected node 502 if (resources.size() == 0) { 503 // the node had no children 504 result.append("parent.setNoChilds(\""); 505 result.append(folder.getRootPath().hashCode()); 506 result.append("\");\n"); 507 } 508 result.append("parent.showLoadedNodes(parent.tree_display.document,\""); 509 result.append(folder.getRootPath().hashCode()); 510 result.append("\");\n"); 511 } 512 } 513 514 result.append("}\n"); 515 } finally { 516 if (storedSiteRoot != null) { 517 getCms().getRequestContext().setSiteRoot(storedSiteRoot); 518 } 519 } 520 return result.toString(); 521 } 522 523 /** 524 * Returns the type of this tree (e.g. "copy", "project" etc.), 525 * if null this is the default explorer version.<p> 526 * 527 * @return the current type of the tree (e.g. "copy", "project" etc.) 528 */ 529 public String getTreeType() { 530 531 return m_treeType; 532 } 533 534 /** 535 * Indicates if only folders or files and folders should be included in the tree.<p> 536 * 537 * @return true if files and folders should be included in the tree 538 */ 539 public boolean includeFiles() { 540 541 return m_includeFiles; 542 } 543 544 /** 545 * Returns the HTML for the tree initialization.<p> 546 * 547 * @return the HTML for the tree initialization 548 */ 549 public String initTree() { 550 551 return initTree(getCms(), getEncoding(), getSkinUri()); 552 } 553 554 /** 555 * Returns the project awareness flag.<p> 556 * 557 * @return the project awareness flag 558 */ 559 public boolean isProjectAware() { 560 561 return m_projectAware; 562 } 563 564 /** 565 * Sets the project awareness flag.<p> 566 * 567 * @param projectAware the project awareness flag to set 568 */ 569 public void setProjectAware(boolean projectAware) { 570 571 m_projectAware = projectAware; 572 } 573 574 /** 575 * Indicates if the site selector should be shown depending on the tree type, initial settings and the count of accessible sites.<p> 576 * 577 * @return true if site selector should be shown, otherwise false 578 */ 579 public boolean showSiteSelector() { 580 581 return m_showSiteSelector; 582 } 583 584 /** 585 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, jakarta.servlet.http.HttpServletRequest) 586 */ 587 @Override 588 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 589 590 setIncludeFiles(Boolean.valueOf(request.getParameter(PARAM_INCLUDEFILES)).booleanValue()); 591 setProjectAware(Boolean.valueOf(request.getParameter(PARAM_PROJECTAWARE)).booleanValue()); 592 boolean rootloaded = Boolean.valueOf(request.getParameter(PARAM_ROOTLOADED)).booleanValue(); 593 String resource = request.getParameter(PARAM_RESOURCE); 594 595 setTreeType(request.getParameter(PARAM_TYPE)); 596 String treeSite = request.getParameter(PARAM_TREESITE); 597 if ((getTreeType() != null) && (treeSite != null)) { 598 getSettings().setTreeSite(getTreeType(), treeSite); 599 } 600 601 if (getSettings().getTreeSite(getTreeType()) != null) { 602 String site = getCms().getRequestContext().getSiteRoot(); 603 try { 604 getCms().getRequestContext().setSiteRoot(getSettings().getTreeSite(getTreeType())); 605 if (!getCms().existsResource(resource)) { 606 resource = null; 607 } 608 } finally { 609 getCms().getRequestContext().setSiteRoot(site); 610 } 611 } else { 612 if (!getCms().existsResource(resource)) { 613 resource = null; 614 } 615 } 616 617 computeSiteSelector(request); 618 619 String currentResource; 620 if (getTreeType() == null) { 621 currentResource = getSettings().getExplorerResource(); 622 } else { 623 // get the current tree resource from the settings for a special tree type 624 currentResource = getSettings().getTreeResource(getTreeType()); 625 } 626 627 String lastknown = request.getParameter(PARAM_LASTKNOWN); 628 // both "resource" and "lastknown" must be folders 629 630 if (resource != null) { 631 resource = CmsResource.getFolderPath(resource); 632 } 633 if ((lastknown != null) && (!lastknown.endsWith("/"))) { 634 lastknown += "/"; 635 } 636 637 String rootFolder = getRootFolder(); 638 if (rootFolder.equals(resource) && !rootFolder.equals(currentResource) && (lastknown == null) && !rootloaded) { 639 // direct load of a new tree with subtree (e.g. when returning from an editor) 640 lastknown = getRootFolder(); 641 resource = CmsResource.getFolderPath(currentResource); 642 setNewTree(true); 643 } else if (rootFolder.equals(resource)) { 644 // load new tree if not already loaded 645 setNewTree(!rootloaded); 646 } else { 647 setNewTree(false); 648 } 649 650 if (getTreeType() != null) { 651 getSettings().setTreeResource(getTreeType(), resource); 652 } 653 654 setTargetFolder(resource); 655 setStartFolder(lastknown); 656 } 657 658 /** 659 * Determines if the site selector frame should be shown depending on the tree type or the value of a request parameter.<p> 660 * 661 * If only one site is available, the site selector is not displayed.<p> 662 * 663 * @param request the HttpServletRequest to check 664 */ 665 private void computeSiteSelector(HttpServletRequest request) { 666 667 boolean selectorForType = TYPE_SIBLING.equals(getTreeType()) 668 || TYPE_COPY.equals(getTreeType()) 669 || TYPE_PAGELINK.equals(getTreeType()) 670 || TYPE_PREFERENCES.equals(getTreeType()); 671 boolean showFromRequest = Boolean.valueOf(request.getParameter(PARAM_SHOWSITESELECTOR)).booleanValue(); 672 if (selectorForType || showFromRequest) { 673 // get all available sites 674 int siteCount = OpenCms.getSiteManager().getAvailableSites(getCms(), true).size(); 675 setShowSiteSelector(siteCount > 1); 676 return; 677 } 678 setShowSiteSelector(false); 679 } 680 681 /** 682 * Creates the output for a tree node.<p> 683 * 684 * @param path the path of the resource represented by this tree node 685 * @param title the resource name 686 * @param type the resource type 687 * @param folder if the resource is a folder 688 * @param state the resource state 689 * @param grey if true, the node is displayed in grey 690 * 691 * @return the output for a tree node 692 */ 693 private String getNode(String path, String title, int type, boolean folder, CmsResourceState state, boolean grey) { 694 695 StringBuffer result = new StringBuffer(64); 696 String parent = CmsResource.getParentFolder(path); 697 result.append("parent.aC(\""); 698 // name 699 result.append(title); 700 result.append("\","); 701 // type 702 result.append(type); 703 result.append(","); 704 // folder 705 if (folder) { 706 result.append(1); 707 } else { 708 result.append(0); 709 } 710 result.append(","); 711 // hashcode of path 712 result.append(path.hashCode()); 713 result.append(","); 714 // hashcode of parent path 715 result.append((parent != null) ? parent.hashCode() : 0); 716 result.append(","); 717 // resource state 718 result.append(state); 719 result.append(","); 720 // project status 721 if (grey) { 722 result.append(1); 723 } else { 724 result.append(0); 725 } 726 result.append(");\n"); 727 return result.toString(); 728 } 729 730 /** 731 * Creates a node entry for the root node of the current site.<p> 732 * 733 * @return a node entry for the root node of the current site 734 */ 735 private String getRootNode() { 736 737 CmsResource resource = null; 738 String title = null; 739 String folder = getRootFolder(); 740 try { 741 resource = getCms().readFolder(folder, CmsResourceFilter.IGNORE_EXPIRATION); 742 // get the title information of the folder 743 CmsProperty titleProperty = getCms().readPropertyObject( 744 folder, 745 CmsPropertyDefinition.PROPERTY_TITLE, 746 false); 747 748 if ((titleProperty == null) || titleProperty.isNullProperty()) { 749 getCms().getSitePath(resource); 750 title = resource.getRootPath(); 751 } else { 752 title = titleProperty.getValue(); 753 } 754 return getNode(resource.getRootPath(), title, resource.getTypeId(), true, resource.getState(), false); 755 } catch (CmsException e) { 756 // should usually never happen 757 if (LOG.isInfoEnabled()) { 758 LOG.info(e.getLocalizedMessage(), e); 759 } 760 } 761 return ""; 762 } 763 764 /** 765 * Calculates the prefix that has to be added when selecting a resource in a popup tree window.<p> 766 * 767 * This is needed for the link dialog in editors 768 * as well as the copy, move and link popup dialogs for resources in the VFS.<p> 769 * 770 * @param prefix the current prefix of the resource 771 * @param storedSiteRoot the site root in which the workplace (not the tree!) is 772 * @return the prefix which is added to the resource name 773 */ 774 private String getSitePrefix(String prefix, String storedSiteRoot) { 775 776 if (OpenCms.getSiteManager().isSharedFolder(prefix)) { 777 return prefix; 778 } 779 if (TYPE_PAGELINK.equals(getTreeType())) { 780 // in editor link dialog, create a special prefix for internal links 781 if (!storedSiteRoot.equals(prefix)) { 782 // stored site is not selected site, create complete URL as prefix 783 CmsSite site = OpenCms.getSiteManager().getSiteForSiteRoot(prefix); 784 prefix = getCms().getRequestContext().removeSiteRoot(prefix); 785 prefix = site.getUrl() + OpenCms.getSystemInfo().getOpenCmsContext() + prefix; 786 } else { 787 // stored site is selected site, don't show prefix at all 788 prefix = ""; 789 } 790 791 } else if (TYPE_COPY.equals(getTreeType()) 792 || TYPE_SIBLING.equals(getTreeType()) 793 || TYPE_VFSWIDGET.equals(getTreeType())) { 794 // in vfs copy|move|link or vfs widget mode, don't add the prefix for the current workplace site 795 if (storedSiteRoot.equals(prefix)) { 796 prefix = ""; 797 } 798 } else if (TYPE_PREFERENCES.equals(getTreeType())) { 799 prefix = ""; 800 } 801 802 return prefix; 803 } 804 805 /** 806 * Returns the name of the start folder (or "last known" folder) to be loaded.<p> 807 * 808 * @return the name of the start folder (or "last known" folder) to be loaded 809 */ 810 private String getStartFolder() { 811 812 return m_startFolder; 813 } 814 815 /** 816 * Returns the target folder name.<p> 817 * 818 * @return the target folder name 819 */ 820 private String getTargetFolder() { 821 822 return m_targetFolder; 823 } 824 825 /** 826 * Returns true if a complete new tree must be loaded, false if an existing 827 * tree is updated or extended.<p> 828 * 829 * @return true if a complete new tree must be loaded 830 */ 831 private boolean newTree() { 832 833 return m_newTree; 834 } 835 836 /** 837 * Creates error information output.<p> 838 * 839 * @param t an error that occurred 840 * @return error information output 841 */ 842 private String printError(Throwable t) { 843 844 StringBuffer result = new StringBuffer(1024); 845 result.append("/*\n"); 846 result.append(CmsStringUtil.escapeHtml(t.getMessage())); 847 result.append("\n*/\n"); 848 result.append("function init() {\n"); 849 result.append("}\n"); 850 return result.toString(); 851 } 852 853 /** 854 * Sets the value to indicate if only folders or files and folders should be included in the tree.<p> 855 * 856 * @param includeFiles if true if files and folders should be included in the tree 857 */ 858 private void setIncludeFiles(boolean includeFiles) { 859 860 m_includeFiles = includeFiles; 861 } 862 863 /** 864 * Sets if a complete tree must be loaded.<p> 865 * 866 * @param newTree if true, a complete tree must be loaded 867 */ 868 private void setNewTree(boolean newTree) { 869 870 m_newTree = newTree; 871 } 872 873 /** 874 * Sets if the site selector should be shown depending on the tree type and the count of accessible sites.<p> 875 * 876 * @param showSiteSelector true if site selector should be shown, otherwise false 877 */ 878 private void setShowSiteSelector(boolean showSiteSelector) { 879 880 m_showSiteSelector = showSiteSelector; 881 } 882 883 /** 884 * Sets the name of the start folder (or "last known" folder) to be loaded.<p> 885 * 886 * @param startFolder the name of the start folder (or "last known" folder) to be loaded 887 */ 888 private void setStartFolder(String startFolder) { 889 890 m_startFolder = startFolder; 891 } 892 893 /** 894 * Sets the target folder name.<p> 895 * 896 * @param targetFolder the target folder name 897 */ 898 private void setTargetFolder(String targetFolder) { 899 900 m_targetFolder = targetFolder; 901 } 902 903 /** 904 * Sets the type of this tree.<p> 905 * 906 * @param type the type of this tree 907 */ 908 private void setTreeType(String type) { 909 910 m_treeType = type; 911 } 912}