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