001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.widgets;
029
030import org.opencms.ade.configuration.CmsADEConfigData;
031import org.opencms.ade.configuration.CmsResourceTypeConfig;
032import org.opencms.ade.galleries.shared.CmsGalleryTabConfiguration;
033import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants;
034import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.GalleryMode;
035import org.opencms.file.CmsObject;
036import org.opencms.file.CmsResource;
037import org.opencms.file.types.CmsResourceTypeBinary;
038import org.opencms.file.types.CmsResourceTypeImage;
039import org.opencms.file.types.CmsResourceTypePlain;
040import org.opencms.file.types.CmsResourceTypeXmlContainerPage;
041import org.opencms.i18n.CmsMessages;
042import org.opencms.json.JSONException;
043import org.opencms.json.JSONObject;
044import org.opencms.main.CmsLog;
045import org.opencms.main.OpenCms;
046import org.opencms.util.CmsMacroResolver;
047import org.opencms.util.CmsStringUtil;
048import org.opencms.workplace.CmsWorkplace;
049import org.opencms.xml.content.I_CmsXmlContentHandler.DisplayType;
050import org.opencms.xml.types.A_CmsXmlContentValue;
051
052import java.util.Arrays;
053import java.util.List;
054import java.util.Locale;
055import java.util.Set;
056
057import org.apache.commons.collections.Factory;
058import org.apache.commons.logging.Log;
059
060import com.google.common.base.Objects;
061
062/**
063 * Provides a OpenCms VFS file selection widget, for use on a widget dialog.<p>
064 *
065 * @since 6.0.0
066 */
067public class CmsVfsFileWidget extends A_CmsWidget implements I_CmsADEWidget {
068
069    /** Macro resolver factory to get the default searchable types. */
070    protected class SearchTypesFactory implements Factory {
071
072        /** The CMS context. */
073        private CmsObject m_cms;
074
075        /** The resource. */
076        private CmsResource m_resource;
077
078        /**
079         * Constructor.<p>
080         *
081         * @param cms the CMS context
082         * @param resource the resource
083         */
084        public SearchTypesFactory(CmsObject cms, CmsResource resource) {
085
086            m_cms = cms;
087            m_resource = resource;
088        }
089
090        /**
091         * @see org.apache.commons.collections.Factory#create()
092         */
093        public Object create() {
094
095            return getDefaultSearchTypes(m_cms, m_resource);
096        }
097    }
098
099    /** Configuration parameter to set the flag to include files in popup resource tree. */
100    public static final String CONFIGURATION_EXCLUDEFILES = "excludefiles";
101
102    /** Configuration parameter to restrict the widget to gallery selection only. */
103    public static final String CONFIGURATION_GALLERYSELECT = "galleryselect";
104
105    /** Configuration parameter to set the flag to show the site selector in popup resource tree. */
106    public static final String CONFIGURATION_HIDESITESELECTOR = "hidesiteselector";
107
108    /** Configuration parameter to set the flag to include files in popup resource tree. */
109    public static final String CONFIGURATION_INCLUDEFILES = "includefiles";
110
111    /** Configuration parameter to prevent the project awareness flag in the popup resource tree. */
112    public static final String CONFIGURATION_NOTPROJECTAWARE = "notprojectaware";
113
114    /** Configuration parameter to set the project awareness flag in the popup resource tree. */
115    public static final String CONFIGURATION_PROJECTAWARE = "projectaware";
116
117    /** Configuration parameter to set search types of the gallery widget. */
118    public static final String CONFIGURATION_SEARCHTYPES = "searchtypes";
119
120    /** Configuration parameter to set the selectable types of the gallery widget. */
121    public static final String CONFIGURATION_SELECTABLETYPES = "selectabletypes";
122
123    /** Configuration parameter to set the flag to show the site selector in popup resource tree. */
124    public static final String CONFIGURATION_SHOWSITESELECTOR = "showsiteselector";
125
126    /** Configuration parameter to set start folder. */
127    public static final String CONFIGURATION_STARTFOLDER = "startfolder";
128
129    /** Configuration parameter to set start site of the popup resource tree. */
130    public static final String CONFIGURATION_STARTSITE = "startsite";
131
132    /** The default search types macro name. */
133    public static final String DEFAULT_SEARCH_TYPES_MACRO = "defaultSearchTypes";
134
135    /** The logger instance for this class. */
136    private static final Log LOG = CmsLog.getLog(CmsVfsFileWidget.class);
137
138    /** Flag which, when set, restricts the user to select only galleries or folders. */
139    private boolean m_gallerySelect;
140
141    /** Flag to determine if files should be shown in popup window. */
142    private boolean m_includeFiles;
143
144    /** Flag to determine project awareness, ie. if resources outside of the current project should be displayed as normal. */
145    private boolean m_projectAware;
146
147    /** The type shown in the gallery types tab. */
148    private String m_searchTypes;
149
150    /** The types that may be selected through the gallery widget. */
151    private String m_selectableTypes;
152
153    /** Flag to determine if the site selector should be shown in popup window. */
154    private boolean m_showSiteSelector;
155
156    /** The start folder. */
157    private String m_startFolder;
158
159    /** The start site used in the popup window. */
160    private String m_startSite;
161
162    /**
163     * Creates a new vfs file widget.<p>
164     */
165    public CmsVfsFileWidget() {
166
167        // empty constructor is required for class registration
168        this("");
169    }
170
171    /**
172     * Creates a new vfs file widget with the parameters to configure the popup tree window behavior.<p>
173     *
174     * @param showSiteSelector true if the site selector should be shown in the popup window
175     * @param startSite the start site root for the popup window
176     */
177    public CmsVfsFileWidget(boolean showSiteSelector, String startSite) {
178
179        this(showSiteSelector, startSite, true);
180    }
181
182    /**
183     * Creates a new vfs file widget with the parameters to configure the popup tree window behavior.<p>
184     *
185     * @param showSiteSelector true if the site selector should be shown in the popup window
186     * @param startSite the start site root for the popup window
187     * @param includeFiles true if files should be shown in the popup window
188     */
189    public CmsVfsFileWidget(boolean showSiteSelector, String startSite, boolean includeFiles) {
190
191        this(showSiteSelector, startSite, includeFiles, true);
192    }
193
194    /**
195     * Creates a new vfs file widget with the parameters to configure the popup tree window behavior.<p>
196     *
197     * @param showSiteSelector true if the site selector should be shown in the popup window
198     * @param startSite the start site root for the popup window
199     * @param includeFiles <code>true</code> if files should be shown in the popup window
200     * @param projectAware <code>true</code> if resources outside of the current project should be displayed as normal
201     */
202    public CmsVfsFileWidget(boolean showSiteSelector, String startSite, boolean includeFiles, boolean projectAware) {
203
204        m_showSiteSelector = showSiteSelector;
205        m_startSite = startSite;
206        m_includeFiles = includeFiles;
207        m_projectAware = projectAware;
208    }
209
210    /**
211     * Creates a new vfs file widget with the given configuration.<p>
212     *
213     * @param configuration the configuration to use
214     */
215    public CmsVfsFileWidget(String configuration) {
216
217        super(configuration);
218    }
219
220    /**
221     * Returns a comma separated list of the default search type names.<p>
222     *
223     * @param cms the CMS context
224     * @param resource the edited resource
225     *
226     * @return a comma separated list of the default search type names
227     */
228    public static String getDefaultSearchTypes(CmsObject cms, CmsResource resource) {
229
230        StringBuffer result = new StringBuffer();
231        String referenceSitePath = cms.getSitePath(resource);
232        String configPath;
233        if (resource == null) {
234            // not sure if this can ever happen?
235            configPath = cms.addSiteRoot(cms.getRequestContext().getUri());
236        } else {
237            configPath = resource.getRootPath();
238        }
239        CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration(cms, configPath);
240        Set<String> detailPageTypes = OpenCms.getADEManager().getDetailPageTypes(cms);
241        for (CmsResourceTypeConfig typeConfig : config.getResourceTypes()) {
242            String typeName = typeConfig.getTypeName();
243            if (!detailPageTypes.contains(typeName)) {
244                continue;
245            }
246            if (typeConfig.checkViewable(cms, referenceSitePath)) {
247                result.append(typeName).append(",");
248            }
249        }
250        result.append(CmsResourceTypeXmlContainerPage.getStaticTypeName()).append(",");
251        result.append(CmsResourceTypeBinary.getStaticTypeName()).append(",");
252        result.append(CmsResourceTypeImage.getStaticTypeName()).append(",");
253        result.append(CmsResourceTypePlain.getStaticTypeName());
254        return result.toString();
255    }
256
257    /**
258     * @see org.opencms.widgets.A_CmsWidget#getConfiguration()
259     */
260    @Override
261    public String getConfiguration() {
262
263        StringBuffer result = new StringBuffer(8);
264
265        // append site selector flag to configuration
266        if (m_showSiteSelector) {
267            result.append(CONFIGURATION_SHOWSITESELECTOR);
268        } else {
269            result.append(CONFIGURATION_HIDESITESELECTOR);
270        }
271
272        // append start site to configuration
273        if (m_startSite != null) {
274            result.append("|");
275            result.append(CONFIGURATION_STARTSITE);
276            result.append("=");
277            result.append(m_startSite);
278        }
279
280        // append flag for including files
281        result.append("|");
282        if (m_includeFiles) {
283            result.append(CONFIGURATION_INCLUDEFILES);
284        } else {
285            result.append(CONFIGURATION_EXCLUDEFILES);
286        }
287
288        if (m_gallerySelect) {
289            result.append("|");
290            result.append(CONFIGURATION_GALLERYSELECT);
291        }
292
293        // append flag for project awareness
294        result.append("|");
295        if (m_projectAware) {
296            result.append(CONFIGURATION_PROJECTAWARE);
297        } else {
298            result.append(CONFIGURATION_NOTPROJECTAWARE);
299        }
300        if (m_searchTypes != null) {
301            result.append("|");
302            result.append(CONFIGURATION_SEARCHTYPES);
303            result.append("=");
304            result.append(m_searchTypes);
305        }
306        if (m_selectableTypes != null) {
307            result.append("|");
308            result.append(CONFIGURATION_SELECTABLETYPES);
309            result.append("=");
310            result.append(m_selectableTypes);
311        }
312        return result.toString();
313    }
314
315    /**
316     * @see org.opencms.widgets.I_CmsADEWidget#getConfiguration(org.opencms.file.CmsObject, org.opencms.xml.types.A_CmsXmlContentValue, org.opencms.i18n.CmsMessages, org.opencms.file.CmsResource, java.util.Locale)
317     */
318    public String getConfiguration(
319        CmsObject cms,
320        A_CmsXmlContentValue schemaType,
321        CmsMessages messages,
322        CmsResource resource,
323        Locale contentLocale) {
324
325        JSONObject config = getJsonConfig(cms, schemaType, messages, resource, contentLocale);
326        return config.toString();
327    }
328
329    /**
330     * @see org.opencms.widgets.I_CmsADEWidget#getCssResourceLinks(org.opencms.file.CmsObject)
331     */
332    public List<String> getCssResourceLinks(CmsObject cms) {
333
334        return null;
335    }
336
337    /**
338     * @see org.opencms.widgets.I_CmsADEWidget#getDefaultDisplayType()
339     */
340    public DisplayType getDefaultDisplayType() {
341
342        return DisplayType.wide;
343    }
344
345    /**
346     * @see org.opencms.widgets.I_CmsWidget#getDialogIncludes(org.opencms.file.CmsObject, org.opencms.widgets.I_CmsWidgetDialog)
347     */
348    @Override
349    public String getDialogIncludes(CmsObject cms, I_CmsWidgetDialog widgetDialog) {
350
351        StringBuffer result = new StringBuffer(16);
352        result.append(getJSIncludeFile(CmsWorkplace.getSkinUri() + "commons/tree.js"));
353        result.append("\n");
354        result.append(getJSIncludeFile(CmsWorkplace.getSkinUri() + "components/widgets/fileselector.js"));
355        return result.toString();
356    }
357
358    /**
359     * @see org.opencms.widgets.I_CmsWidget#getDialogInitCall(org.opencms.file.CmsObject, org.opencms.widgets.I_CmsWidgetDialog)
360     */
361    @Override
362    public String getDialogInitCall(CmsObject cms, I_CmsWidgetDialog widgetDialog) {
363
364        return "\tinitVfsFileSelector();\n";
365    }
366
367    /**
368     * @see org.opencms.widgets.I_CmsWidget#getDialogInitMethod(org.opencms.file.CmsObject, org.opencms.widgets.I_CmsWidgetDialog)
369     */
370    @Override
371    public String getDialogInitMethod(CmsObject cms, I_CmsWidgetDialog widgetDialog) {
372
373        StringBuffer result = new StringBuffer(16);
374        result.append("function initVfsFileSelector() {\n");
375        //initialize tree javascript, does parts of <code>CmsTree.initTree(CmsObject, encoding, skinuri);</code>
376        result.append("\tinitResources(\"");
377        result.append(OpenCms.getWorkplaceManager().getEncoding());
378        result.append("\", \"");
379        result.append(CmsWorkplace.VFS_PATH_WORKPLACE);
380        result.append("\", \"");
381        result.append(CmsWorkplace.getSkinUri());
382        result.append("\", \"");
383        result.append(OpenCms.getSystemInfo().getOpenCmsContext());
384        result.append("\");\n");
385        result.append("}\n");
386        return result.toString();
387    }
388
389    /**
390     * @see org.opencms.widgets.I_CmsWidget#getDialogWidget(org.opencms.file.CmsObject, org.opencms.widgets.I_CmsWidgetDialog, org.opencms.widgets.I_CmsWidgetParameter)
391     */
392    public String getDialogWidget(CmsObject cms, I_CmsWidgetDialog widgetDialog, I_CmsWidgetParameter param) {
393
394        String id = param.getId();
395        StringBuffer result = new StringBuffer(128);
396
397        result.append("<td class=\"xmlTd\">");
398        result.append(
399            "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"maxwidth\"><tr><td style=\"width: 100%;\">");
400        result.append("<input style=\"width: 99%;\" class=\"xmlInput");
401        if (param.hasError()) {
402            result.append(" xmlInputError");
403        }
404        result.append("\" value=\"");
405        result.append(param.getStringValue(cms));
406        result.append("\" name=\"");
407        result.append(id);
408        result.append("\" id=\"");
409        result.append(id);
410        result.append("\"></td>");
411        result.append(widgetDialog.dialogHorizontalSpacer(10));
412        result.append(
413            "<td><table class=\"editorbuttonbackground\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>");
414
415        StringBuffer buttonJs = new StringBuffer(8);
416        buttonJs.append("javascript:openTreeWin('EDITOR',  '");
417        buttonJs.append(id);
418        buttonJs.append("', document, ");
419        buttonJs.append(m_showSiteSelector);
420        buttonJs.append(", '");
421        if (m_startSite != null) {
422            buttonJs.append(m_startSite);
423        } else {
424            buttonJs.append(cms.getRequestContext().getSiteRoot());
425        }
426        buttonJs.append("', ");
427        // include files
428        buttonJs.append(m_includeFiles);
429        // project awareness
430        buttonJs.append(", ");
431        buttonJs.append(m_projectAware);
432        buttonJs.append(");return false;");
433
434        result.append(
435            widgetDialog.button(
436                buttonJs.toString(),
437                null,
438                "folder",
439                org.opencms.workplace.Messages.GUI_DIALOG_BUTTON_SEARCH_0,
440                widgetDialog.getButtonStyle()));
441        result.append("</tr></table>");
442        result.append("</td></tr></table>");
443
444        result.append("</td>");
445
446        return result.toString();
447    }
448
449    /**
450     * @see org.opencms.widgets.I_CmsADEWidget#getInitCall()
451     */
452    public String getInitCall() {
453
454        return null;
455    }
456
457    /**
458     * @see org.opencms.widgets.I_CmsADEWidget#getJavaScriptResourceLinks(org.opencms.file.CmsObject)
459     */
460    public List<String> getJavaScriptResourceLinks(CmsObject cms) {
461
462        return null;
463    }
464
465    /**
466     * Returns the start site root shown by the widget when first displayed.<p>
467     *
468     * If <code>null</code> is returned, the dialog will display the current site of
469     * the current user.<p>
470     *
471     * @return the start site root shown by the widget when first displayed
472     */
473    public String getStartSite() {
474
475        return m_startSite;
476    }
477
478    /**
479     * @see org.opencms.widgets.I_CmsADEWidget#getWidgetName()
480     */
481    public String getWidgetName() {
482
483        return CmsVfsFileWidget.class.getName();
484    }
485
486    /**
487     * @see org.opencms.widgets.I_CmsADEWidget#isInternal()
488     */
489    public boolean isInternal() {
490
491        return true;
492    }
493
494    /**
495     * Returns <code>true</code> if the site selector is shown.<p>
496     *
497     * The default is <code>true</code>.<p>
498     *
499     * @return <code>true</code> if the site selector is shown
500     */
501    public boolean isShowingSiteSelector() {
502
503        return m_showSiteSelector;
504    }
505
506    /**
507     * @see org.opencms.widgets.I_CmsWidget#newInstance()
508     */
509    public I_CmsWidget newInstance() {
510
511        return new CmsVfsFileWidget(getConfiguration());
512    }
513
514    /**
515     * @see org.opencms.widgets.A_CmsWidget#setConfiguration(java.lang.String)
516     */
517    @Override
518    public void setConfiguration(String configuration) {
519
520        m_showSiteSelector = true;
521        m_includeFiles = true;
522        m_projectAware = true;
523
524        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(configuration)) {
525            if (configuration.contains(CONFIGURATION_HIDESITESELECTOR)) {
526                // site selector should be hidden
527                m_showSiteSelector = false;
528            }
529            int siteIndex = configuration.indexOf(CONFIGURATION_STARTSITE);
530            if (siteIndex != -1) {
531                // start site is given
532                String site = configuration.substring(siteIndex + CONFIGURATION_STARTSITE.length() + 1);
533                if (site.indexOf('|') != -1) {
534                    // cut eventual following configuration values
535                    site = site.substring(0, site.indexOf('|'));
536                }
537                m_startSite = site;
538            }
539            if (configuration.contains(CONFIGURATION_EXCLUDEFILES)) {
540                // files should not be included
541                m_includeFiles = false;
542            }
543            if (configuration.contains(CONFIGURATION_GALLERYSELECT)) {
544                m_gallerySelect = true;
545            }
546
547            if (configuration.contains(CONFIGURATION_NOTPROJECTAWARE)) {
548                // resources outside of the current project should not be disabled
549                m_projectAware = false;
550            }
551            int searchTypesIndex = configuration.indexOf(CONFIGURATION_SEARCHTYPES);
552            if (searchTypesIndex != -1) {
553                String searchTypes = configuration.substring(searchTypesIndex + CONFIGURATION_SEARCHTYPES.length() + 1);
554                if (searchTypes.contains("|")) {
555                    m_searchTypes = searchTypes.substring(0, searchTypes.indexOf("|"));
556                } else {
557                    m_searchTypes = searchTypes;
558                }
559            }
560            int selectableTypesIndex = configuration.indexOf(CONFIGURATION_SELECTABLETYPES);
561            if (selectableTypesIndex != -1) {
562                String selectableTypes = configuration.substring(
563                    selectableTypesIndex + CONFIGURATION_SELECTABLETYPES.length() + 1);
564                if (selectableTypes.contains("|")) {
565                    m_selectableTypes = selectableTypes.substring(0, selectableTypes.indexOf("|"));
566                } else {
567                    m_selectableTypes = selectableTypes;
568                }
569            }
570            int startFolderIndex = configuration.indexOf(CONFIGURATION_STARTFOLDER);
571            if (startFolderIndex != -1) {
572                String startFolder = configuration.substring(startFolderIndex + CONFIGURATION_STARTFOLDER.length() + 1);
573                if (startFolder.contains("|")) {
574                    m_startFolder = startFolder.substring(0, startFolder.indexOf("|"));
575                } else {
576                    m_startFolder = startFolder;
577                }
578            }
579        }
580        super.setConfiguration(configuration);
581    }
582
583    /**
584     * Gets the JSON configuration.<p>
585     *
586     * @param cms the current CMS context
587     * @param schemaType the schema type
588     * @param messages the messages
589     * @param resource the content resource
590     * @param contentLocale the content locale
591     *
592     * @return the JSON configuration object
593     */
594    protected JSONObject getJsonConfig(
595        CmsObject cms,
596        A_CmsXmlContentValue schemaType,
597        CmsMessages messages,
598        CmsResource resource,
599        Locale contentLocale) {
600
601        JSONObject config = new JSONObject();
602        try {
603            config.put(I_CmsGalleryProviderConstants.CONFIG_START_SITE, m_startSite);
604
605            config.put(I_CmsGalleryProviderConstants.CONFIG_SHOW_SITE_SELECTOR, m_showSiteSelector);
606            config.put(I_CmsGalleryProviderConstants.CONFIG_REFERENCE_PATH, cms.getSitePath(resource));
607            config.put(I_CmsGalleryProviderConstants.CONFIG_LOCALE, contentLocale.toString());
608            config.put(I_CmsGalleryProviderConstants.CONFIG_GALLERY_MODE, GalleryMode.widget.name());
609            config.put(I_CmsGalleryProviderConstants.CONFIG_GALLERY_STORAGE_PREFIX, "linkselect");
610            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_selectableTypes)) {
611                config.put(I_CmsGalleryProviderConstants.CONFIG_RESOURCE_TYPES, m_selectableTypes.trim());
612            }
613            String tabConfig = null;
614            if (m_includeFiles) {
615                tabConfig = CmsGalleryTabConfiguration.TC_SELECT_ALL;
616                if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_selectableTypes)
617                    && !Arrays.asList(m_selectableTypes.split("[, ]+")).contains(
618                        CmsResourceTypeXmlContainerPage.getStaticTypeName())) {
619                    tabConfig = CmsGalleryTabConfiguration.TC_SELECT_ALL_NO_SITEMAP;
620                }
621            } else {
622                tabConfig = CmsGalleryTabConfiguration.TC_FOLDERS;
623            }
624            config.put(I_CmsGalleryProviderConstants.CONFIG_TAB_CONFIG, tabConfig);
625            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_searchTypes)) {
626                CmsMacroResolver resolver = CmsMacroResolver.newInstance();
627                resolver.addDynamicMacro(DEFAULT_SEARCH_TYPES_MACRO, new SearchTypesFactory(cms, resource));
628                String searchTypes = resolver.resolveMacros(m_searchTypes.trim());
629                config.put(I_CmsGalleryProviderConstants.CONFIG_SEARCH_TYPES, searchTypes);
630            } else if (CmsStringUtil.isEmptyOrWhitespaceOnly(m_selectableTypes)) {
631                config.put(I_CmsGalleryProviderConstants.CONFIG_SEARCH_TYPES, getDefaultSearchTypes(cms, resource));
632            }
633            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_startFolder)) {
634                config.put(I_CmsGalleryProviderConstants.CONFIG_START_FOLDER, m_startFolder);
635            }
636            String treeToken = ""
637                + Objects.hashCode(m_startSite, cms.getRequestContext().getSiteRoot(), "" + m_selectableTypes);
638            config.put(I_CmsGalleryProviderConstants.CONFIG_TREE_TOKEN, treeToken);
639
640            if (m_gallerySelect) {
641                config.put(I_CmsGalleryProviderConstants.CONFIG_GALLERIES_SELECTABLE, "true");
642                config.put(I_CmsGalleryProviderConstants.CONFIG_RESULTS_SELECTABLE, "false");
643                config.put(I_CmsGalleryProviderConstants.CONFIG_TAB_CONFIG, CmsGalleryTabConfiguration.TC_GALLERIES);
644            }
645
646        } catch (JSONException e) {
647            LOG.error(e.getLocalizedMessage(), e);
648        }
649        return config;
650    }
651
652    /**
653     * Computes the tree token, which is used to decide which preloaded tree, if any, to load for the VFS/sitemap tabs.<p>
654     *
655     * @param cms the current CMS context
656     * @param value the content value
657     * @param resource the content resource
658     * @param contentLocale the content locale
659     *
660     * @return the tree token
661     */
662    protected String getTreeToken(
663        CmsObject cms,
664        A_CmsXmlContentValue value,
665        CmsResource resource,
666        Locale contentLocale) {
667
668        return cms.getRequestContext().getSiteRoot();
669    }
670}