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, 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.ade.galleries; 029 030import org.opencms.ade.configuration.CmsADEConfigData; 031import org.opencms.ade.configuration.formatters.CmsFormatterConfigurationCacheState; 032import org.opencms.ade.galleries.CmsGalleryFilteredNavTreeBuilder.NavigationNode; 033import org.opencms.ade.galleries.preview.I_CmsPreviewProvider; 034import org.opencms.ade.galleries.shared.CmsGalleryActionInfo; 035import org.opencms.ade.galleries.shared.CmsGalleryConfiguration; 036import org.opencms.ade.galleries.shared.CmsGalleryDataBean; 037import org.opencms.ade.galleries.shared.CmsGalleryFolderBean; 038import org.opencms.ade.galleries.shared.CmsGalleryGroup; 039import org.opencms.ade.galleries.shared.CmsGallerySearchBean; 040import org.opencms.ade.galleries.shared.CmsGallerySearchScope; 041import org.opencms.ade.galleries.shared.CmsGalleryTabConfiguration; 042import org.opencms.ade.galleries.shared.CmsResourceTypeBean; 043import org.opencms.ade.galleries.shared.CmsResourceTypeBean.TypeVisibility; 044import org.opencms.ade.galleries.shared.CmsResultItemBean; 045import org.opencms.ade.galleries.shared.CmsSitemapEntryBean; 046import org.opencms.ade.galleries.shared.CmsVfsEntryBean; 047import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants; 048import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.GalleryMode; 049import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.GalleryTabId; 050import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.SortParams; 051import org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService; 052import org.opencms.file.CmsObject; 053import org.opencms.file.CmsProperty; 054import org.opencms.file.CmsPropertyDefinition; 055import org.opencms.file.CmsResource; 056import org.opencms.file.CmsResourceFilter; 057import org.opencms.file.CmsUser; 058import org.opencms.file.CmsVfsResourceNotFoundException; 059import org.opencms.file.types.CmsResourceTypeBinary; 060import org.opencms.file.types.CmsResourceTypeFunctionConfig; 061import org.opencms.file.types.CmsResourceTypeImage; 062import org.opencms.file.types.CmsResourceTypePointer; 063import org.opencms.file.types.CmsResourceTypeXmlContent; 064import org.opencms.file.types.CmsResourceTypeXmlPage; 065import org.opencms.file.types.I_CmsResourceType; 066import org.opencms.flex.CmsFlexController; 067import org.opencms.gwt.CmsCoreService; 068import org.opencms.gwt.CmsGwtService; 069import org.opencms.gwt.CmsIconUtil; 070import org.opencms.gwt.CmsRpcException; 071import org.opencms.gwt.CmsVfsService; 072import org.opencms.gwt.shared.CmsGalleryContainerInfo; 073import org.opencms.gwt.shared.CmsListInfoBean; 074import org.opencms.gwt.shared.CmsTemplateContextInfo; 075import org.opencms.i18n.CmsLocaleManager; 076import org.opencms.i18n.CmsMessages; 077import org.opencms.json.JSONException; 078import org.opencms.json.JSONObject; 079import org.opencms.jsp.CmsJspNavBuilder; 080import org.opencms.jsp.CmsJspNavBuilder.Visibility; 081import org.opencms.jsp.CmsJspNavElement; 082import org.opencms.loader.CmsLoaderException; 083import org.opencms.loader.CmsResourceManager; 084import org.opencms.loader.I_CmsTemplateContextProvider; 085import org.opencms.main.CmsException; 086import org.opencms.main.CmsLog; 087import org.opencms.main.CmsPermalinkResourceHandler; 088import org.opencms.main.CmsStaticResourceHandler; 089import org.opencms.main.OpenCms; 090import org.opencms.search.fields.CmsSearchFieldMapping; 091import org.opencms.search.galleries.CmsGallerySearch; 092import org.opencms.search.galleries.CmsGallerySearchParameters; 093import org.opencms.search.galleries.CmsGallerySearchResult; 094import org.opencms.search.galleries.CmsGallerySearchResultList; 095import org.opencms.security.CmsPermissionSet; 096import org.opencms.security.CmsPermissionViolationException; 097import org.opencms.security.CmsRole; 098import org.opencms.site.CmsSite; 099import org.opencms.staticexport.CmsLinkManager; 100import org.opencms.ui.components.CmsResourceIcon; 101import org.opencms.util.CmsDateUtil; 102import org.opencms.util.CmsPath; 103import org.opencms.util.CmsRequestUtil; 104import org.opencms.util.CmsStringUtil; 105import org.opencms.util.CmsUUID; 106import org.opencms.util.CmsUriSplitter; 107import org.opencms.workplace.CmsWorkplace; 108import org.opencms.workplace.CmsWorkplaceMessages; 109import org.opencms.workplace.CmsWorkplaceSettings; 110import org.opencms.workplace.explorer.CmsResourceUtil; 111import org.opencms.xml.containerpage.CmsADESessionCache; 112import org.opencms.xml.containerpage.CmsFormatterConfiguration; 113import org.opencms.xml.containerpage.CmsFunctionFormatterBean; 114import org.opencms.xml.containerpage.CmsXmlDynamicFunctionHandler; 115import org.opencms.xml.containerpage.I_CmsFormatterBean; 116 117import java.text.Collator; 118import java.text.DateFormat; 119import java.text.ParseException; 120import java.util.ArrayList; 121import java.util.Arrays; 122import java.util.Collection; 123import java.util.Collections; 124import java.util.Comparator; 125import java.util.Date; 126import java.util.HashMap; 127import java.util.HashSet; 128import java.util.Iterator; 129import java.util.List; 130import java.util.Locale; 131import java.util.Map; 132import java.util.Map.Entry; 133import java.util.Set; 134import java.util.TreeMap; 135import java.util.TreeSet; 136import java.util.function.Predicate; 137 138import javax.servlet.http.HttpServletRequest; 139import javax.servlet.http.HttpSession; 140 141import org.apache.commons.logging.Log; 142 143import com.google.common.collect.ArrayListMultimap; 144import com.google.common.collect.ComparisonChain; 145import com.google.common.collect.Lists; 146import com.google.common.collect.Maps; 147import com.google.common.collect.Multimap; 148import com.google.common.collect.Sets; 149 150/** 151 * Handles all RPC services related to the gallery dialog.<p> 152 * 153 * @since 8.0.0 154 * 155 * @see org.opencms.ade.galleries.CmsGalleryService 156 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService 157 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryServiceAsync 158 */ 159public class CmsGalleryService extends CmsGwtService implements I_CmsGalleryService { 160 161 /** 162 * Gallery info object.<p> 163 */ 164 protected class CmsGalleryTypeInfo { 165 166 /** The content types using this gallery. */ 167 private List<I_CmsResourceType> m_contentTypes; 168 169 /** The gallery folder resources. */ 170 private List<CmsResource> m_galleries; 171 172 /** The resource type of this gallery. */ 173 private I_CmsResourceType m_resourceType; 174 175 /** 176 * Constructor.<p> 177 * 178 * @param resourceType the resource type of the gallery 179 * @param contentType the resource type of the gallery content 180 * @param galleries the gallery resources 181 */ 182 protected CmsGalleryTypeInfo( 183 I_CmsResourceType resourceType, 184 I_CmsResourceType contentType, 185 List<CmsResource> galleries) { 186 187 m_resourceType = resourceType; 188 m_contentTypes = new ArrayList<I_CmsResourceType>(); 189 m_contentTypes.add(contentType); 190 m_galleries = galleries; 191 } 192 193 /** 194 * Adds a type to the list of content types.<p> 195 * 196 * @param type the type to add 197 */ 198 protected void addContentType(I_CmsResourceType type) { 199 200 m_contentTypes.add(type); 201 } 202 203 /** 204 * Returns the contentTypes.<p> 205 * 206 * @return the contentTypes 207 */ 208 protected List<I_CmsResourceType> getContentTypes() { 209 210 return m_contentTypes; 211 } 212 213 /** 214 * Returns the gallery folder resources.<p> 215 * 216 * @return the resources 217 */ 218 protected List<CmsResource> getGalleries() { 219 220 return m_galleries; 221 } 222 223 /** 224 * Returns the resourceType.<p> 225 * 226 * @return the resourceType 227 */ 228 protected I_CmsResourceType getResourceType() { 229 230 return m_resourceType; 231 } 232 233 /** 234 * Sets the contentTypes.<p> 235 * 236 * @param contentTypes the contentTypes to set 237 */ 238 protected void setContentTypes(List<I_CmsResourceType> contentTypes) { 239 240 m_contentTypes = contentTypes; 241 } 242 243 /** 244 * Sets the galleries.<p> 245 * 246 * @param galleries the gallery resource list to set 247 */ 248 protected void setGalleries(List<CmsResource> galleries) { 249 250 m_galleries = galleries; 251 } 252 253 /** 254 * Sets the resourceType.<p> 255 * 256 * @param resourceType the resourceType to set 257 */ 258 protected void setResourceType(I_CmsResourceType resourceType) { 259 260 m_resourceType = resourceType; 261 } 262 } 263 264 /** Bean used to store a single type together with a flag indicating its visibility. */ 265 class TypeWithVisibility { 266 267 /** True if the type should only be shown in the full list. */ 268 private boolean m_onlyShowInFullList; 269 270 /** The resource type. */ 271 private I_CmsResourceType m_type; 272 273 /** 274 * Creates a new instance.<p> 275 * 276 * @param type the resource type 277 * @param onlyShowInFullList the flag to control the visibility 278 */ 279 public TypeWithVisibility(I_CmsResourceType type, boolean onlyShowInFullList) { 280 281 m_type = type; 282 m_onlyShowInFullList = onlyShowInFullList; 283 } 284 285 /** 286 * Returns the type.<p> 287 * 288 * @return the type 289 */ 290 public I_CmsResourceType getType() { 291 292 return m_type; 293 } 294 295 /** 296 * Returns the onlyShowInFullList.<p> 297 * 298 * @return the onlyShowInFullList 299 */ 300 public boolean isOnlyShowInFullList() { 301 302 return m_onlyShowInFullList; 303 } 304 305 } 306 307 /** Key for additional info gallery folder filter. */ 308 public static final String FOLDER_FILTER_ADD_INFO_KEY = "gallery_folder_filter"; 309 310 /** Limit to the number results loaded on initial search. */ 311 public static final int INITIAL_SEARCH_MAX_RESULTS = 200; 312 313 /** The key used for storing the last used gallery in adeview mode. */ 314 public static final String KEY_LAST_USED_GALLERY_ADEVIEW = "__adeView"; 315 316 /** Name for the 'galleryShowInvalidDefault' preference. */ 317 public static final String PREF_GALLERY_SHOW_INVALID_DEFAULT = "galleryShowInvalidDefault"; 318 319 /** Storage key for the last gallery sort order used in the content editor and ADE image gallery button. */ 320 public static final String RESULT_ORDER_KEY_EDITOR = "editor"; 321 322 /** Storage key for the last gallery sort order in other contexts. */ 323 public static final String RESULT_ORDER_KEY_OTHER = "other"; 324 325 /** Storage key for the last gallery sort order used in the 'magic wand'/new element dialog. */ 326 public static final String RESULT_ORDER_KEY_PAGE = "page"; 327 328 /** Key for additional info gallery result view type. */ 329 public static final String RESULT_VIEW_TYPE_ADD_INFO_KEY = "gallery_result_view_type"; 330 331 /** The dynamic function resource type names. */ 332 private static final Set<String> FUNCTION_TYPES = new HashSet<>( 333 Arrays.asList( 334 new String[] {CmsXmlDynamicFunctionHandler.TYPE_FUNCTION, CmsResourceTypeFunctionConfig.TYPE_NAME})); 335 336 /** The logger instance for this class. */ 337 private static final Log LOG = CmsLog.getLog(CmsGalleryService.class); 338 339 /** Serialization uid. */ 340 private static final long serialVersionUID = 1673026761080584889L; 341 342 /** Compares the VFS entry beans. */ 343 private static final Comparator<CmsVfsEntryBean> VFS_COMPARATOR = new Comparator<CmsVfsEntryBean>() { 344 345 public int compare(CmsVfsEntryBean o1, CmsVfsEntryBean o2) { 346 347 String o1Path = o1.getRootPath(); 348 String o2Path = o2.getRootPath(); 349 if (o1Path.endsWith("/")) { 350 o1Path = o1Path.substring(0, o1Path.length() - 1); 351 } 352 if (o2Path.endsWith("/")) { 353 o2Path = o2Path.substring(0, o2Path.length() - 1); 354 } 355 return o1Path.compareTo(o2Path); 356 } 357 }; 358 359 /** The instance of the resource manager. */ 360 CmsResourceManager m_resourceManager; 361 362 /** The workplace settings of the current user. */ 363 private CmsWorkplaceSettings m_workplaceSettings; 364 365 /** The workplace locale from the current user's settings. */ 366 private Locale m_wpLocale; 367 368 /** 369 * Converts the gallery mode to the key used for storing the last used search order 370 * 371 * @param mode the gallery mode 372 * @return the key to use for storing the last used search order 373 */ 374 public static String convertModeToResultOrderKey(GalleryMode mode) { 375 376 String key = null; 377 switch (mode) { 378 case ade: 379 key = RESULT_ORDER_KEY_PAGE; 380 break; 381 case adeView: 382 case view: 383 key = RESULT_ORDER_KEY_OTHER; 384 break; 385 default: 386 return null; 387 388 } 389 return key; 390 391 } 392 393 /** 394 * Generates the pre-loaded contents for the VFS tab of the gallery dialog.<p> 395 * 396 * @param cms the current CMS context 397 * @param vfsState the saved VFS tree state (may be null) 398 * @param folders the saved search folders (may be null) 399 * 400 * @return the root tree entry for the VFS tab 401 */ 402 public static CmsVfsEntryBean generateVfsPreloadData( 403 final CmsObject cms, 404 final CmsTreeOpenState vfsState, 405 final Set<String> folders) { 406 407 CmsVfsEntryBean vfsPreloadData = null; 408 409 A_CmsTreeTabDataPreloader<CmsVfsEntryBean> vfsloader = new A_CmsTreeTabDataPreloader<CmsVfsEntryBean>() { 410 411 @SuppressWarnings("synthetic-access") 412 @Override 413 protected CmsVfsEntryBean createEntry(CmsObject innerCms, CmsResource resource) throws CmsException { 414 415 String title = innerCms.readPropertyObject( 416 resource, 417 CmsPropertyDefinition.PROPERTY_TITLE, 418 false).getValue(); 419 boolean isEditable = false; 420 try { 421 isEditable = innerCms.hasPermissions( 422 resource, 423 CmsPermissionSet.ACCESS_WRITE, 424 false, 425 CmsResourceFilter.ALL); 426 } catch (CmsException e) { 427 LOG.info(e.getLocalizedMessage(), e); 428 } 429 430 return internalCreateVfsEntryBean(innerCms, resource, title, true, isEditable, null, false); 431 } 432 433 }; 434 Set<CmsResource> treeOpenResources = Sets.newHashSet(); 435 if (vfsState != null) { 436 437 for (CmsUUID structureId : vfsState.getOpenItems()) { 438 try { 439 treeOpenResources.add(cms.readResource(structureId, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)); 440 } catch (CmsException e) { 441 LOG.warn(e.getLocalizedMessage(), e); 442 } 443 } 444 } 445 CmsObject rootCms = null; 446 Set<CmsResource> folderSetResources = Sets.newHashSet(); 447 try { 448 rootCms = OpenCms.initCmsObject(cms); 449 rootCms.getRequestContext().setSiteRoot(""); 450 if (!((folders == null) || folders.isEmpty())) { 451 for (String folder : folders) { 452 try { 453 folderSetResources.add(rootCms.readResource(folder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)); 454 } catch (CmsException e) { 455 LOG.warn(e.getLocalizedMessage(), e); 456 } 457 } 458 } 459 } catch (CmsException e1) { 460 LOG.error(e1.getLocalizedMessage(), e1); 461 } 462 try { 463 vfsPreloadData = vfsloader.preloadData(cms, treeOpenResources, folderSetResources); 464 } catch (CmsException e) { 465 LOG.error(e.getLocalizedMessage(), e); 466 } 467 468 return vfsPreloadData; 469 470 } 471 472 /** 473 * Returns the initial gallery settings.<p> 474 * 475 * @param request the current request 476 * @param config the gallery configuration 477 * 478 * @return the initial gallery settings 479 * 480 * @throws CmsRpcException if something goes wrong 481 */ 482 public static CmsGalleryDataBean getInitialSettings(HttpServletRequest request, CmsGalleryConfiguration config) 483 throws CmsRpcException { 484 485 CmsGalleryService srv = new CmsGalleryService(); 486 srv.setCms(CmsFlexController.getCmsObject(request)); 487 srv.setRequest(request); 488 CmsGalleryDataBean result = null; 489 try { 490 result = srv.getInitialSettings(config); 491 } finally { 492 srv.clearThreadStorage(); 493 } 494 return result; 495 } 496 497 /** 498 * Returns the initial search data.<p> 499 * 500 * @param request the current request 501 * @param config the gallery configuration 502 * 503 * @return the search data 504 */ 505 public static CmsGallerySearchBean getSearch(HttpServletRequest request, CmsGalleryDataBean config) { 506 507 CmsGalleryService srv = new CmsGalleryService(); 508 srv.setCms(CmsFlexController.getCmsObject(request)); 509 srv.setRequest(request); 510 CmsGallerySearchBean result = null; 511 try { 512 result = srv.getSearch(config); 513 } finally { 514 srv.clearThreadStorage(); 515 } 516 return result; 517 } 518 519 /** 520 * Gets the attribute name for a tree open state.<p> 521 * 522 * @param treeName the tree name 523 * @param treeToken the tree token 524 * 525 * @return the attribute name for the tree 526 */ 527 public static String getTreeOpenStateAttributeName(String treeName, String treeToken) { 528 529 return "tree_" + treeName + "_" + treeToken; 530 } 531 532 /** 533 * Convenience method for reading the saved VFS tree state from the session.<p> 534 * 535 * @param request the current request 536 * @param treeToken the tree token (may be null) 537 * 538 * @return the saved tree open state (may be null) 539 */ 540 public static CmsTreeOpenState getVfsTreeState(HttpServletRequest request, String treeToken) { 541 542 return (CmsTreeOpenState)request.getSession().getAttribute( 543 getTreeOpenStateAttributeName(I_CmsGalleryProviderConstants.TREE_VFS, treeToken)); 544 545 } 546 547 /** 548 * Creates the VFS entry bean for a resource.<p> 549 * 550 * @param cms the CMS context to use 551 * @param resource the resource for which to create the VFS entry bean 552 * @param title the title 553 * @param isRoot true if this is a root entry 554 * @param isEditable true if this entry is editable 555 * @param children the children of the entry 556 * @param isMatch true if the VFS entry bean is a match for the quick search 557 * 558 * @return the created VFS entry bean 559 * @throws CmsException if something goes wrong 560 */ 561 public static CmsVfsEntryBean internalCreateVfsEntryBean( 562 CmsObject cms, 563 CmsResource resource, 564 String title, 565 boolean isRoot, 566 boolean isEditable, 567 List<CmsVfsEntryBean> children, 568 boolean isMatch) 569 throws CmsException { 570 571 String rootPath = resource.getRootPath(); 572 CmsUUID structureId = resource.getStructureId(); 573 CmsVfsEntryBean result = new CmsVfsEntryBean( 574 rootPath, 575 structureId, 576 title, 577 CmsIconUtil.getIconClasses(CmsIconUtil.getDisplayType(cms, resource), resource.getName(), true), 578 isRoot, 579 isEditable, 580 children, 581 isMatch); 582 String siteRoot = null; 583 if (resource.isFolder()) { 584 cms = OpenCms.initCmsObject(cms); 585 cms.getRequestContext().setSiteRoot(""); 586 List<CmsResource> realChildren = cms.getResourcesInFolder( 587 rootPath, 588 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 589 List<CmsResource> effectiveChildren = new ArrayList<CmsResource>(); 590 for (CmsResource realChild : realChildren) { 591 if (realChild.isFolder()) { 592 effectiveChildren.add(realChild); 593 } 594 } 595 if (effectiveChildren.isEmpty()) { 596 result.setChildren(new ArrayList<CmsVfsEntryBean>()); 597 } 598 } 599 600 if (OpenCms.getSiteManager().startsWithShared(rootPath)) { 601 siteRoot = OpenCms.getSiteManager().getSharedFolder(); 602 } else { 603 String tempSiteRoot = OpenCms.getSiteManager().getSiteRoot(rootPath); 604 if (tempSiteRoot != null) { 605 siteRoot = tempSiteRoot; 606 } else { 607 siteRoot = ""; 608 } 609 } 610 result.setSiteRoot(siteRoot); 611 return result; 612 } 613 614 /** 615 * Helper function for getting the IDs of functions which do not fit into a given set of container type/width combinations. 616 * 617 * @param cms the current CMS context 618 * @param config the sitemap configuration 619 * @param containerInfo the information about available container type/width combinations 620 * 621 * @return the set of functions which should be excluded 622 */ 623 private static Set<CmsUUID> getExcludedFunctionsForContainerInfo( 624 CmsObject cms, 625 CmsADEConfigData config, 626 CmsGalleryContainerInfo containerInfo) { 627 628 CmsFormatterConfigurationCacheState formatterCache = config.getCachedFormatters(); 629 // start with all functions, then go through each item in the container info and remove formatters if they match that item 630 // -> we end up with the functions that don't match anything 631 Map<CmsUUID, I_CmsFormatterBean> remainingUnmatchedFunctions = new HashMap<>( 632 Maps.filterValues( 633 formatterCache.getFormatters(), 634 formatter -> formatter instanceof CmsFunctionFormatterBean)); 635 for (CmsGalleryContainerInfo.Item item : containerInfo.getItems()) { 636 Iterator<Map.Entry<CmsUUID, I_CmsFormatterBean>> iterator = remainingUnmatchedFunctions.entrySet().iterator(); 637 while (iterator.hasNext()) { 638 Map.Entry<CmsUUID, I_CmsFormatterBean> entry = iterator.next(); 639 I_CmsFormatterBean formatter = entry.getValue(); 640 if (CmsFormatterConfiguration.matchFormatter(formatter, item.getType(), item.getWidth())) { 641 iterator.remove(); 642 } 643 } 644 } 645 return new TreeSet<>(remainingUnmatchedFunctions.keySet()); 646 } 647 648 /** 649 * Returns the resource types beans.<p> 650 * 651 * @param resourceTypes the resource types 652 * @param creatableTypes the creatable types 653 * @param deactivatedTypes the deactivated types 654 * @param typesForTypeTab the types which should be shown in the types tab according to the gallery configuration 655 * 656 * @return the resource types 657 */ 658 public List<CmsResourceTypeBean> buildTypesList( 659 List<I_CmsResourceType> resourceTypes, 660 Set<String> creatableTypes, 661 Set<String> deactivatedTypes, 662 final List<String> typesForTypeTab) { 663 664 List<CmsResourceTypeBean> result = buildTypesList(resourceTypes, creatableTypes); 665 666 for (CmsResourceTypeBean typeBean : result) { 667 if ((typesForTypeTab != null) && (typesForTypeTab.size() > 0)) { 668 if (!typesForTypeTab.contains(typeBean.getType())) { 669 if (typeBean.getVisibility() != TypeVisibility.hidden) { 670 typeBean.setVisibility(TypeVisibility.showOptional); 671 } 672 } 673 } 674 typeBean.setDeactivated(deactivatedTypes.contains(typeBean.getType())); 675 } 676 if ((typesForTypeTab != null) && (typesForTypeTab.size() > 0)) { 677 Collections.sort(result, new Comparator<CmsResourceTypeBean>() { 678 679 public int compare(CmsResourceTypeBean first, CmsResourceTypeBean second) { 680 681 return ComparisonChain.start().compare(searchTypeRank(first), searchTypeRank(second)).compare( 682 first.getTitle(), 683 second.getTitle(), 684 Collator.getInstance(getWorkplaceLocale())).compare(first.getType(), second.getType()).result(); 685 } 686 687 int searchTypeRank(CmsResourceTypeBean type) { 688 689 int index = typesForTypeTab.indexOf(type.getType()); 690 if (index == -1) { 691 return Integer.MAX_VALUE; 692 } else { 693 return index; 694 } 695 } 696 }); 697 698 } 699 return result; 700 } 701 702 /** 703 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#deleteResource(java.lang.String) 704 */ 705 public void deleteResource(String resourcePath) throws CmsRpcException { 706 707 try { 708 ensureLock(resourcePath); 709 getCmsObject().deleteResource(resourcePath, CmsResource.DELETE_PRESERVE_SIBLINGS); 710 } catch (Exception e) { 711 error(e); 712 } 713 } 714 715 /** 716 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getAdeViewModeConfiguration() 717 */ 718 public CmsGalleryConfiguration getAdeViewModeConfiguration() { 719 720 CmsGalleryConfiguration result = new CmsGalleryConfiguration(); 721 List<String> typeNames = new ArrayList<String>(); 722 723 for (I_CmsResourceType type : OpenCms.getResourceManager().getResourceTypes()) { 724 Class<?> typeClass = type.getClass(); 725 if (CmsResourceTypeXmlContent.class.isAssignableFrom(typeClass) 726 || CmsResourceTypeXmlPage.class.isAssignableFrom(typeClass)) { 727 continue; 728 } 729 if (type.getGalleryTypes().size() > 0) { 730 typeNames.add(type.getTypeName()); 731 } 732 } 733 result.setSearchTypes(typeNames); 734 result.setResourceTypes(typeNames); 735 result.setGalleryMode(GalleryMode.adeView); 736 result.setGalleryStoragePrefix("" + GalleryMode.adeView); 737 result.setTabConfiguration(CmsGalleryTabConfiguration.resolve("selectDoc")); 738 return result; 739 } 740 741 /** 742 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getGalleries(java.lang.String, java.util.List) 743 */ 744 public List<CmsGalleryFolderBean> getGalleries(String context, List<String> resourceTypes) { 745 746 return buildGalleriesList(context, readGalleryInfosByTypeNames(resourceTypes)); 747 } 748 749 /** 750 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getGalleryActionInfo(java.lang.String) 751 */ 752 public CmsGalleryActionInfo getGalleryActionInfo(String sitePath) throws CmsRpcException { 753 754 try { 755 CmsObject cms = getCmsObject(); 756 try { 757 CmsResource folderRes = cms.readResource(sitePath, CmsResourceFilter.IGNORE_EXPIRATION); 758 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(folderRes); 759 String action = type.getConfiguration().get("gallery.upload.action"); 760 return new CmsGalleryActionInfo(folderRes.getStructureId(), action); 761 } catch (CmsVfsResourceNotFoundException e) { 762 LOG.info(e.getLocalizedMessage(), e); 763 return null; 764 } 765 } catch (Throwable e) { 766 error(e); 767 return null; 768 } 769 770 } 771 772 /** 773 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getInfoForResource(java.lang.String, java.lang.String) 774 */ 775 public CmsResultItemBean getInfoForResource(String linkPath, String locale) throws CmsRpcException { 776 777 CmsResultItemBean result = null; 778 CmsObject cms = getCmsObject(); 779 CmsMessages messageBundle = Messages.get().getBundle(getWorkplaceLocale()); 780 try { 781 if (new CmsUriSplitter(linkPath).getProtocol() != null) { 782 result = new CmsResultItemBean(); 783 result.setTitle(messageBundle.key(Messages.GUI_EXTERNAL_LINK_0)); 784 result.setSubTitle(""); 785 result.setType(CmsResourceTypePointer.getStaticTypeName()); 786 result.setBigIconClasses( 787 CmsIconUtil.getIconClasses(CmsResourceTypePointer.getStaticTypeName(), null, false)); 788 } else if (CmsStaticResourceHandler.isStaticResourceUri(linkPath)) { 789 result = new CmsResultItemBean(); 790 result.setTitle(messageBundle.key(Messages.GUI_STATIC_RESOURCE_0)); 791 result.setSubTitle(CmsStaticResourceHandler.removeStaticResourcePrefix(linkPath)); 792 result.setType(CmsResourceTypeBinary.getStaticTypeName()); 793 result.setBigIconClasses( 794 CmsIconUtil.getIconClasses(CmsResourceTypeBinary.getStaticTypeName(), null, false)); 795 } else { 796 boolean notFound = false; 797 String path = linkPath; 798 String siteRoot = OpenCms.getSiteManager().getSiteRoot(linkPath); 799 String oldSite = cms.getRequestContext().getSiteRoot(); 800 try { 801 if (siteRoot != null) { 802 // only switch the site if needed 803 cms.getRequestContext().setSiteRoot(siteRoot); 804 // remove the site root, because the link manager call will append it anyway 805 path = cms.getRequestContext().removeSiteRoot(linkPath); 806 } 807 // remove parameters, if not the link manager call might fail 808 int pos = path.indexOf(CmsRequestUtil.URL_DELIMITER); 809 int anchorPos = path.indexOf('#'); 810 if ((pos == -1) || ((anchorPos > -1) && (pos > anchorPos))) { 811 pos = anchorPos; 812 } 813 if (pos > -1) { 814 path = path.substring(0, pos); 815 } 816 // get the root path 817 path = OpenCms.getLinkManager().getRootPath(cms, path); 818 819 } catch (Exception e) { 820 notFound = true; 821 } finally { 822 if (siteRoot != null) { 823 cms.getRequestContext().setSiteRoot(oldSite); 824 } 825 } 826 notFound = notFound || (path == null); 827 boolean isInTimeRange = true; 828 if (!notFound) { 829 CmsObject rootCms = OpenCms.initCmsObject(cms); 830 rootCms.getRequestContext().setSiteRoot(""); 831 try { 832 CmsResource selectedResource = rootCms.readResource(path, CmsResourceFilter.IGNORE_EXPIRATION); 833 long currentTime = System.currentTimeMillis(); 834 isInTimeRange = selectedResource.isReleasedAndNotExpired(currentTime); 835 if (selectedResource.isFolder()) { 836 result = new CmsResultItemBean(); 837 838 CmsJspNavElement folderNav = new CmsJspNavBuilder(rootCms).getNavigationForResource( 839 selectedResource.getRootPath(), 840 CmsResourceFilter.IGNORE_EXPIRATION); 841 CmsResource defaultFileResource = null; 842 if (folderNav.isInNavigation() && !folderNav.isNavigationLevel()) { 843 try { 844 defaultFileResource = rootCms.readDefaultFile( 845 selectedResource, 846 CmsResourceFilter.ONLY_VISIBLE); 847 } catch (Exception e) { 848 log(e.getMessage(), e); 849 } 850 } 851 result.setBigIconClasses( 852 CmsIconUtil.getIconClasses( 853 CmsIconUtil.getDisplayType(rootCms, selectedResource), 854 path, 855 false)); 856 CmsResource resourceForType = defaultFileResource != null 857 ? defaultFileResource 858 : selectedResource; 859 result.setType(OpenCms.getResourceManager().getResourceType(resourceForType).getTypeName()); 860 if (defaultFileResource != null) { 861 result.setSmallIconClasses( 862 CmsIconUtil.getIconClasses( 863 CmsIconUtil.getDisplayType(rootCms, defaultFileResource), 864 defaultFileResource.getName(), 865 true)); 866 } 867 String title = folderNav.getProperty(CmsPropertyDefinition.PROPERTY_NAVTEXT); 868 if (CmsStringUtil.isEmptyOrWhitespaceOnly(title)) { 869 title = folderNav.getTitle(); 870 } else if (CmsStringUtil.isEmptyOrWhitespaceOnly(title)) { 871 title = CmsResource.getName(path); 872 if (title.contains("/")) { 873 title = title.substring(0, title.indexOf("/")); 874 } 875 } 876 result.setTitle(title); 877 try { 878 String userName = cms.readUser(selectedResource.getUserLastModified()).getFullName(); 879 result.setUserLastModified(userName); 880 } catch (CmsException e) { 881 log(e.getMessage(), e); 882 } 883 Date date = new Date(selectedResource.getDateLastModified()); 884 String formattedDate = CmsDateUtil.getDateTime( 885 date, 886 DateFormat.MEDIUM, 887 getWorkplaceLocale()); 888 result.setDateLastModified(formattedDate); 889 890 } else { 891 CmsGallerySearchResult resultItem = null; 892 try { 893 resultItem = CmsGallerySearch.searchByPath( 894 cms, 895 path, 896 CmsLocaleManager.getLocale(locale)); 897 } catch (CmsVfsResourceNotFoundException ex) { 898 // ignore 899 } 900 notFound = resultItem == null; 901 if (!notFound) { 902 result = buildSingleSearchResultItem(getCmsObject(), resultItem, null, res -> false); 903 } 904 } 905 } catch (CmsException ex) { 906 notFound = true; 907 } 908 } 909 if (notFound) { 910 result = new CmsResultItemBean(); 911 result.setTitle(messageBundle.key(Messages.GUI_RESOURCE_NOT_FOUND_0)); 912 result.setSubTitle(""); 913 result.setType(CmsIconUtil.TYPE_RESOURCE_NOT_FOUND); 914 result.setBigIconClasses( 915 CmsIconUtil.getIconClasses(CmsIconUtil.TYPE_RESOURCE_NOT_FOUND, null, false)); 916 } else if (!isInTimeRange && (result != null)) { 917 result.setType(CmsIconUtil.TYPE_RESOURCE_NOT_FOUND); 918 result.setTitle(messageBundle.key(Messages.GUI_RESOURCE_OUT_OF_TIME_RANGE_1, result.getTitle())); 919 result.setBigIconClasses( 920 CmsIconUtil.getIconClasses(CmsIconUtil.TYPE_RESOURCE_NOT_FOUND, null, false)); 921 } 922 } 923 } catch (Throwable t) { 924 error(t); 925 } 926 return result; 927 } 928 929 /** 930 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getInitialSettings(org.opencms.ade.galleries.shared.CmsGalleryConfiguration) 931 */ 932 public CmsGalleryDataBean getInitialSettings(CmsGalleryConfiguration conf) throws CmsRpcException { 933 934 try { 935 return getInitialSettingsInternal(conf); 936 } catch (Throwable t) { 937 error(t); 938 return null; // will never be reached 939 } 940 } 941 942 /** 943 * Returns the initial gallery data for the container page editor.<p> 944 * 945 * @param types the available resource types 946 * @param uri the page URI 947 * @param locale the content locale 948 * 949 * @return the gallery data 950 */ 951 public CmsGalleryDataBean getInitialSettingsForContainerPage( 952 List<CmsResourceTypeBean> types, 953 String uri, 954 String locale) { 955 956 CmsGalleryDataBean data = null; 957 try { 958 data = new CmsGalleryDataBean(); 959 boolean galleryShowInvalidDefault = Boolean.parseBoolean( 960 getWorkplaceSettings().getUserSettings().getAdditionalPreference( 961 PREF_GALLERY_SHOW_INVALID_DEFAULT, 962 true)); 963 data.setIncludeExpiredDefault(galleryShowInvalidDefault); 964 data.setResultViewType(readResultViewType()); 965 data.setMode(GalleryMode.ade); 966 data.setGalleryStoragePrefix(""); 967 data.setLocales(buildLocalesMap()); 968 data.setLocale(locale); 969 970 data.setVfsRootFolders(getRootEntries()); 971 972 data.setScope(getWorkplaceSettings().getLastSearchScope()); 973 data.setSortOrder( 974 getWorkplaceSettings().getLastGalleryResultOrder(CmsGalleryService.RESULT_ORDER_KEY_PAGE)); 975 976 data.setTabIds(GalleryMode.ade.getTabs()); 977 data.setReferenceSitePath(uri); 978 data.setTypes(types); 979 Map<String, CmsGalleryTypeInfo> adeGalleryTypeInfos = readGalleryInfosByTypeBeans(types); 980 data.setGalleries(buildGalleriesList(uri, adeGalleryTypeInfos)); 981 data.setStartTab(GalleryTabId.cms_tab_types); 982 Set<String> folderFilter = readFolderFilters(); 983 data.setStartFolderFilter(folderFilter); 984 if ((folderFilter != null) && !folderFilter.isEmpty()) { 985 try { 986 data.setVfsPreloadData(generateVfsPreloadData(getCmsObject(), null, folderFilter)); 987 } catch (Exception e) { 988 LOG.error(e.getLocalizedMessage(), e); 989 } 990 } 991 CmsSiteSelectorOptionBuilder optionBuilder = new CmsSiteSelectorOptionBuilder(getCmsObject()); 992 optionBuilder.addNormalSites(true, getWorkplaceSettings().getUserSettings().getStartFolder()); 993 optionBuilder.addSharedSite(); 994 data.setVfsSiteSelectorOptions(optionBuilder.getOptions()); 995 996 CmsSiteSelectorOptionBuilder sitemapOptionBuilder = new CmsSiteSelectorOptionBuilder(getCmsObject()); 997 sitemapOptionBuilder.addNormalSites(false, null); 998 if (data.getReferenceSitePath() != null) { 999 sitemapOptionBuilder.addCurrentSubsite(getCmsObject().addSiteRoot(data.getReferenceSitePath())); 1000 } 1001 data.setSitemapSiteSelectorOptions(sitemapOptionBuilder.getOptions()); 1002 data.setDefaultScope(OpenCms.getWorkplaceManager().getGalleryDefaultScope()); 1003 CmsCoreService service = new CmsCoreService(); 1004 service.setCms(getCmsObject()); 1005 data.setCategories(service.getCategoriesForSitePath(data.getReferenceSitePath())); 1006 } catch (Exception e) { 1007 LOG.error(e.getLocalizedMessage(), e); 1008 } 1009 return data; 1010 } 1011 1012 /** 1013 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getSearch(org.opencms.ade.galleries.shared.CmsGalleryDataBean) 1014 */ 1015 public CmsGallerySearchBean getSearch(CmsGalleryDataBean data) { 1016 1017 CmsGallerySearchBean result = null; 1018 // search within all available types 1019 List<String> types = getTypeNames(data); 1020 switch (data.getMode()) { 1021 case editor: 1022 case view: 1023 case adeView: 1024 case widget: 1025 String currentelement = data.getCurrentElement(); 1026 try { 1027 CmsSitemapEntryBean sitemapPreloadData = null; 1028 CmsVfsEntryBean vfsPreloadData = null; 1029 boolean disablePreview = false; 1030 GalleryTabId startTab = null; 1031 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(currentelement)) { 1032 log("looking up:" + currentelement); 1033 // removing the servlet context if present 1034 currentelement = CmsLinkManager.removeOpenCmsContext(currentelement); 1035 // get search results given resource path 1036 result = findResourceInGallery(currentelement, data); 1037 if (result != null) { 1038 sitemapPreloadData = result.getSitemapPreloadData(); 1039 vfsPreloadData = result.getVfsPreloadData(); 1040 } 1041 if ((sitemapPreloadData != null) 1042 && data.getTabConfiguration().getTabs().contains(GalleryTabId.cms_tab_sitemap)) { 1043 startTab = GalleryTabId.cms_tab_sitemap; 1044 disablePreview = true; 1045 } 1046 } else { 1047 CmsTreeOpenState sitemapState = getSitemapTreeState(data.getTreeToken()); 1048 if (sitemapState != null) { 1049 A_CmsTreeTabDataPreloader<CmsSitemapEntryBean> sitemaploader = new A_CmsTreeTabDataPreloader<CmsSitemapEntryBean>() { 1050 1051 @Override 1052 protected CmsSitemapEntryBean createEntry(CmsObject cms, CmsResource resource) 1053 throws CmsException { 1054 1055 return internalCreateSitemapEntryBean(cms, resource); 1056 } 1057 1058 /** 1059 * @see org.opencms.ade.galleries.A_CmsTreeTabDataPreloader#getChildren(org.opencms.file.CmsResource) 1060 */ 1061 @Override 1062 protected List<CmsResource> getChildren(CmsResource resource) throws CmsException { 1063 1064 return getSitemapSubEntryResources(resource.getRootPath()); 1065 } 1066 1067 }; 1068 // in the case 1069 sitemapPreloadData = sitemaploader.preloadData( 1070 getCmsObject(), 1071 Sets.newHashSet( 1072 readAll(sitemapState.getOpenItems(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)), 1073 null); 1074 } 1075 } 1076 if ((result == null) || (result.getResults() == null) || result.getResults().isEmpty()) { 1077 result = new CmsGallerySearchBean(); 1078 result.setOriginalGalleryData(data); 1079 result.setGalleryMode(data.getMode()); 1080 result.setGalleryStoragePrefix(data.getGalleryStoragePrefix()); 1081 result.setIgnoreSearchExclude(true); 1082 String gallery = data.getStartGallery(); 1083 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(gallery)) { 1084 List<String> galleries = new ArrayList<String>(); 1085 galleries.add(gallery); 1086 result.setGalleries(galleries); 1087 } 1088 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(data.getStartFolder())) { 1089 Set<String> folders = new HashSet<String>(); 1090 folders.add(data.getStartFolder()); 1091 result.setFolders(folders); 1092 } else if (data.getStartFolderFilter() != null) { 1093 result.setFolders(data.getStartFolderFilter()); 1094 } 1095 result.setTypes(types); 1096 result.setLocale(data.getLocale()); 1097 CmsGallerySearchScope scope = data.getScope(); 1098 if (scope == null) { 1099 scope = OpenCms.getWorkplaceManager().getGalleryDefaultScope(); 1100 } 1101 result.setSortOrder(data.getSortOrder().name()); 1102 result.setScope(scope); 1103 result.setIncludeExpired(data.getIncludeExpiredDefault()); 1104 result = search(result); 1105 } 1106 result.setSitemapPreloadData(sitemapPreloadData); 1107 result.setVfsPreloadData(vfsPreloadData); 1108 result.setInitialTabId(startTab); 1109 result.setDisablePreview(disablePreview); 1110 if (types.size() > 1) { 1111 // only remove types parameter if there is more than one type available 1112 result.setTypes(null); 1113 } 1114 } catch (CmsException e) { 1115 logError(e); 1116 result = null; 1117 } 1118 break; 1119 case ade: 1120 default: 1121 break; 1122 } 1123 return result; 1124 } 1125 1126 /** 1127 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getSearch(CmsGallerySearchBean) 1128 */ 1129 public CmsGallerySearchBean getSearch(CmsGallerySearchBean searchObj) throws CmsRpcException { 1130 1131 CmsGallerySearchBean gSearchObj = null; 1132 1133 try { 1134 gSearchObj = search(searchObj); 1135 getWorkplaceSettings().setLastSearchScope(searchObj.getScope()); 1136 String resultOrderKey = convertModeToResultOrderKey(searchObj.getGalleryMode()); 1137 getWorkplaceSettings().setLastGalleryResultOrder( 1138 resultOrderKey, 1139 SortParams.valueOf(searchObj.getSortOrder())); 1140 setLastOpenedGallery(searchObj); 1141 } catch (Throwable e) { 1142 error(e); 1143 } 1144 1145 return gSearchObj; 1146 } 1147 1148 /** 1149 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getSubEntries(java.lang.String, boolean, java.lang.String) 1150 */ 1151 public List<CmsSitemapEntryBean> getSubEntries(String rootPath, boolean isRoot, String filter) 1152 throws CmsRpcException { 1153 1154 try { 1155 return getSubEntriesInternal(rootPath, isRoot, filter); 1156 } catch (Throwable e) { 1157 error(e); 1158 } 1159 return null; 1160 } 1161 1162 /** 1163 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getSubFolders(java.lang.String) 1164 */ 1165 public List<CmsVfsEntryBean> getSubFolders(String rootPath) throws CmsRpcException { 1166 1167 try { 1168 CmsObject cms = OpenCms.initCmsObject(getCmsObject()); 1169 cms.getRequestContext().setSiteRoot(""); 1170 List<CmsVfsEntryBean> result = new ArrayList<CmsVfsEntryBean>(); 1171 if (cms.existsResource(rootPath, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 1172 CmsResource resource = cms.readResource(rootPath, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1173 List<CmsResource> resources = cms.getSubFolders( 1174 resource.getRootPath(), 1175 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1176 for (CmsResource res : resources) { 1177 String title = cms.readPropertyObject(res, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue(); 1178 result.add( 1179 internalCreateVfsEntryBean( 1180 getCmsObject(), 1181 res, 1182 title, 1183 false, 1184 isEditable(cms, res), 1185 null, 1186 false)); 1187 } 1188 } 1189 Collections.<CmsVfsEntryBean> sort(result, VFS_COMPARATOR); 1190 return result; 1191 } catch (Throwable e) { 1192 error(e); 1193 } 1194 return null; 1195 } 1196 1197 /** 1198 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#loadVfsEntryBean(java.lang.String, java.lang.String) 1199 */ 1200 public CmsVfsEntryBean loadVfsEntryBean(String path, String filter) throws CmsRpcException { 1201 1202 try { 1203 if (CmsStringUtil.isEmpty(filter)) { 1204 1205 CmsObject cms = OpenCms.initCmsObject(getCmsObject()); 1206 cms.getRequestContext().setSiteRoot(""); 1207 if (!cms.existsResource(path, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 1208 String startFolder = CmsStringUtil.joinPaths( 1209 path, 1210 getWorkplaceSettings().getUserSettings().getStartFolder()); 1211 if (cms.existsResource(startFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 1212 path = startFolder; 1213 } 1214 } 1215 CmsResource optionRes = cms.readResource(path); 1216 String title = cms.readPropertyObject( 1217 optionRes, 1218 CmsPropertyDefinition.PROPERTY_TITLE, 1219 false).getValue(); 1220 if (CmsStringUtil.isEmpty(title)) { 1221 title = path; 1222 } 1223 CmsVfsEntryBean entryBean = internalCreateVfsEntryBean( 1224 getCmsObject(), 1225 optionRes, 1226 title, 1227 true, 1228 isEditable(cms, optionRes), 1229 null, 1230 false); 1231 return entryBean; 1232 } else { 1233 filter = filter.toLowerCase(); 1234 CmsObject cms = OpenCms.initCmsObject(getCmsObject()); 1235 cms.getRequestContext().setSiteRoot(""); 1236 if (!cms.existsResource(path, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 1237 String startFolder = CmsStringUtil.joinPaths( 1238 path, 1239 getWorkplaceSettings().getUserSettings().getStartFolder()); 1240 if (cms.existsResource(startFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 1241 path = startFolder; 1242 } 1243 } 1244 CmsResource optionRes = cms.readResource(path); 1245 List<CmsResource> folders = cms.readResources( 1246 optionRes.getRootPath(), 1247 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireFolder()); 1248 folders.add(optionRes); 1249 Set<CmsResource> folderSet = Sets.newHashSet(folders); 1250 List<CmsResource> titleResources = cms.readResourcesWithProperty( 1251 path, 1252 CmsPropertyDefinition.PROPERTY_TITLE); 1253 titleResources.retainAll(folderSet); 1254 Set<CmsResource> filterMatches = Sets.newHashSet(); 1255 for (CmsResource folder : folderSet) { 1256 if (folder.getName().toLowerCase().contains(filter)) { 1257 filterMatches.add(folder); 1258 titleResources.remove(folder); // we don't need to check the title if the name already matched 1259 } 1260 } 1261 for (CmsResource titleRes : titleResources) { 1262 CmsProperty prop = cms.readPropertyObject(titleRes, CmsPropertyDefinition.PROPERTY_TITLE, false); 1263 String title = prop.getValue(); 1264 if ((title != null) && title.toLowerCase().contains(filter)) { 1265 filterMatches.add(titleRes); 1266 } 1267 } 1268 Set<String> filterMatchAncestorPaths = Sets.newHashSet(); 1269 if (filterMatches.size() > 0) { 1270 for (CmsResource filterMatch : filterMatches) { 1271 String currentPath = filterMatch.getRootPath(); 1272 while (currentPath != null) { 1273 filterMatchAncestorPaths.add(currentPath); 1274 currentPath = CmsResource.getParentFolder(currentPath); 1275 } 1276 } 1277 Set<String> allPaths = Sets.newHashSet(); 1278 Set<String> parentPaths = Sets.newHashSet(); 1279 for (CmsResource folder : folderSet) { 1280 allPaths.add(folder.getRootPath()); 1281 String parent = CmsResource.getParentFolder(folder.getRootPath()); 1282 if (parent != null) { 1283 parentPaths.add(parent); 1284 } 1285 } 1286 parentPaths.retainAll(allPaths); 1287 1288 Set<CmsResource> filterMatchAncestors = Sets.newHashSet(); 1289 for (CmsResource folderRes : folderSet) { 1290 if (filterMatchAncestorPaths.contains(folderRes.getRootPath())) { 1291 filterMatchAncestors.add(folderRes); 1292 } 1293 } 1294 Map<String, CmsResource> resourcesByPath = Maps.newHashMap(); 1295 for (CmsResource treeRes : filterMatchAncestors) { 1296 resourcesByPath.put(treeRes.getRootPath(), treeRes); 1297 } 1298 Multimap<CmsResource, CmsResource> childMap = ArrayListMultimap.create(); 1299 for (CmsResource res : filterMatchAncestors) { 1300 CmsResource parent = resourcesByPath.get(CmsResource.getParentFolder(res.getRootPath())); 1301 if (parent != null) { 1302 childMap.put(parent, res); 1303 } 1304 } 1305 return buildVfsEntryBeanForQuickSearch(optionRes, childMap, filterMatches, parentPaths, true); 1306 } else { 1307 return null; 1308 } 1309 } 1310 } catch (Throwable e) { 1311 error(e); 1312 return null; 1313 } 1314 } 1315 1316 /** 1317 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#saveResultViewType(java.lang.String) 1318 */ 1319 public void saveResultViewType(String resultViewType) { 1320 1321 CmsUser user = getCmsObject().getRequestContext().getCurrentUser(); 1322 user.setAdditionalInfo(RESULT_VIEW_TYPE_ADD_INFO_KEY, resultViewType); 1323 try { 1324 getCmsObject().writeUser(user); 1325 } catch (CmsException e) { 1326 LOG.error(e.getLocalizedMessage(), e); 1327 } 1328 } 1329 1330 /** 1331 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#saveTreeOpenState(java.lang.String, java.lang.String, java.lang.String, java.util.Set) 1332 */ 1333 public void saveTreeOpenState(String treeName, String treeToken, String siteRoot, Set<CmsUUID> openItems) 1334 throws CmsRpcException { 1335 1336 try { 1337 HttpServletRequest request = getRequest(); 1338 HttpSession session = request.getSession(); 1339 String attributeName = getTreeOpenStateAttributeName(treeName, treeToken); 1340 if (openItems.isEmpty()) { 1341 CmsObject cms = OpenCms.initCmsObject(getCmsObject()); 1342 cms.getRequestContext().setSiteRoot(""); 1343 CmsResource resource = cms.readResource(siteRoot); 1344 openItems = Sets.newHashSet(resource.getStructureId()); 1345 } 1346 CmsTreeOpenState treeState = new CmsTreeOpenState(treeName, siteRoot, openItems); 1347 session.setAttribute(attributeName, treeState); 1348 } catch (Throwable e) { 1349 error(e); 1350 } 1351 } 1352 1353 /** 1354 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#updateIndex() 1355 */ 1356 public void updateIndex() throws CmsRpcException { 1357 1358 try { 1359 OpenCms.getSearchManager().updateOfflineIndexes(); 1360 } catch (Throwable e) { 1361 error(e); 1362 } 1363 } 1364 1365 /** 1366 * Gets an initialized CmsObject to be used for the actual search for a given search bean.<p> 1367 * 1368 * @param searchObj the search object 1369 * @return the initialized CmsObject 1370 * 1371 * @throws CmsException if something goes wrong 1372 */ 1373 protected CmsObject getSearchCms(CmsGallerySearchBean searchObj) throws CmsException { 1374 1375 CmsObject searchCms = getCmsObject(); 1376 if (searchObj.isIncludeExpired()) { 1377 searchCms = OpenCms.initCmsObject(getCmsObject()); 1378 searchCms.getRequestContext().setRequestTime(CmsResource.DATE_RELEASED_EXPIRED_IGNORE); 1379 } 1380 return searchCms; 1381 } 1382 1383 /** 1384 * Gets the sitemap sub entries for a given path as resources.<p> 1385 * 1386 * @param rootPath the root path 1387 * @return the sitemap sub entry resources 1388 * @throws CmsException if something goes wrong 1389 */ 1390 protected List<CmsResource> getSitemapSubEntryResources(String rootPath) throws CmsException { 1391 1392 CmsObject rootCms = OpenCms.initCmsObject(getCmsObject()); 1393 List<CmsResource> result = new ArrayList<CmsResource>(); 1394 rootCms.getRequestContext().setSiteRoot(""); 1395 CmsJspNavBuilder navBuilder = new CmsJspNavBuilder(rootCms); 1396 for (CmsJspNavElement navElement : navBuilder.getNavigationForFolder( 1397 rootPath, 1398 Visibility.all, 1399 CmsResourceFilter.ONLY_VISIBLE)) { 1400 if ((navElement != null) && navElement.isInNavigation()) { 1401 result.add(navElement.getResource()); 1402 } 1403 } 1404 return result; 1405 } 1406 1407 /** 1408 * Internal method for getting sitemap sub entries for a given root path.<p> 1409 * 1410 * @param rootPath the root path 1411 * @param isRoot true if this method is used to get the root entries of a sitemap 1412 * @param filter the filter string (only relevant if isRoot is true) 1413 * @return the list of sitemap sub-entry beans 1414 * 1415 * @throws CmsException if something goes wrong 1416 */ 1417 protected List<CmsSitemapEntryBean> getSubEntriesInternal(String rootPath, boolean isRoot, String filter) 1418 throws CmsException { 1419 1420 CmsObject rootCms = OpenCms.initCmsObject(getCmsObject()); 1421 rootCms.getRequestContext().setSiteRoot(""); 1422 CmsJspNavBuilder navBuilder = new CmsJspNavBuilder(rootCms); 1423 if (isRoot) { 1424 if (CmsStringUtil.isEmpty(filter)) { 1425 List<CmsSitemapEntryBean> result = new ArrayList<CmsSitemapEntryBean>(); 1426 for (CmsJspNavElement navElement : navBuilder.getNavigationForFolder( 1427 rootPath, 1428 Visibility.all, 1429 CmsResourceFilter.ONLY_VISIBLE)) { 1430 if ((navElement != null) && navElement.isInNavigation()) { 1431 CmsSitemapEntryBean nextEntry = prepareSitemapEntry(rootCms, navElement, false, true); 1432 result.add(nextEntry); 1433 } 1434 } 1435 CmsJspNavElement navElement = navBuilder.getNavigationForResource( 1436 rootPath, 1437 CmsResourceFilter.ONLY_VISIBLE); 1438 if (navElement == null) { 1439 return result; 1440 } 1441 CmsSitemapEntryBean root = prepareSitemapEntry(rootCms, navElement, isRoot, true); 1442 root.setChildren(result); 1443 return Collections.singletonList(root); 1444 } else { 1445 CmsGalleryFilteredNavTreeBuilder navTreeBuilder = new CmsGalleryFilteredNavTreeBuilder( 1446 rootCms, 1447 rootPath); 1448 navTreeBuilder.initTree(filter); 1449 if (navTreeBuilder.hasMatches()) { 1450 return Lists.newArrayList(convertNavigationTreeToBean(rootCms, navTreeBuilder.getRoot(), true)); 1451 } else { 1452 return Lists.newArrayList(); 1453 } 1454 } 1455 } else { 1456 List<CmsSitemapEntryBean> result = new ArrayList<CmsSitemapEntryBean>(); 1457 for (CmsJspNavElement navElement : navBuilder.getNavigationForFolder( 1458 rootPath, 1459 Visibility.all, 1460 CmsResourceFilter.ONLY_VISIBLE)) { 1461 if ((navElement != null) && navElement.isInNavigation()) { 1462 CmsSitemapEntryBean nextEntry = prepareSitemapEntry(rootCms, navElement, false, true); 1463 result.add(nextEntry); 1464 } 1465 } 1466 return result; 1467 } 1468 } 1469 1470 /** 1471 * Gets the type names from the gallery data bean.<p> 1472 * 1473 * @param data the gallery data bean 1474 * @return the type names 1475 */ 1476 protected List<String> getTypeNames(CmsGalleryDataBean data) { 1477 1478 List<String> types = new ArrayList<String>(); 1479 for (CmsResourceTypeBean info : data.getTypes()) { 1480 types.add(info.getType()); 1481 } 1482 return types; 1483 } 1484 1485 /** 1486 * Checks whether a given resource is a sitemap entry.<p> 1487 * 1488 * This is used for preselected entries in the gallery widget.<p> 1489 * 1490 * 1491 * @param cms the current CMS context 1492 * @param resource the resource to check 1493 * @return true if the resource is a sitemap entry 1494 * 1495 * @throws CmsException if something goes wrong 1496 */ 1497 protected boolean isSitemapEntry(CmsObject cms, CmsResource resource) throws CmsException { 1498 1499 CmsResourceFilter filter = CmsResourceFilter.ONLY_VISIBLE_NO_DELETED; 1500 List<CmsResource> ancestors = new ArrayList<CmsResource>(); 1501 CmsResource currentResource = resource; 1502 String siteRoot = OpenCms.getSiteManager().getSiteRoot(resource.getRootPath()); 1503 if (CmsStringUtil.isEmpty(siteRoot)) { 1504 return false; 1505 } 1506 while (true) { 1507 CmsResource parent = cms.readParentFolder(currentResource.getStructureId()); 1508 if ((parent == null) || !cms.existsResource(parent.getStructureId(), filter)) { 1509 break; 1510 } 1511 ancestors.add(parent); 1512 if (CmsStringUtil.comparePaths(siteRoot, parent.getRootPath())) { 1513 break; 1514 } 1515 currentResource = parent; 1516 } 1517 Collections.reverse(ancestors); 1518 boolean first = true; 1519 for (CmsResource ancestor : ancestors) { 1520 if (first) { 1521 if (null == OpenCms.getSiteManager().getSiteRoot(ancestor.getRootPath())) { 1522 return false; 1523 } 1524 } else { 1525 if (!hasNavigationProperty(cms, ancestor)) { 1526 return false; 1527 } 1528 } 1529 first = false; 1530 } 1531 if (resource.isFile()) { 1532 if (ancestors.isEmpty()) { 1533 return false; 1534 } 1535 CmsResource defaultFile = cms.readDefaultFile(ancestors.get(ancestors.size() - 1), filter); 1536 if (!resource.equals(defaultFile)) { 1537 return false; 1538 } 1539 } else { 1540 if (!hasNavigationProperty(cms, resource)) { 1541 return false; 1542 } 1543 } 1544 return true; 1545 } 1546 1547 /** 1548 * Reads the resources for a collection of structure ids and returns the list of resources which could be read.<p> 1549 * 1550 * @param structureIds the structure ids for which we want to read the resources 1551 * @param filter the filter used to read the resource 1552 * 1553 * @return the list of resources for the given structure id 1554 */ 1555 protected List<CmsResource> readAll(Collection<CmsUUID> structureIds, CmsResourceFilter filter) { 1556 1557 List<CmsResource> result = new ArrayList<CmsResource>(); 1558 for (CmsUUID id : structureIds) { 1559 try { 1560 result.add(getCmsObject().readResource(id, filter)); 1561 } catch (CmsException e) { 1562 LOG.info(e.getLocalizedMessage(), e); 1563 } 1564 } 1565 return result; 1566 } 1567 1568 /** 1569 * Gets the sitemap tree open state.<p> 1570 * 1571 * @param treeToken the tree token to use 1572 * 1573 * @return the sitemap tree open state 1574 */ 1575 CmsTreeOpenState getSitemapTreeState(String treeToken) { 1576 1577 return (CmsTreeOpenState)(getRequest().getSession().getAttribute( 1578 getTreeOpenStateAttributeName(I_CmsGalleryProviderConstants.TREE_SITEMAP, treeToken))); 1579 } 1580 1581 /** 1582 * Gets the VFS tree open state.<p> 1583 * 1584 * @param treeToken the tree token 1585 * 1586 * @return the VFS tree open state 1587 */ 1588 CmsTreeOpenState getVfsTreeState(String treeToken) { 1589 1590 return (CmsTreeOpenState)(getRequest().getSession().getAttribute( 1591 getTreeOpenStateAttributeName(I_CmsGalleryProviderConstants.TREE_VFS, treeToken))); 1592 } 1593 1594 /** 1595 * Returns the workplace locale from the current user's settings.<p> 1596 * 1597 * @return the workplace locale 1598 */ 1599 Locale getWorkplaceLocale() { 1600 1601 if (m_wpLocale == null) { 1602 m_wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject()); 1603 } 1604 return m_wpLocale; 1605 } 1606 1607 /** 1608 * Creates the sitemap entry bean for a resource.<p> 1609 * 1610 * @param cms the current CMS context 1611 * @param resource the resource for which the sitemap entry bean should be created 1612 * 1613 * @return the created sitemap entry bean 1614 * 1615 * @throws CmsException if something goes wrong 1616 */ 1617 CmsSitemapEntryBean internalCreateSitemapEntryBean(CmsObject cms, CmsResource resource) throws CmsException { 1618 1619 cms = OpenCms.initCmsObject(cms); 1620 cms.getRequestContext().setSiteRoot(""); 1621 CmsJspNavBuilder navBuilder = new CmsJspNavBuilder(cms); 1622 CmsJspNavElement entry = navBuilder.getNavigationForResource(resource.getRootPath()); 1623 if (entry == null) { 1624 // may be null for expired resources 1625 return null; 1626 } 1627 return prepareSitemapEntry(cms, entry, false, true); 1628 } 1629 1630 /** 1631 * Checks if the current user has write permissions on the given resource.<p> 1632 * 1633 * @param cms the current cms context 1634 * @param resource the resource to check 1635 * 1636 * @return <code>true</code> if the current user has write permissions on the given resource 1637 */ 1638 boolean isEditable(CmsObject cms, CmsResource resource) { 1639 1640 try { 1641 return cms.hasPermissions(resource, CmsPermissionSet.ACCESS_WRITE, false, CmsResourceFilter.ALL); 1642 } catch (CmsException e) { 1643 return false; 1644 } 1645 } 1646 1647 /** 1648 * Adds galleries for a given type.<p> 1649 * 1650 * @param galleryTypeInfos the gallery type infos 1651 * @param typeName the type name 1652 * 1653 * @throws CmsLoaderException if something goes wrong 1654 */ 1655 @SuppressWarnings("deprecation") 1656 private void addGalleriesForType(Map<String, CmsGalleryTypeInfo> galleryTypeInfos, String typeName) 1657 throws CmsLoaderException { 1658 1659 I_CmsResourceType contentType = getResourceManager().getResourceType(typeName); 1660 for (I_CmsResourceType galleryType : contentType.getGalleryTypes()) { 1661 1662 if (galleryTypeInfos.containsKey(galleryType.getTypeName())) { 1663 CmsGalleryTypeInfo typeInfo = galleryTypeInfos.get(galleryType.getTypeName()); 1664 typeInfo.addContentType(contentType); 1665 } else { 1666 CmsGalleryTypeInfo typeInfo; 1667 1668 typeInfo = new CmsGalleryTypeInfo( 1669 galleryType, 1670 contentType, 1671 getGalleriesByType(galleryType.getTypeId())); 1672 1673 galleryTypeInfos.put(galleryType.getTypeName(), typeInfo); 1674 } 1675 1676 } 1677 } 1678 1679 /** 1680 * Returns the map with the available galleries.<p> 1681 * 1682 * The map uses gallery path as the key and stores the CmsGalleriesListInfoBean as the value.<p> 1683 * @param contextPath the site path used as the current context 1684 * @param galleryTypes the galleries 1685 * 1686 * @return the map with gallery info beans 1687 */ 1688 private List<CmsGalleryFolderBean> buildGalleriesList( 1689 String contextPath, 1690 Map<String, CmsGalleryTypeInfo> galleryTypes) { 1691 1692 CmsObject cms = getCmsObject(); 1693 Locale wpLocale = getWorkplaceLocale(); 1694 String rootPath = cms.getRequestContext().addSiteRoot(contextPath); 1695 CmsADEConfigData sitemapConfig = OpenCms.getADEManager().lookupConfigurationWithCache(cms, rootPath); 1696 String subsitePath = sitemapConfig.getBasePath(); 1697 CmsSite site = OpenCms.getSiteManager().getSiteForRootPath(rootPath); 1698 1699 List<CmsGalleryFolderBean> list = new ArrayList<CmsGalleryFolderBean>(); 1700 if (galleryTypes == null) { 1701 return list; 1702 } 1703 for (Entry<String, CmsGalleryTypeInfo> ent : galleryTypes.entrySet()) { 1704 CmsGalleryTypeInfo tInfo = ent.getValue(); 1705 ArrayList<String> contentTypes = new ArrayList<String>(); 1706 Iterator<I_CmsResourceType> it = tInfo.getContentTypes().iterator(); 1707 while (it.hasNext()) { 1708 contentTypes.add(String.valueOf(it.next().getTypeName())); 1709 } 1710 for (CmsResource res : tInfo.getGalleries()) { 1711 CmsGalleryFolderBean bean = new CmsGalleryFolderBean(); 1712 String sitePath = getCmsObject().getSitePath(res); 1713 String title = ""; 1714 try { 1715 // read the gallery title 1716 title = getCmsObject().readPropertyObject( 1717 sitePath, 1718 CmsPropertyDefinition.PROPERTY_TITLE, 1719 false, 1720 getWorkplaceLocale()).getValue(""); 1721 } catch (CmsException e) { 1722 // error reading title property 1723 logError(e); 1724 } 1725 // sitepath as gallery id 1726 bean.setPath(sitePath); 1727 bean.setId(res.getStructureId()); 1728 // content types 1729 bean.setContentTypes(contentTypes); 1730 // title 1731 bean.setTitle(title); 1732 CmsGalleryGroup group = null; 1733 String groupLabel = null; 1734 if ((site != null) 1735 && (subsitePath != null) 1736 && CmsStringUtil.isPrefixPath(subsitePath, res.getRootPath()) 1737 && !new CmsPath(subsitePath).equals(new CmsPath(site.getSiteRoot()))) { 1738 // we are in a proper subsite, not just the site itself 1739 group = CmsGalleryGroup.subsite; 1740 1741 String labelSuffix = cms.getRequestContext().removeSiteRoot(subsitePath); 1742 try { 1743 Map<String, String> properties = CmsProperty.toMap( 1744 cms.readPropertyObjects(cms.getRequestContext().removeSiteRoot(subsitePath), false)); 1745 for (String propName : new String[] { 1746 CmsPropertyDefinition.PROPERTY_TITLE, 1747 CmsPropertyDefinition.PROPERTY_NAVTEXT}) { 1748 String propValue = properties.get(propName); 1749 if (propValue != null) { 1750 labelSuffix = propValue; 1751 break; 1752 } 1753 } 1754 } catch (Exception e) { 1755 LOG.error(e.getLocalizedMessage(), e); 1756 } 1757 groupLabel = Messages.get().getBundle(wpLocale).key( 1758 Messages.GUI_GALLERIES_GROUP_SUBSITE_1, 1759 labelSuffix); 1760 } else if ((site != null) && CmsStringUtil.isPrefixPath(site.getSiteRoot(), res.getRootPath())) { 1761 group = CmsGalleryGroup.site; 1762 String labelSuffix; 1763 labelSuffix = site.getTitle(); 1764 if (CmsStringUtil.isEmptyOrWhitespaceOnly(labelSuffix)) { 1765 labelSuffix = site.getSiteRoot(); 1766 } 1767 groupLabel = Messages.get().getBundle(wpLocale).key( 1768 Messages.GUI_GALLERIES_GROUP_SITE_1, 1769 labelSuffix); 1770 } else if (CmsStringUtil.isPrefixPath(CmsResource.VFS_FOLDER_SYSTEM, res.getRootPath()) 1771 || OpenCms.getSiteManager().startsWithShared(res.getRootPath())) { 1772 group = CmsGalleryGroup.shared; 1773 groupLabel = Messages.get().getBundle(wpLocale).key(Messages.GUI_GALLERIES_GROUP_SHARED_0); 1774 } else { 1775 group = CmsGalleryGroup.other; 1776 groupLabel = Messages.get().getBundle(wpLocale).key(Messages.GUI_GALLERIES_GROUP_OTHER_0); 1777 } 1778 bean.setGroup(group); 1779 bean.setGroupLabel(groupLabel); 1780 bean.setResourceType(tInfo.getResourceType().getTypeName()); 1781 bean.setUploadAction(tInfo.getResourceType().getConfiguration().get("gallery.upload.action")); 1782 1783 boolean isOptimizeGalleryType = Arrays.asList("imagegallery", "downloadgallery").stream().anyMatch( 1784 typeName -> OpenCms.getResourceManager().matchResourceType(typeName, res.getTypeId())); 1785 1786 // For performance reasons, we only do a general role check for EDITOR which does not take the concrete gallery path or context path into account. 1787 bean.setOptimizable( 1788 OpenCms.getRoleManager().hasRole(getCmsObject(), CmsRole.EDITOR) && isOptimizeGalleryType); 1789 1790 bean.setEditable(isEditable(getCmsObject(), res)); 1791 bean.setBigIconClasses( 1792 CmsIconUtil.getIconClasses(CmsIconUtil.getDisplayType(getCmsObject(), res), sitePath, false)); 1793 list.add(bean); 1794 } 1795 } 1796 return list; 1797 } 1798 1799 /** 1800 * Returns a map with the available locales.<p> 1801 * 1802 * The map entry key is the current locale and the value the localized nice name.<p> 1803 * 1804 * @return the map representation of all available locales 1805 */ 1806 private Map<String, String> buildLocalesMap() { 1807 1808 TreeMap<String, String> localesMap = new TreeMap<String, String>(); 1809 Iterator<Locale> it = OpenCms.getLocaleManager().getAvailableLocales().iterator(); 1810 while (it.hasNext()) { 1811 Locale locale = it.next(); 1812 localesMap.put(locale.toString(), locale.getDisplayName(getWorkplaceLocale())); 1813 } 1814 return localesMap; 1815 } 1816 1817 /** 1818 * Returns the list of beans for the given search results.<p> 1819 * 1820 * @param searchResult the list of search results 1821 * @param presetResult the search result which corresponds to a preset value in the editor 1822 * @param checkDeactivated checks if search results should be shown as deactivated 1823 * 1824 * @return the list with the current search results 1825 */ 1826 private List<CmsResultItemBean> buildSearchResultList( 1827 List<CmsGallerySearchResult> searchResult, 1828 CmsGallerySearchResult presetResult, 1829 Predicate<CmsResource> checkDeactivated) { 1830 1831 ArrayList<CmsResultItemBean> list = new ArrayList<CmsResultItemBean>(); 1832 if ((searchResult == null) || (searchResult.size() == 0)) { 1833 return list; 1834 } 1835 CmsObject cms = getCmsObject(); 1836 for (CmsGallerySearchResult sResult : searchResult) { 1837 try { 1838 CmsResultItemBean bean = buildSingleSearchResultItem(cms, sResult, presetResult, checkDeactivated); 1839 list.add(bean); 1840 } catch (Exception e) { 1841 logError(e); 1842 } 1843 } 1844 return list; 1845 } 1846 1847 /** 1848 * Builds a single search result list item for the client from a server-side search result.<p> 1849 * 1850 * @param cms the current CMS context 1851 * @param sResult the server-side search result 1852 * @param presetResult the preselected result 1853 * @param checkDeactivated checks if search results should be shown as deactivated 1854 * 1855 * @return the client side search result item 1856 * 1857 * @throws CmsException if something goes wrong 1858 * @throws ParseException if date parsing fails 1859 */ 1860 private CmsResultItemBean buildSingleSearchResultItem( 1861 CmsObject cms, 1862 CmsGallerySearchResult sResult, 1863 CmsGallerySearchResult presetResult, 1864 Predicate<CmsResource> checkDeactivated) 1865 throws CmsException, ParseException { 1866 1867 Locale wpLocale = getWorkplaceLocale(); 1868 CmsResultItemBean bean = new CmsResultItemBean(); 1869 if (sResult == presetResult) { 1870 bean.setPreset(true); 1871 } 1872 bean.setReleasedAndNotExpired(sResult.isReleaseAndNotExpired(cms)); 1873 String path = sResult.getPath(); 1874 path = cms.getRequestContext().removeSiteRoot(path); 1875 1876 // resource path as id 1877 bean.setPath(path); 1878 1879 // title 1880 String rawTitle = CmsStringUtil.isEmptyOrWhitespaceOnly(sResult.getTitle()) 1881 ? CmsResource.getName(sResult.getPath()) 1882 : sResult.getTitle(); 1883 bean.setTitle(rawTitle); 1884 bean.setRawTitle(rawTitle); 1885 // resource type 1886 bean.setType(sResult.getResourceType()); 1887 CmsResource resultResource = cms.readResource( 1888 new CmsUUID(sResult.getStructureId()), 1889 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1890 bean.setBigIconClasses( 1891 CmsIconUtil.getIconClasses(CmsIconUtil.getDisplayType(cms, resultResource), path, false)); 1892 String detailType = CmsResourceIcon.getDefaultFileOrDetailType(cms, resultResource); 1893 if (detailType != null) { 1894 bean.setSmallIconClasses(CmsIconUtil.getIconClasses(detailType, null, true)); 1895 } 1896 // structured id 1897 bean.setClientId(sResult.getStructureId()); 1898 1899 CmsVfsService.addLockInfo(cms, resultResource, bean); 1900 String extension = CmsResource.getExtension(resultResource.getRootPath()); 1901 String suffix = extension != null ? "." + extension : ""; 1902 1903 String permalinkId = sResult.getStructureId().toString(); 1904 String permalink = CmsStringUtil.joinPaths( 1905 OpenCms.getSystemInfo().getOpenCmsContext(), 1906 CmsPermalinkResourceHandler.PERMALINK_HANDLER, 1907 permalinkId) + suffix; 1908 1909 bean.setViewLink(permalink); 1910 // set nice resource type name as subtitle 1911 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(sResult.getResourceType()); 1912 String resourceTypeDisplayName = CmsWorkplaceMessages.getResourceTypeName(wpLocale, type.getTypeName()); 1913 String description = sResult.getDescription(); 1914 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(description)) { 1915 bean.setDescription(description); 1916 bean.addAdditionalInfo( 1917 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_DESCRIPTION_0), 1918 description); 1919 if (sResult.getResourceType().equals(CmsResourceTypeFunctionConfig.TYPE_NAME)) { 1920 bean.setSubTitle(description); 1921 } 1922 } else { 1923 bean.setDescription(resourceTypeDisplayName); 1924 } 1925 bean.setUserLastModified(sResult.getUserLastModified()); 1926 Date lastModDate = sResult.getDateLastModified(); 1927 String formattedDate = lastModDate != null 1928 ? CmsDateUtil.getDateTime(lastModDate, DateFormat.MEDIUM, wpLocale) 1929 : ""; 1930 bean.setDateLastModified(formattedDate); 1931 if (!type.getTypeName().equals(CmsResourceTypeImage.getStaticTypeName())) { 1932 bean.addAdditionalInfo( 1933 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_RESOURCE_TYPE_0), 1934 resourceTypeDisplayName); 1935 } 1936 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(sResult.getExcerpt())) { 1937 bean.addAdditionalInfo( 1938 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_EXCERPT_0), 1939 sResult.getExcerpt(), 1940 CmsListInfoBean.CSS_CLASS_MULTI_LINE); 1941 } 1942 if (type instanceof CmsResourceTypeImage) { 1943 CmsProperty copyrightProp = cms.readPropertyObject( 1944 resultResource, 1945 CmsPropertyDefinition.PROPERTY_COPYRIGHT, 1946 false); 1947 if (!copyrightProp.isNullProperty()) { 1948 bean.addAdditionalInfo( 1949 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_COPYRIGHT_0), 1950 copyrightProp.getValue()); 1951 } 1952 CmsProperty imageDimensionProp = cms.readPropertyObject( 1953 resultResource, 1954 CmsPropertyDefinition.PROPERTY_IMAGE_SIZE, 1955 false); 1956 if (!imageDimensionProp.isNullProperty()) { 1957 String dimensions = imageDimensionProp.getValue(); 1958 dimensions = dimensions.substring(2).replace(",h:", " x "); 1959 bean.setDimension(dimensions); 1960 bean.addAdditionalInfo( 1961 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_DIMENSION_0), 1962 dimensions); 1963 } 1964 } 1965 1966 if (type instanceof CmsResourceTypeXmlContent) { 1967 CmsProperty elementModelProperty = cms.readPropertyObject( 1968 resultResource, 1969 CmsPropertyDefinition.PROPERTY_ELEMENT_MODEL, 1970 true); 1971 if (!elementModelProperty.isNullProperty()) { 1972 if (Boolean.valueOf(elementModelProperty.getValue()).booleanValue()) { 1973 bean.setIsCopyModel(true); 1974 } 1975 } 1976 } 1977 bean.setResourceState(resultResource.getState()); 1978 bean.addAdditionalInfo( 1979 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_SIZE_0), 1980 (sResult.getLength() / 1000) + " kb"); 1981 if (lastModDate != null) { 1982 bean.addAdditionalInfo( 1983 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_DATE_CHANGED_0), 1984 CmsDateUtil.getDate(lastModDate, DateFormat.SHORT, getWorkplaceLocale())); 1985 } 1986 if ((sResult.getDateExpired().getTime() != CmsResource.DATE_EXPIRED_DEFAULT) 1987 && !sResult.getDateExpired().equals(CmsSearchFieldMapping.getDefaultDateExpired())) { 1988 bean.addAdditionalInfo( 1989 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_DATE_EXPIRED_0), 1990 CmsDateUtil.getDate(sResult.getDateExpired(), DateFormat.SHORT, getWorkplaceLocale())); 1991 } 1992 1993 bean.setNoEditReson( 1994 new CmsResourceUtil(cms, resultResource).getNoEditReason( 1995 OpenCms.getWorkplaceManager().getWorkplaceLocale(cms))); 1996 bean.setMarkChangedState(true); 1997 if (checkDeactivated.test(resultResource)) { 1998 bean.setDeactivated(true); 1999 } 2000 return bean; 2001 } 2002 2003 /** 2004 * Generates a map with all available content types.<p> 2005 * 2006 * The map uses resource type name as the key and stores the CmsTypesListInfoBean as the value. 2007 * 2008 * @param types the resource types 2009 * @param creatableTypes the creatable types 2010 * 2011 * @return the map containing the available resource types 2012 */ 2013 private List<CmsResourceTypeBean> buildTypesList(List<I_CmsResourceType> types, Set<String> creatableTypes) { 2014 2015 ArrayList<CmsResourceTypeBean> list = new ArrayList<CmsResourceTypeBean>(); 2016 if (types == null) { 2017 return list; 2018 } 2019 Map<I_CmsResourceType, I_CmsPreviewProvider> typeProviderMapping = getPreviewProviderForTypes(types); 2020 Iterator<I_CmsResourceType> it = types.iterator(); 2021 while (it.hasNext()) { 2022 2023 I_CmsResourceType type = it.next(); 2024 try { 2025 CmsResourceTypeBean bean = createTypeBean( 2026 type, 2027 typeProviderMapping.get(type), 2028 creatableTypes.contains(type.getTypeName())); 2029 list.add(bean); 2030 } catch (Exception e) { 2031 if (type != null) { 2032 log( 2033 Messages.get().getBundle(getWorkplaceLocale()).key( 2034 Messages.ERR_BUILD_TYPE_LIST_1, 2035 type.getTypeName()), 2036 e); 2037 } 2038 } 2039 } 2040 return list; 2041 } 2042 2043 /** 2044 * Recursively builds the VFS entry bean for the quick filtering function in the folder tab.<p< 2045 * 2046 * @param resource the resource 2047 * @param childMap map from parent to child resources 2048 * @param filterMatches the resources matching the filter 2049 * @param parentPaths root paths of resources which are not leaves 2050 * @param isRoot true if this the root node 2051 * 2052 * @return the VFS entry bean for the client 2053 * 2054 * @throws CmsException if something goes wrong 2055 */ 2056 private CmsVfsEntryBean buildVfsEntryBeanForQuickSearch( 2057 CmsResource resource, 2058 Multimap<CmsResource, CmsResource> childMap, 2059 Set<CmsResource> filterMatches, 2060 Set<String> parentPaths, 2061 boolean isRoot) 2062 throws CmsException { 2063 2064 CmsObject cms = getCmsObject(); 2065 String title = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue(); 2066 boolean isMatch = filterMatches.contains(resource); 2067 List<CmsVfsEntryBean> childBeans = Lists.newArrayList(); 2068 2069 Collection<CmsResource> children = childMap.get(resource); 2070 if (!children.isEmpty()) { 2071 for (CmsResource child : children) { 2072 CmsVfsEntryBean childBean = buildVfsEntryBeanForQuickSearch( 2073 child, 2074 childMap, 2075 filterMatches, 2076 parentPaths, 2077 false); 2078 childBeans.add(childBean); 2079 } 2080 } else if (filterMatches.contains(resource)) { 2081 if (parentPaths.contains(resource.getRootPath())) { 2082 childBeans = null; 2083 } 2084 // otherwise childBeans remains an empty list 2085 } 2086 2087 String rootPath = resource.getRootPath(); 2088 CmsVfsEntryBean result = new CmsVfsEntryBean( 2089 rootPath, 2090 resource.getStructureId(), 2091 title, 2092 CmsIconUtil.getIconClasses(CmsIconUtil.getDisplayType(cms, resource), resource.getName(), true), 2093 isRoot, 2094 isEditable(cms, resource), 2095 childBeans, 2096 isMatch); 2097 String siteRoot = null; 2098 if (OpenCms.getSiteManager().startsWithShared(rootPath)) { 2099 siteRoot = OpenCms.getSiteManager().getSharedFolder(); 2100 } else { 2101 String tempSiteRoot = OpenCms.getSiteManager().getSiteRoot(rootPath); 2102 if (tempSiteRoot != null) { 2103 siteRoot = tempSiteRoot; 2104 } else { 2105 siteRoot = ""; 2106 } 2107 } 2108 result.setSiteRoot(siteRoot); 2109 return result; 2110 } 2111 2112 /** 2113 * Helper method to construct a sitemap entry bean for the sitemap tab filter functionality.<p> 2114 * 2115 * @param cms the CMS context 2116 * @param node the root node of the filtered tree 2117 * @param isRoot true if this is the root node 2118 * 2119 * @return the sitemap entry bean 2120 */ 2121 private CmsSitemapEntryBean convertNavigationTreeToBean(CmsObject cms, NavigationNode node, boolean isRoot) { 2122 2123 CmsSitemapEntryBean bean = null; 2124 try { 2125 bean = prepareSitemapEntry(cms, node.getNavElement(), isRoot, false); 2126 bean.setSearchMatch(node.isMatch()); 2127 List<NavigationNode> children = node.getChildren(); 2128 List<CmsSitemapEntryBean> childBeans = Lists.newArrayList(); 2129 if (children.size() > 0) { 2130 for (NavigationNode child : children) { 2131 childBeans.add(convertNavigationTreeToBean(cms, child, false)); 2132 } 2133 } else if (node.isLeaf()) { 2134 childBeans = Lists.newArrayList(); 2135 } else { 2136 // no children in filter result, but can still load children by clicking on tree item 2137 childBeans = null; 2138 } 2139 bean.setChildren(childBeans); 2140 2141 } catch (CmsException e) { 2142 LOG.error(e.getLocalizedMessage(), e); 2143 } 2144 return bean; 2145 } 2146 2147 /** 2148 * Returns a list of resource types by a request parameter.<p> 2149 * 2150 * @param resourceTypes the resource types parameter 2151 * 2152 * @return the resource types 2153 */ 2154 private List<I_CmsResourceType> convertTypeNamesToTypes(List<String> resourceTypes) { 2155 2156 List<I_CmsResourceType> result = new ArrayList<I_CmsResourceType>(); 2157 if (resourceTypes != null) { 2158 for (String type : resourceTypes) { 2159 try { 2160 result.add(getResourceManager().getResourceType(type.trim())); 2161 } catch (Exception e) { 2162 logError(e); 2163 } 2164 } 2165 } 2166 2167 return result; 2168 } 2169 2170 /** 2171 * Creates a resource type bean for the given type.<p> 2172 * 2173 * @param type the resource type 2174 * @param preview the preview provider 2175 * @param creatable if the type may be created by the current user 2176 * 2177 * @return the resource type bean 2178 */ 2179 @SuppressWarnings("deprecation") 2180 private CmsResourceTypeBean createTypeBean( 2181 I_CmsResourceType type, 2182 I_CmsPreviewProvider preview, 2183 boolean creatable) { 2184 2185 CmsResourceTypeBean result = new CmsResourceTypeBean(); 2186 2187 result.setResourceType(type.getTypeName()); 2188 result.setTypeId(type.getTypeId()); 2189 Locale wpLocale = getWorkplaceLocale(); 2190 // type title and subtitle 2191 result.setTitle(CmsWorkplaceMessages.getResourceTypeName(wpLocale, type.getTypeName())); 2192 result.setSubTitle(CmsWorkplaceMessages.getResourceTypeDescription(wpLocale, type.getTypeName())); 2193 result.setBigIconClasses(CmsIconUtil.getIconClasses(type.getTypeName(), null, false)); 2194 // gallery id of corresponding galleries 2195 ArrayList<String> galleryNames = new ArrayList<String>(); 2196 Iterator<I_CmsResourceType> galleryTypes = type.getGalleryTypes().iterator(); 2197 while (galleryTypes.hasNext()) { 2198 I_CmsResourceType galleryType = galleryTypes.next(); 2199 galleryNames.add(galleryType.getTypeName()); 2200 } 2201 result.setGalleryTypeNames(galleryNames); 2202 if (preview != null) { 2203 result.setPreviewProviderName(preview.getPreviewName()); 2204 } 2205 if (type.isFolder()) { 2206 result.setVisibility(TypeVisibility.hidden); 2207 } 2208 result.setCreatableType(creatable); 2209 return result; 2210 } 2211 2212 /** 2213 * Returns the search object containing the list with search results and the path to the specified resource.<p> 2214 * 2215 * @param resourceName the given resource 2216 * @param data the gallery data bean 2217 * 2218 * @return the gallery search object containing the current search parameter and the search result list 2219 * 2220 * @throws CmsException if the search fails 2221 */ 2222 private CmsGallerySearchBean findResourceInGallery(String resourceName, CmsGalleryDataBean data) 2223 throws CmsException { 2224 2225 CmsResource resource = null; 2226 int pos = resourceName.indexOf("?"); 2227 String resName = resourceName; 2228 String query = ""; 2229 if (pos > -1) { 2230 query = resourceName.substring(pos); 2231 resName = resourceName.substring(0, pos); 2232 } 2233 String resNameWithoutServer = OpenCms.getLinkManager().getRootPath(getCmsObject(), resName); 2234 if (resNameWithoutServer != null) { 2235 // also cut off fragment if it has one 2236 resName = resNameWithoutServer.replaceFirst("#.*$", ""); 2237 } 2238 CmsObject cms = getCmsObject(); 2239 try { 2240 log("reading resource: " + resName); 2241 resource = cms.readResource(resName, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2242 } catch (CmsException e) { 2243 String originalSiteRoot = cms.getRequestContext().getSiteRoot(); 2244 try { 2245 cms.getRequestContext().setSiteRoot(""); 2246 resource = cms.readResource(resName, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2247 } catch (CmsException e2) { 2248 logError(e); 2249 return null; 2250 } finally { 2251 cms.getRequestContext().setSiteRoot(originalSiteRoot); 2252 } 2253 } 2254 boolean typeOk = true; 2255 if ((data.getTypes() != null) && !data.getTypes().isEmpty()) { 2256 typeOk = false; 2257 for (CmsResourceTypeBean type : data.getTypes()) { 2258 if (OpenCms.getResourceManager().matchResourceType(type.getType(), resource.getTypeId())) { 2259 typeOk = true; 2260 } 2261 } 2262 } 2263 if (!typeOk) { 2264 LOG.debug( 2265 "Selected resource " + resource.getRootPath() + " has invalid type for configured gallery widget."); 2266 return null; 2267 } 2268 ArrayList<String> types = new ArrayList<String>(); 2269 String resType = OpenCms.getResourceManager().getResourceType(resource).getTypeName(); 2270 types.add(resType); 2271 Set<String> folders = null; 2272 if (data.getStartFolderFilter() != null) { 2273 for (String folder : data.getStartFolderFilter()) { 2274 if (resource.getRootPath().startsWith(folder)) { 2275 folders = data.getStartFolderFilter(); 2276 break; 2277 } 2278 } 2279 } 2280 CmsGallerySearchBean initialSearchObj = new CmsGallerySearchBean(); 2281 initialSearchObj.setGalleryMode(data.getMode()); 2282 initialSearchObj.setGalleryStoragePrefix(data.getGalleryStoragePrefix()); 2283 initialSearchObj.setIncludeExpired(data.getIncludeExpiredDefault()); 2284 initialSearchObj.setIgnoreSearchExclude(true); 2285 initialSearchObj.setTypes(types); 2286 if (folders != null) { 2287 initialSearchObj.setFolders(folders); 2288 } 2289 ArrayList<String> galleries = new ArrayList<String>(); 2290 for (CmsGalleryFolderBean gallery : data.getGalleries()) { 2291 String galleryPath = gallery.getPath(); 2292 String galleryRootPath = cms.addSiteRoot(galleryPath); 2293 String folderPath = CmsResource.getFolderPath(resName); 2294 if (galleryPath.equals(folderPath) || galleryRootPath.equals(folderPath)) { 2295 galleries.add(gallery.getPath()); 2296 initialSearchObj.setGalleries(galleries); 2297 break; 2298 } 2299 } 2300 if (galleries.isEmpty()) { 2301 ArrayList<String> vfsFolders = new ArrayList<String>(); 2302 vfsFolders.add(CmsResource.getFolderPath(resource.getRootPath())); 2303 initialSearchObj.setFolders(new HashSet<String>(vfsFolders)); 2304 } 2305 initialSearchObj.setLocale(data.getLocale()); 2306 CmsGallerySearchBean searchObj = new CmsGallerySearchBean(initialSearchObj); 2307 CmsWorkplaceSettings wpSettings = getWorkplaceSettings(); 2308 String resultOrderKey = convertModeToResultOrderKey(data.getMode()); 2309 SortParams sortOrder = wpSettings.getLastGalleryResultOrder(resultOrderKey); 2310 if (sortOrder == null) { 2311 sortOrder = SortParams.dateLastModified_desc; 2312 } 2313 try { 2314 // Make sure that the SortParams name corresponds to a valid CmsGallerySortParam name 2315 searchObj.setSortOrder(CmsGallerySearchParameters.CmsGallerySortParam.valueOf(sortOrder.toString()).name()); 2316 } catch (Exception e) { 2317 LOG.error(e.getLocalizedMessage(), e); 2318 searchObj.setSortOrder(CmsGallerySearchParameters.CmsGallerySortParam.dateLastModified_desc.name()); 2319 } 2320 2321 int currentPage = 1; 2322 boolean found = false; 2323 searchObj.setPage(currentPage); 2324 CmsGallerySearchParameters params = prepareSearchParams(searchObj, CmsAddContentRestriction.EMPTY); 2325 CmsObject searchCms = getSearchCms(searchObj); 2326 org.opencms.search.galleries.CmsGallerySearch searchBean = new org.opencms.search.galleries.CmsGallerySearch(); 2327 searchBean.init(searchCms); 2328 searchBean.setIndexForProject(searchCms); 2329 CmsGallerySearchResultList searchResults = null; 2330 CmsGallerySearchResultList totalResults = new CmsGallerySearchResultList(); 2331 CmsGallerySearchResult foundItem = null; 2332 while (!found) { 2333 params.setResultPage(currentPage); 2334 searchResults = searchBean.getResult(params); 2335 totalResults.append(searchResults); 2336 Iterator<CmsGallerySearchResult> resultsIt = searchResults.listIterator(); 2337 while (resultsIt.hasNext()) { 2338 CmsGallerySearchResult searchResult = resultsIt.next(); 2339 if (searchResult.getPath().equals(resource.getRootPath())) { 2340 found = true; 2341 foundItem = searchResult; 2342 break; 2343 } 2344 } 2345 if (!found && ((searchResults.getHitCount() / (currentPage * params.getMatchesPerPage())) >= 1)) { 2346 currentPage++; 2347 } else { 2348 break; 2349 } 2350 if (searchResults.getHitCount() > INITIAL_SEARCH_MAX_RESULTS) { 2351 // in case the hit count is too large, don't continue the search to avoid slow load times 2352 break; 2353 } 2354 } 2355 boolean hasResults = searchResults != null; 2356 searchResults = totalResults; 2357 if (hasResults) { 2358 initialSearchObj.setSortOrder(params.getSortOrder().name()); 2359 initialSearchObj.setResultCount(searchResults.getHitCount()); 2360 initialSearchObj.setPage(params.getResultPage()); 2361 initialSearchObj.setResults(buildSearchResultList(searchResults, foundItem, res -> false)); 2362 initialSearchObj.setPage(1); 2363 initialSearchObj.setLastPage(currentPage); 2364 initialSearchObj.setTabId(I_CmsGalleryProviderConstants.GalleryTabId.cms_tab_results.name()); 2365 initialSearchObj.setResourcePath(resName + query); 2366 initialSearchObj.setResourceType(resType); 2367 updateNoUploadReason(searchCms, searchObj); 2368 } else { 2369 log("could not find selected resource"); 2370 } 2371 if ((resource != null)) { 2372 if (isSitemapEntry(cms, resource)) { 2373 A_CmsTreeTabDataPreloader<CmsSitemapEntryBean> loader = new A_CmsTreeTabDataPreloader<CmsSitemapEntryBean>() { 2374 2375 @Override 2376 protected CmsSitemapEntryBean createEntry(CmsObject innerCms, CmsResource innerResource) 2377 throws CmsException { 2378 2379 return internalCreateSitemapEntryBean(innerCms, innerResource); 2380 } 2381 2382 /** 2383 * @see org.opencms.ade.galleries.A_CmsTreeTabDataPreloader#getChildren(org.opencms.file.CmsResource) 2384 */ 2385 @Override 2386 protected List<CmsResource> getChildren(CmsResource parent) throws CmsException { 2387 2388 return getSitemapSubEntryResources(parent.getRootPath()); 2389 } 2390 }; 2391 CmsSitemapEntryBean entryBean = loader.preloadData( 2392 cms, 2393 Sets.newHashSet(Collections.singletonList(resource)), 2394 null); 2395 initialSearchObj.setSitemapPreloadData(entryBean); 2396 } else if (resource.isFolder()) { 2397 A_CmsTreeTabDataPreloader<CmsVfsEntryBean> loader = new A_CmsTreeTabDataPreloader<CmsVfsEntryBean>() { 2398 2399 @Override 2400 protected CmsVfsEntryBean createEntry(CmsObject innerCms, CmsResource innerResource) 2401 throws CmsException { 2402 2403 String title = innerCms.readPropertyObject( 2404 innerResource, 2405 CmsPropertyDefinition.PROPERTY_TITLE, 2406 false).getValue(); 2407 return internalCreateVfsEntryBean( 2408 getCmsObject(), 2409 innerResource, 2410 title, 2411 true, 2412 isEditable(innerCms, innerResource), 2413 null, 2414 false); 2415 } 2416 }; 2417 CmsVfsEntryBean entryBean = loader.preloadData( 2418 cms, 2419 Sets.newHashSet(Collections.singletonList(resource)), 2420 null); 2421 initialSearchObj.setVfsPreloadData(entryBean); 2422 } 2423 } 2424 2425 return initialSearchObj; 2426 } 2427 2428 /** 2429 * Get default types for gallery together with visibility.<p> 2430 * 2431 * @return the default types 2432 */ 2433 private List<I_CmsResourceType> getDefaultTypesForGallery() { 2434 2435 return OpenCms.getResourceManager().getResourceTypes(); 2436 } 2437 2438 /** 2439 * Generates a list of available galleries for the given gallery-type.<p> 2440 * 2441 * @param galleryTypeId the gallery-type 2442 * 2443 * @return the list of galleries 2444 * 2445 */ 2446 @SuppressWarnings("deprecation") 2447 private List<CmsResource> getGalleriesByType(int galleryTypeId) { 2448 2449 Set<CmsResource> galleries = new HashSet<CmsResource>(); 2450 2451 // We swallow errors in this method because we don't want a failure to read some folders (e.g. because of permission problems) to 2452 // cause an empty gallery list as a result 2453 2454 try { 2455 galleries.addAll( 2456 getCmsObject().readResources( 2457 "/", 2458 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(galleryTypeId))); 2459 } catch (Exception e) { 2460 LOG.error("Could not read site galleries: " + e.getLocalizedMessage(), e); 2461 } 2462 2463 String siteRoot = getCmsObject().getRequestContext().getSiteRoot(); 2464 // if the current site is NOT the root site - add all other galleries from the system path 2465 2466 try { 2467 if (!siteRoot.equals("")) { 2468 List<CmsResource> systemGalleries = null; 2469 // get the galleries in the /system/ folder 2470 systemGalleries = getCmsObject().readResources( 2471 CmsWorkplace.VFS_PATH_SYSTEM, 2472 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(galleryTypeId)); 2473 if (systemGalleries != null) { 2474 // add the found system galleries to the result 2475 galleries.addAll(systemGalleries); 2476 } 2477 } 2478 } catch (Exception e) { 2479 LOG.info("Could not read system galleries: " + e.getLocalizedMessage(), e); 2480 } 2481 2482 try { 2483 if (!OpenCms.getSiteManager().isSharedFolder(siteRoot)) { 2484 String shared = OpenCms.getSiteManager().getSharedFolder(); 2485 List<CmsResource> sharedGalleries = getCmsObject().readResources( 2486 shared, 2487 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(galleryTypeId)); 2488 if (sharedGalleries != null) { 2489 galleries.addAll(sharedGalleries); 2490 } 2491 } 2492 } catch (Exception e) { 2493 LOG.info("Could not read shared galleries: " + e.getLocalizedMessage(), e); 2494 } 2495 List<CmsResource> galleriesList = new ArrayList<>(galleries); 2496 Collections.sort( 2497 galleriesList, 2498 (a, b) -> ComparisonChain.start().compare(a.getRootPath(), b.getRootPath()).result()); 2499 return galleriesList; 2500 } 2501 2502 /** 2503 * Helper method for getting the initial gallery settings.<p> 2504 * 2505 * @param conf the gallery configration 2506 * @return the gallery settings 2507 * 2508 * @throws CmsRpcException if something goes wrong 2509 */ 2510 private CmsGalleryDataBean getInitialSettingsInternal(CmsGalleryConfiguration conf) throws CmsRpcException { 2511 2512 CmsObject cms = getCmsObject(); 2513 CmsGalleryDataBean data = new CmsGalleryDataBean(); 2514 data.setMode(conf.getGalleryMode()); 2515 data.setResultViewType(readResultViewType()); 2516 boolean galleryShowInvalidDefault = Boolean.parseBoolean( 2517 getWorkplaceSettings().getUserSettings().getAdditionalPreference(PREF_GALLERY_SHOW_INVALID_DEFAULT, true)); 2518 data.setIncludeExpiredDefault(galleryShowInvalidDefault); 2519 2520 data.setGalleryStoragePrefix(conf.getGalleryStoragePrefix()); 2521 data.setLocales(buildLocalesMap()); 2522 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(conf.getLocale())) { 2523 data.setLocale(conf.getLocale()); 2524 } else { 2525 data.setLocale(getCmsObject().getRequestContext().getLocale().toString()); 2526 } 2527 data.setVfsRootFolders(getRootEntries()); 2528 data.setScope(getWorkplaceSettings().getLastSearchScope()); 2529 String resultOrderKey = convertModeToResultOrderKey(conf.getGalleryMode()); 2530 data.setSortOrder(getWorkplaceSettings().getLastGalleryResultOrder(resultOrderKey)); 2531 2532 List<CmsResourceTypeBean> types = null; 2533 data.setTabIds(conf.getGalleryMode().getTabs()); 2534 switch (conf.getGalleryMode()) { 2535 case editor: 2536 case view: 2537 case adeView: 2538 case widget: 2539 if (conf.getTabIds() != null) { 2540 data.setTabIds(conf.getTabIds()); 2541 } 2542 data.setCurrentElement(conf.getCurrentElement()); 2543 String referencePath = conf.getReferencePath(); 2544 if (CmsStringUtil.isEmptyOrWhitespaceOnly(referencePath)) { 2545 referencePath = conf.getGalleryPath(); 2546 } 2547 data.setReferenceSitePath(referencePath); 2548 types = getResourceTypeBeans( 2549 conf.getGalleryMode(), 2550 data.getReferenceSitePath(), 2551 conf.getResourceTypes(), 2552 conf.getSearchTypes()); 2553 data.setTypes(types); 2554 Map<String, CmsGalleryTypeInfo> galleryTypeInfos = readGalleryInfosByTypeBeans(types); 2555 // in case the 'gallerytypes' parameter is set, allow only the given galleries 2556 if (conf.getGalleryTypes() != null) { 2557 Map<String, CmsGalleryTypeInfo> infos = new HashMap<String, CmsGalleryTypeInfo>(); 2558 for (int i = 0; i < conf.getGalleryTypes().length; i++) { 2559 CmsGalleryTypeInfo typeInfo = galleryTypeInfos.get(conf.getGalleryTypes()[i]); 2560 if (typeInfo != null) { 2561 infos.put(conf.getGalleryTypes()[i], typeInfo); 2562 } 2563 } 2564 galleryTypeInfos = infos; 2565 } 2566 2567 String uri = cms.getRequestContext().getUri(); 2568 String galleryContext = referencePath; 2569 if (conf.getPageId() != null) { 2570 // This covers the case where the user is in the page editor, 2571 // then edits an element of the page with the content editor, and then 2572 // opens the gallery from a WYSIWYG field in the content editor. 2573 try { 2574 CmsResource page = cms.readResource( 2575 new CmsUUID(conf.getPageId()), 2576 CmsResourceFilter.IGNORE_EXPIRATION); 2577 galleryContext = cms.getSitePath(page); 2578 } catch (Exception e) { 2579 LOG.error(e.getLocalizedMessage(), e); 2580 } 2581 } else if (!uri.endsWith(".gwt") && !uri.endsWith(".jsp")) { 2582 galleryContext = uri; 2583 } 2584 if (galleryContext == null) { 2585 galleryContext = "/"; 2586 } 2587 data.setGalleries(buildGalleriesList(galleryContext, galleryTypeInfos)); 2588 String startGallery = conf.getGalleryPath(); 2589 // check if the configured gallery path really is an existing gallery 2590 boolean galleryAvailable = false; 2591 for (CmsGalleryFolderBean folderBean : data.getGalleries()) { 2592 if (folderBean.getPath().equals(startGallery)) { 2593 galleryAvailable = true; 2594 break; 2595 } 2596 } 2597 data.setStartGallery(galleryAvailable ? startGallery : null); 2598 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(conf.getStartFolder())) { 2599 try { 2600 CmsObject cloneCms = OpenCms.initCmsObject(getCmsObject()); 2601 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(conf.getStartSite())) { 2602 cloneCms.getRequestContext().setSiteRoot(conf.getStartSite()); 2603 } 2604 if (cloneCms.existsResource(conf.getStartFolder(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 2605 data.setStartFolder(cloneCms.getRequestContext().addSiteRoot(conf.getStartFolder())); 2606 } 2607 } catch (CmsException e) { 2608 log(e.getMessage(), e); 2609 } 2610 } 2611 2612 if (CmsStringUtil.isEmptyOrWhitespaceOnly(data.getStartGallery()) && !data.getGalleries().isEmpty()) { 2613 2614 String key = ""; 2615 if (!types.isEmpty() && !CmsStringUtil.isEmptyOrWhitespaceOnly(conf.getReferencePath())) { 2616 key = types.get(0).getType(); 2617 try { 2618 CmsResource refResource = getCmsObject().readResource(conf.getReferencePath()); 2619 String referenceType = OpenCms.getResourceManager().getResourceType( 2620 refResource).getTypeName(); 2621 key = CmsGallerySearchBean.getGalleryStorageKey( 2622 data.getGalleryStoragePrefix(), 2623 referenceType); 2624 } catch (Exception e) { 2625 LOG.error("Could not read reference resource: " + conf.getReferencePath()); 2626 } 2627 } 2628 2629 if (!data.getGalleries().isEmpty()) { 2630 startGallery = getWorkplaceSettings().getLastUsedGallery(key); 2631 if (CmsStringUtil.isEmptyOrWhitespaceOnly(startGallery)) { 2632 // check the user preferences for any configured start gallery 2633 String galleryTypeName = data.getGalleries().get(0).getType(); 2634 startGallery = getWorkplaceSettings().getUserSettings().getStartGallery( 2635 galleryTypeName, 2636 getCmsObject()); 2637 if (CmsWorkplace.INPUT_DEFAULT.equals(startGallery)) { 2638 startGallery = OpenCms.getWorkplaceManager().getDefaultUserSettings().getStartGallery( 2639 galleryTypeName); 2640 } 2641 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(startGallery)) { 2642 startGallery = getCmsObject().getRequestContext().removeSiteRoot(startGallery); 2643 } 2644 } 2645 } 2646 // check if the gallery is available in this site and still exists 2647 if (!conf.isResultsSelectable()) { 2648 // if selecting results is explicitly disabled, opening the start gallery does not make much sense 2649 data.setStartGallery(null); 2650 } else if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(startGallery)) { 2651 boolean galleryExists = getCmsObject().existsResource(startGallery); 2652 if (galleryExists) { 2653 data.setStartGallery(startGallery); 2654 } else { 2655 LOG.error("Could not read start gallery: " + startGallery); 2656 data.setStartGallery(null); 2657 } 2658 } else { 2659 data.setStartGallery(null); 2660 } 2661 } 2662 2663 GalleryTabId defaultTab = conf.getTabConfiguration().getDefaultTab(); 2664 data.setTabConfiguration(conf.getTabConfiguration()); 2665 if (CmsStringUtil.isEmptyOrWhitespaceOnly(data.getStartGallery()) 2666 && CmsStringUtil.isEmptyOrWhitespaceOnly(data.getCurrentElement()) 2667 && CmsStringUtil.isEmptyOrWhitespaceOnly(data.getStartFolder())) { 2668 data.setStartTab(defaultTab); 2669 } else { 2670 data.setStartTab(GalleryTabId.cms_tab_results); 2671 } 2672 break; 2673 case ade: 2674 data.setReferenceSitePath(getCmsObject().getRequestContext().getUri()); 2675 types = getResourceTypeBeans( 2676 conf.getGalleryMode(), 2677 data.getReferenceSitePath(), 2678 conf.getResourceTypes(), 2679 conf.getSearchTypes()); 2680 data.setTypes(types); 2681 Map<String, CmsGalleryTypeInfo> adeGalleryTypeInfos = readGalleryInfosByTypeBeans(types); 2682 data.setGalleries(buildGalleriesList(data.getReferenceSitePath(), adeGalleryTypeInfos)); 2683 data.setStartTab(GalleryTabId.cms_tab_types); 2684 break; 2685 default: 2686 break; 2687 } 2688 2689 if (CmsStringUtil.isEmptyOrWhitespaceOnly(data.getStartGallery())) { 2690 Set<String> folderFilter = readFolderFilters(); 2691 data.setStartFolderFilter(folderFilter); 2692 if ((folderFilter != null) && !folderFilter.isEmpty()) { 2693 try { 2694 data.setVfsPreloadData( 2695 generateVfsPreloadData( 2696 getCmsObject(), 2697 CmsGalleryService.getVfsTreeState(getRequest(), conf.getTreeToken()), 2698 folderFilter)); 2699 } catch (Exception e) { 2700 LOG.error(e.getLocalizedMessage(), e); 2701 } 2702 } 2703 } 2704 2705 CmsSiteSelectorOptionBuilder optionBuilder = new CmsSiteSelectorOptionBuilder(getCmsObject()); 2706 optionBuilder.addNormalSites(true, getWorkplaceSettings().getUserSettings().getStartFolder()); 2707 optionBuilder.addSharedSite(); 2708 data.setVfsSiteSelectorOptions(optionBuilder.getOptions()); 2709 2710 CmsSiteSelectorOptionBuilder sitemapOptionBuilder = new CmsSiteSelectorOptionBuilder(getCmsObject()); 2711 sitemapOptionBuilder.addNormalSites(false, null); 2712 if (data.getReferenceSitePath() != null) { 2713 sitemapOptionBuilder.addCurrentSubsite(getCmsObject().addSiteRoot(data.getReferenceSitePath())); 2714 } 2715 data.setSitemapSiteSelectorOptions(sitemapOptionBuilder.getOptions()); 2716 data.setDefaultScope(OpenCms.getWorkplaceManager().getGalleryDefaultScope()); 2717 return data; 2718 } 2719 2720 /** 2721 * Reads the preview provider configuration and generates needed type-provider mappings.<p> 2722 * 2723 * @param types the resource types 2724 * 2725 * @return a map from resource types to preview providers 2726 */ 2727 private Map<I_CmsResourceType, I_CmsPreviewProvider> getPreviewProviderForTypes(List<I_CmsResourceType> types) { 2728 2729 Map<String, I_CmsPreviewProvider> previewProviderMap = new HashMap<String, I_CmsPreviewProvider>(); 2730 Map<I_CmsResourceType, I_CmsPreviewProvider> typeProviderMapping = new HashMap<I_CmsResourceType, I_CmsPreviewProvider>(); 2731 for (I_CmsResourceType type : types) { 2732 String providerClass = type.getGalleryPreviewProvider(); 2733 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(providerClass)) { 2734 providerClass = providerClass.trim(); 2735 try { 2736 if (previewProviderMap.containsKey(providerClass)) { 2737 typeProviderMapping.put(type, previewProviderMap.get(providerClass)); 2738 } else { 2739 I_CmsPreviewProvider previewProvider = (I_CmsPreviewProvider)Class.forName( 2740 providerClass).newInstance(); 2741 previewProviderMap.put(providerClass, previewProvider); 2742 typeProviderMapping.put(type, previewProvider); 2743 } 2744 } catch (Exception e) { 2745 logError( 2746 new CmsException( 2747 Messages.get().container( 2748 Messages.ERR_INSTANCING_PREVIEW_PROVIDER_2, 2749 providerClass, 2750 type.getTypeName()), 2751 e)); 2752 } 2753 } 2754 } 2755 return typeProviderMapping; 2756 } 2757 2758 /** 2759 * Returns the resourceManager.<p> 2760 * 2761 * @return the resourceManager 2762 */ 2763 private CmsResourceManager getResourceManager() { 2764 2765 if (m_resourceManager == null) { 2766 m_resourceManager = OpenCms.getResourceManager(); 2767 } 2768 return m_resourceManager; 2769 } 2770 2771 /** 2772 * Returns the resource types configured to be used within the given gallery mode.<p> 2773 * 2774 * @param galleryMode the gallery mode 2775 * @param referenceSitePath the reference site-path to check permissions for 2776 * @param resourceTypesList the resource types parameter 2777 * @param typesForTypeTab the types which should be shown in the types tab according to the gallery configuration 2778 * 2779 * @return the resource types 2780 */ 2781 private List<CmsResourceTypeBean> getResourceTypeBeans( 2782 GalleryMode galleryMode, 2783 String referenceSitePath, 2784 List<String> resourceTypesList, 2785 final List<String> typesForTypeTab) { 2786 2787 List<I_CmsResourceType> resourceTypes = null; 2788 Set<String> creatableTypes = null; 2789 switch (galleryMode) { 2790 case editor: 2791 case view: 2792 case adeView: 2793 case widget: 2794 resourceTypes = convertTypeNamesToTypes(resourceTypesList); 2795 if (resourceTypes.size() == 0) { 2796 resourceTypes = Lists.newArrayList(getDefaultTypesForGallery()); 2797 } 2798 creatableTypes = Collections.<String> emptySet(); 2799 break; 2800 case ade: 2801 throw new IllegalStateException("This code should never be called"); 2802 // ADE case is handled by container page service 2803 default: 2804 resourceTypes = Collections.<I_CmsResourceType> emptyList(); 2805 creatableTypes = Collections.<String> emptySet(); 2806 } 2807 return buildTypesList(resourceTypes, creatableTypes, Collections.<String> emptySet(), typesForTypeTab); 2808 } 2809 2810 /** 2811 * Returns the VFS root entries.<p> 2812 * 2813 * @return the VFS root entries 2814 * 2815 * @throws CmsRpcException if something goes wrong 2816 */ 2817 private List<CmsVfsEntryBean> getRootEntries() throws CmsRpcException { 2818 2819 List<CmsVfsEntryBean> rootFolders = new ArrayList<CmsVfsEntryBean>(); 2820 CmsObject cms = getCmsObject(); 2821 try { 2822 String path = "/"; 2823 if (!cms.existsResource(path, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 2824 String startFolder = getWorkplaceSettings().getUserSettings().getStartFolder(); 2825 if (cms.existsResource(startFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 2826 path = startFolder; 2827 } else { 2828 path = null; 2829 } 2830 } 2831 if (path != null) { 2832 CmsResource rootFolderResource = getCmsObject().readResource( 2833 path, 2834 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2835 String title = cms.readPropertyObject(path, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue(); 2836 rootFolders.add( 2837 internalCreateVfsEntryBean( 2838 getCmsObject(), 2839 rootFolderResource, 2840 title, 2841 true, 2842 isEditable(getCmsObject(), rootFolderResource), 2843 null, 2844 false)); 2845 } 2846 2847 } catch (CmsException e) { 2848 error(e); 2849 } 2850 return rootFolders; 2851 } 2852 2853 /** 2854 * Returns the workplace settings of the current user.<p> 2855 * 2856 * @return the workplace settings 2857 */ 2858 private CmsWorkplaceSettings getWorkplaceSettings() { 2859 2860 if (m_workplaceSettings == null) { 2861 m_workplaceSettings = CmsWorkplace.getWorkplaceSettings(getCmsObject(), getRequest()); 2862 } 2863 return m_workplaceSettings; 2864 } 2865 2866 /** 2867 * Checks whether a resource has a navigation property.<p> 2868 * 2869 * @param cms the current CMS context 2870 * @param resource the resource to use 2871 * 2872 * @return true if the resource has a navigation property 2873 * 2874 * @throws CmsException if something goes wrong 2875 */ 2876 private boolean hasNavigationProperty(CmsObject cms, CmsResource resource) throws CmsException { 2877 2878 List<CmsProperty> props = cms.readPropertyObjects(resource, false); 2879 Map<String, String> propMap = CmsProperty.toMap(props); 2880 return propMap.containsKey(CmsPropertyDefinition.PROPERTY_NAVPOS) 2881 || propMap.containsKey(CmsPropertyDefinition.PROPERTY_NAVTEXT); 2882 } 2883 2884 /** 2885 * Returns the search parameters for the given query data.<p> 2886 * 2887 * @param searchData the query data 2888 * @param replacementConfig the replacement configuration 2889 * 2890 * @return the prepared search parameters 2891 */ 2892 private CmsGallerySearchParameters prepareSearchParams( 2893 CmsGallerySearchBean searchData, 2894 CmsAddContentRestriction replacementConfig) { 2895 2896 // create a new search parameter object 2897 CmsGallerySearchParameters params = new CmsGallerySearchParameters(); 2898 CmsObject cms = getCmsObject(); 2899 2900 // set the selected types to the parameters 2901 if (searchData.getServerSearchTypes() != null) { 2902 params.setResourceTypes(searchData.getServerSearchTypes()); 2903 } 2904 2905 // set the selected galleries to the parameters 2906 if (searchData.getGalleries() != null) { 2907 List<String> paramGalleries = new ArrayList<String>(); 2908 for (String gallerySitePath : searchData.getGalleries()) { 2909 paramGalleries.add(cms.getRequestContext().addSiteRoot(gallerySitePath)); 2910 } 2911 params.setGalleries(paramGalleries); 2912 } 2913 2914 // set the sort order for the galleries to the parameters 2915 CmsGallerySearchParameters.CmsGallerySortParam sortOrder; 2916 String temp = searchData.getSortOrder(); 2917 try { 2918 sortOrder = CmsGallerySearchParameters.CmsGallerySortParam.valueOf(temp); 2919 } catch (Exception e) { 2920 sortOrder = CmsGallerySearchParameters.CmsGallerySortParam.DEFAULT; 2921 } 2922 params.setSortOrder(sortOrder); 2923 if (searchData.getScope() == null) { 2924 params.setScope(OpenCms.getWorkplaceManager().getGalleryDefaultScope()); 2925 } else { 2926 params.setScope(searchData.getScope()); 2927 } 2928 params.setReferencePath(searchData.getReferencePath()); 2929 2930 // set the selected folders to the parameters 2931 params.setFolders(new ArrayList<String>(searchData.getFolders())); 2932 2933 // set the categories to the parameters 2934 if (searchData.getCategories() != null) { 2935 params.setCategories(searchData.getCategories()); 2936 } 2937 2938 // set the search query to the parameters 2939 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(searchData.getQuery())) { 2940 params.setSearchWords(searchData.getQuery()); 2941 } 2942 2943 // set the result page to the parameters 2944 int page = searchData.getPage(); 2945 params.setResultPage(page); 2946 2947 // set the locale to the parameters 2948 String locale = searchData.getLocale(); 2949 if (CmsStringUtil.isEmptyOrWhitespaceOnly(locale)) { 2950 locale = getCmsObject().getRequestContext().getLocale().toString(); 2951 } 2952 params.setSearchLocale(locale); 2953 2954 // set the matches per page to the parameters 2955 params.setMatchesPerPage(searchData.getMatchesPerPage()); 2956 2957 // get the date range input 2958 long dateCreatedStart = searchData.getDateCreatedStart(); 2959 long dateCreatedEnd = searchData.getDateCreatedEnd(); 2960 long dateModifiedStart = searchData.getDateModifiedStart(); 2961 long dateModifiedEnd = searchData.getDateModifiedEnd(); 2962 2963 // set the date created range to the parameters 2964 if ((dateCreatedStart != -1L) && (dateCreatedEnd != -1L)) { 2965 params.setDateCreatedTimeRange(dateCreatedStart, dateCreatedEnd); 2966 } else if (dateCreatedStart != -1L) { 2967 params.setDateCreatedTimeRange(dateCreatedStart, Long.MAX_VALUE); 2968 } else if (dateCreatedEnd != -1L) { 2969 params.setDateCreatedTimeRange(Long.MIN_VALUE, dateCreatedEnd); 2970 } 2971 2972 // set the date modified range to the parameters 2973 if ((dateModifiedStart != -1L) && (dateModifiedEnd != -1L)) { 2974 params.setDateLastModifiedTimeRange(dateModifiedStart, dateModifiedEnd); 2975 } else if (dateModifiedStart != -1L) { 2976 params.setDateLastModifiedTimeRange(dateModifiedStart, Long.MAX_VALUE); 2977 } else if (dateModifiedEnd != -1L) { 2978 params.setDateLastModifiedTimeRange(Long.MIN_VALUE, dateModifiedEnd); 2979 } 2980 params.setIgnoreSearchExclude(searchData.isIgnoreSearchExclude()); 2981 if (GalleryMode.ade.equals(searchData.getGalleryMode())) { 2982 if (searchData.getTypes().isEmpty() || !Collections.disjoint(FUNCTION_TYPES, searchData.getTypes())) { 2983 CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration( 2984 cms, 2985 cms.getRequestContext().addSiteRoot(searchData.getReferencePath())); 2986 CmsFormatterConfigurationCacheState formatterState = OpenCms.getADEManager().getCachedFormatters( 2987 cms.getRequestContext().getCurrentProject().isOnlineProject()); 2988 params.setFunctionAvailability(config.getDynamicFunctionAvailability(formatterState)); 2989 if (config.isHideNonMatchingFunctions()) { 2990 if (searchData.getContainerInfo() != null) { 2991 Set<CmsUUID> excludedFunctions = getExcludedFunctionsForContainerInfo( 2992 cms, 2993 config, 2994 searchData.getContainerInfo()); 2995 params.setExcludedFunctions(excludedFunctions); 2996 } 2997 } 2998 } 2999 CmsTemplateContextInfo templateContextInfo = searchData.getTemplateContextInfo(); 3000 if ((templateContextInfo != null) 3001 && (templateContextInfo.getContextProvider() != null) 3002 && (templateContextInfo.getCurrentContext() != null)) { 3003 I_CmsTemplateContextProvider provider = OpenCms.getTemplateContextManager().getTemplateContextProvider( 3004 templateContextInfo.getContextProvider()); 3005 if (provider != null) { 3006 Set<CmsUUID> allowedFunctions = provider.getFunctionsForGallery( 3007 cms, 3008 templateContextInfo.getCurrentContext()); 3009 // allowed functions may be null - this is fine 3010 params.setIncludedFunctions(allowedFunctions); 3011 String compatibility = provider.getTemplateCompatibility(templateContextInfo.getCurrentContext()); 3012 params.setTemplateCompatibility(compatibility); 3013 } 3014 } 3015 if (replacementConfig != null) { 3016 // if the search replacement configuration didn't already handle the replacement, 3017 // exclude the type from search results (this happens when searching for multiple types). 3018 Set<String> excludedTypes = replacementConfig.getTypes(); 3019 if ((excludedTypes.size() > 0) && (params.getResourceTypes() != null)) { 3020 List<String> types = new ArrayList<>(params.getResourceTypes()); 3021 boolean removed = types.removeAll(excludedTypes); 3022 if (removed && (types.size() == 0)) { 3023 params.setForceEmptyResult(true); 3024 } 3025 params.setResourceTypes(types); 3026 } 3027 } 3028 } 3029 3030 // set include expired/unreleased 3031 if (searchData.isIncludeExpired()) { 3032 params.setIncludeExpired(true); 3033 } 3034 return params; 3035 } 3036 3037 /** 3038 * Prepares a sitemap entry bean from the given navigation element.<p> 3039 * 3040 * @param cms the cms context 3041 * @param navElement the navigation element 3042 * @param isRoot <code>true</code> if this is a site root entry 3043 * @param checkHasChildren if true, check if the entry has any children; set to false if you want to handle the list of children manually 3044 * 3045 * @return the sitemap entry 3046 * 3047 * @throws CmsException if something goes wrong reading types and resources 3048 */ 3049 private CmsSitemapEntryBean prepareSitemapEntry( 3050 CmsObject cms, 3051 CmsJspNavElement navElement, 3052 boolean isRoot, 3053 boolean checkHasChildren) 3054 throws CmsException { 3055 3056 CmsResource ownResource = navElement.getResource(); 3057 CmsResource defaultFileResource = null; 3058 CmsJspNavBuilder navBuilder = new CmsJspNavBuilder(cms); 3059 if (ownResource.isFolder() && !navElement.isNavigationLevel()) { 3060 try { 3061 defaultFileResource = cms.readDefaultFile(ownResource, CmsResourceFilter.ONLY_VISIBLE); 3062 } catch (CmsPermissionViolationException e) { 3063 // user has insufficient rights, can be ignored 3064 } 3065 } 3066 String type; 3067 if (defaultFileResource != null) { 3068 type = OpenCms.getResourceManager().getResourceType(defaultFileResource.getTypeId()).getTypeName(); 3069 } else { 3070 type = OpenCms.getResourceManager().getResourceType(ownResource.getTypeId()).getTypeName(); 3071 } 3072 // make sure not to show ??? NavText ??? 3073 String title = null; 3074 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(navElement.getProperty(CmsPropertyDefinition.PROPERTY_NAVTEXT))) { 3075 title = navElement.getProperty(CmsPropertyDefinition.PROPERTY_NAVTEXT); 3076 } else if (CmsStringUtil.isNotEmptyOrWhitespaceOnly( 3077 navElement.getProperty(CmsPropertyDefinition.PROPERTY_TITLE))) { 3078 title = navElement.getProperty(CmsPropertyDefinition.PROPERTY_TITLE); 3079 } else { 3080 title = navElement.getFileName(); 3081 if (title.contains("/")) { 3082 title = title.substring(0, title.indexOf("/")); 3083 } 3084 } 3085 String childPath = navElement.getResource().getRootPath(); 3086 boolean noChildren = true; 3087 3088 if (checkHasChildren) { 3089 List<CmsJspNavElement> childNav = navBuilder.getNavigationForFolder( 3090 childPath, 3091 Visibility.all, 3092 CmsResourceFilter.ONLY_VISIBLE); 3093 for (CmsJspNavElement childNavEntry : childNav) { 3094 if (childNavEntry.isInNavigation()) { 3095 noChildren = false; 3096 break; 3097 } 3098 } 3099 } 3100 3101 CmsSitemapEntryBean result = new CmsSitemapEntryBean( 3102 navElement.getResource().getRootPath(), 3103 navElement.getResourceName(), 3104 ownResource.getStructureId(), 3105 title, 3106 type, 3107 ownResource.isFolder(), 3108 isRoot, 3109 navElement.isHiddenNavigationEntry()); 3110 result.setSiteRoot(OpenCms.getSiteManager().getSiteRoot(ownResource.getRootPath())); 3111 String displayType = CmsIconUtil.getDisplayType( 3112 cms, 3113 defaultFileResource != null ? defaultFileResource : ownResource); 3114 result.setBigIconClasses( 3115 CmsIconUtil.getIconClasses( 3116 displayType, 3117 defaultFileResource != null ? defaultFileResource.getName() : ownResource.getName(), 3118 false)); 3119 result.setSmallIconClasses( 3120 CmsIconUtil.getIconClasses( 3121 displayType, 3122 defaultFileResource != null ? defaultFileResource.getName() : ownResource.getName(), 3123 true)); 3124 if (checkHasChildren && noChildren) { 3125 result.setChildren(new ArrayList<CmsSitemapEntryBean>()); 3126 } 3127 3128 return result; 3129 } 3130 3131 /** 3132 * Reads the folder filters for the current site.<p> 3133 * 3134 * @return the folder filters 3135 */ 3136 private Set<String> readFolderFilters() { 3137 3138 JSONObject storedFilters = readUserFolderFilters(); 3139 Set<String> result = null; 3140 if (storedFilters.has(getCmsObject().getRequestContext().getSiteRoot())) { 3141 try { 3142 org.opencms.json.JSONArray folders = storedFilters.getJSONArray( 3143 getCmsObject().getRequestContext().getSiteRoot()); 3144 result = new HashSet<String>(); 3145 for (int i = 0; i < folders.length(); i++) { 3146 result.add(folders.getString(i)); 3147 } 3148 } catch (JSONException e) { 3149 LOG.error(e.getLocalizedMessage(), e); 3150 } 3151 } 3152 return result; 3153 } 3154 3155 /** 3156 * Returns a map with gallery type names associated with the list of available galleries for this type.<p> 3157 * 3158 * @param resourceTypes the resources types to collect the galleries for 3159 * 3160 * @return a map with gallery type and the associated galleries 3161 */ 3162 private Map<String, CmsGalleryTypeInfo> readGalleryInfosByTypeBeans(List<CmsResourceTypeBean> resourceTypes) { 3163 3164 Map<String, CmsGalleryTypeInfo> galleryTypeInfos = new HashMap<String, CmsGalleryTypeInfo>(); 3165 for (CmsResourceTypeBean typeBean : resourceTypes) { 3166 try { 3167 if (!typeBean.isDeactivated()) { 3168 addGalleriesForType(galleryTypeInfos, typeBean.getType()); 3169 } 3170 } catch (CmsLoaderException e1) { 3171 logError(e1); 3172 } 3173 } 3174 return galleryTypeInfos; 3175 } 3176 3177 /** 3178 * Returns a map with gallery type names associated with the list of available galleries for this type.<p> 3179 * 3180 * @param resourceTypes the resources types to collect the galleries for 3181 * 3182 * @return a map with gallery type and the associated galleries 3183 */ 3184 private Map<String, CmsGalleryTypeInfo> readGalleryInfosByTypeNames(List<String> resourceTypes) { 3185 3186 Map<String, CmsGalleryTypeInfo> galleryTypeInfos = new HashMap<String, CmsGalleryTypeInfo>(); 3187 for (String typeName : resourceTypes) { 3188 try { 3189 addGalleriesForType(galleryTypeInfos, typeName); 3190 } catch (CmsLoaderException e1) { 3191 logError(e1); 3192 } 3193 } 3194 return galleryTypeInfos; 3195 } 3196 3197 /** 3198 * Reads the result view type from the current user.<p> 3199 * 3200 * @return the result view type 3201 */ 3202 private String readResultViewType() { 3203 3204 return (String)getCmsObject().getRequestContext().getCurrentUser().getAdditionalInfo( 3205 RESULT_VIEW_TYPE_ADD_INFO_KEY); 3206 } 3207 3208 /** 3209 * Reads the users folder filters from the additional info.<p> 3210 * 3211 * @return the folder filters 3212 */ 3213 private JSONObject readUserFolderFilters() { 3214 3215 CmsUser user = getCmsObject().getRequestContext().getCurrentUser(); 3216 String addInfo = (String)user.getAdditionalInfo(FOLDER_FILTER_ADD_INFO_KEY); 3217 JSONObject result = null; 3218 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(addInfo)) { 3219 try { 3220 result = new JSONObject(addInfo); 3221 } catch (JSONException e) { 3222 LOG.error(e.getLocalizedMessage(), e); 3223 } 3224 } 3225 if (result == null) { 3226 result = new JSONObject(); 3227 } 3228 return result; 3229 } 3230 3231 /** 3232 * Returns the gallery search object containing the results for the current parameter.<p> 3233 * 3234 * @param searchObj the current search object 3235 * 3236 * @return the search result 3237 * 3238 * @throws CmsException if the search fails 3239 */ 3240 private CmsGallerySearchBean search(CmsGallerySearchBean searchObj) throws CmsException { 3241 3242 CmsGallerySearchBean searchObjBean = new CmsGallerySearchBean(searchObj); 3243 if (searchObj == null) { 3244 return searchObjBean; 3245 } 3246 // store folder filter 3247 storeFolderFilter(searchObj.getFolders()); 3248 CmsObject cms = getCmsObject(); 3249 CmsADEConfigData config = OpenCms.getADEManager().lookupConfigurationWithCache( 3250 cms, 3251 cms.getRequestContext().addSiteRoot(cms.getRequestContext().getUri())); 3252 CmsAddContentRestriction replacementConfig = config.getAddContentRestriction(); 3253 CmsGallerySearchResultList searchResults = null; 3254 List<String> types = searchObj.getTypes(); 3255 Predicate<CmsResource> deactivatedCheck = res -> false; 3256 if (searchObj.getGalleryMode().equals(GalleryMode.ade) 3257 && types.contains(CmsResourceTypeFunctionConfig.TYPE_NAME) 3258 && !config.isHideNonMatchingFunctions() 3259 && (searchObj.getContainerInfo() != null)) { 3260 final Set<CmsUUID> excludedFunctions = getExcludedFunctionsForContainerInfo( 3261 cms, 3262 config, 3263 searchObj.getContainerInfo()); 3264 deactivatedCheck = res -> excludedFunctions.contains(res.getStructureId()); 3265 } 3266 3267 searchObjBean.setReplacedResults(false); 3268 if (searchObj.getGalleryMode().equals(GalleryMode.ade) 3269 && (types.size() == 1) 3270 && replacementConfig.getTypes().contains(types.iterator().next())) { 3271 3272 List<CmsGallerySearchResult> items = replacementConfig.getResult(cms, types.iterator().next()); 3273 searchResults = new CmsGallerySearchResultList(); 3274 searchResults.addAll(items); 3275 searchObjBean.setReplacedResults(true); 3276 searchObjBean.setPage(1); 3277 searchObjBean.setFolders(new HashSet<>()); 3278 searchObjBean.setGalleries(new ArrayList<>()); 3279 searchObjBean.setCategories(new ArrayList<>()); 3280 // searchObjBean.setMatchesPerPage(searchResults.size()); 3281 searchObjBean.setNoUploadReason( 3282 Messages.get().getBundle(m_wpLocale).key(Messages.GUI_NO_UPLOAD_FOR_REPLACED_SEARCH_RESULTS_0)); 3283 searchObjBean.setResults(buildSearchResultList(searchResults, null, deactivatedCheck)); 3284 searchObjBean.setResultCount(searchResults.size()); 3285 if (searchObjBean.getResultCount() > 0) { 3286 CmsADESessionCache cache = CmsADESessionCache.getCache(getRequest(), getCmsObject()); 3287 cache.setLastPageEditorGallerySearch(searchObj); 3288 } 3289 3290 } else { 3291 // search 3292 CmsGallerySearchParameters params = prepareSearchParams(searchObj, replacementConfig); 3293 CmsObject searchCms = getSearchCms(searchObj); 3294 searchResults = OpenCms.getSearchManager().getIndexSolr("Solr Offline").gallerySearch(searchCms, params); 3295 searchResults.calculatePages(params.getResultPage(), params.getMatchesPerPage()); 3296 3297 // set only the result dependent search params for this search 3298 // the user dependent params(galleries, types etc.) remain unchanged 3299 searchObjBean.setSortOrder(params.getSortOrder().name()); 3300 searchObjBean.setScope(params.getScope()); 3301 searchObjBean.setResultCount(searchResults.getHitCount()); 3302 searchObjBean.setPage(params.getResultPage()); 3303 searchObjBean.setLastPage(params.getResultPage()); 3304 searchObjBean.setResults(buildSearchResultList(searchResults, null, deactivatedCheck)); 3305 if (searchObj.getGalleryMode().equals(GalleryMode.ade)) { 3306 if (searchObjBean.getResultCount() > 0) { 3307 CmsADESessionCache cache = CmsADESessionCache.getCache(getRequest(), getCmsObject()); 3308 cache.setLastPageEditorGallerySearch(searchObj); 3309 } 3310 } 3311 updateNoUploadReason(searchCms, searchObjBean); 3312 } 3313 return searchObjBean; 3314 } 3315 3316 /** 3317 * Sets the last opened gallery information for the current user.<p> 3318 * 3319 * @param searchObject the current search 3320 */ 3321 private void setLastOpenedGallery(CmsGallerySearchBean searchObject) { 3322 3323 if ((searchObject.getGalleries() != null) 3324 && (searchObject.getGalleries().size() <= 1) // if the size is 0, the user has actively deselected the galleries, so we want to handle this case too 3325 && searchObject.haveGalleriesChanged()) { 3326 String galleryPath = searchObject.getGalleries().isEmpty() ? null : searchObject.getGalleries().get(0); 3327 CmsWorkplaceSettings settings = getWorkplaceSettings(); 3328 if (searchObject.getGalleryMode() == GalleryMode.adeView) { 3329 settings.setLastUsedGallery("" + GalleryMode.adeView, galleryPath); 3330 } else { 3331 String referencePath = searchObject.getReferencePath(); 3332 3333 String referenceTypeName = ""; 3334 3335 try { 3336 CmsObject cms = getCmsObject(); 3337 CmsResource referenceResource = cms.readResource(referencePath); 3338 I_CmsResourceType referenceType = OpenCms.getResourceManager().getResourceType(referenceResource); 3339 referenceTypeName = referenceType.getTypeName(); 3340 } catch (CmsException e) { 3341 LOG.error(e.getLocalizedMessage(), e); 3342 } 3343 settings.setLastUsedGallery( 3344 CmsGallerySearchBean.getGalleryStorageKey( 3345 searchObject.getGalleryStoragePrefix(), 3346 referenceTypeName), 3347 galleryPath); 3348 } 3349 } 3350 } 3351 3352 /** 3353 * Stores the folder filters for the current site.<p> 3354 * 3355 * @param folders the folder filters 3356 */ 3357 private void storeFolderFilter(Set<String> folders) { 3358 3359 JSONObject storedFilters = readUserFolderFilters(); 3360 try { 3361 storedFilters.put(getCmsObject().getRequestContext().getSiteRoot(), folders); 3362 CmsUser user = getCmsObject().getRequestContext().getCurrentUser(); 3363 user.setAdditionalInfo(FOLDER_FILTER_ADD_INFO_KEY, storedFilters.toString()); 3364 getCmsObject().writeUser(user); 3365 } catch (Exception e) { 3366 LOG.error(e.getLocalizedMessage(), e); 3367 } 3368 } 3369 3370 /** 3371 * Checks the current users permissions on the upload target folder to update the no upload reason.<p> 3372 * 3373 * @param searchCms the cms context 3374 * @param searchObj the search data 3375 */ 3376 private void updateNoUploadReason(CmsObject searchCms, CmsGallerySearchBean searchObj) { 3377 3378 if ((searchObj.getGalleries().size() + searchObj.getFolders().size()) == 1) { 3379 String target = !searchObj.getGalleries().isEmpty() 3380 ? searchObj.getGalleries().get(0) 3381 : searchObj.getFolders().iterator().next(); 3382 try { 3383 CmsResource targetRes; 3384 if (searchCms.existsResource(target, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 3385 targetRes = searchCms.readResource(target, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3386 } else { 3387 CmsObject rootCms = OpenCms.initCmsObject(searchCms); 3388 rootCms.getRequestContext().setSiteRoot(""); 3389 targetRes = rootCms.readResource(target, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3390 } 3391 searchObj.setNoUploadReason( 3392 new CmsResourceUtil(searchCms, targetRes).getNoEditReason(getWorkplaceLocale(), true)); 3393 } catch (CmsException e) { 3394 searchObj.setNoUploadReason(e.getLocalizedMessage(getWorkplaceLocale())); 3395 } 3396 } else { 3397 searchObj.setNoUploadReason(null); 3398 } 3399 } 3400}