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