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