001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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: https://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: https://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.workplace;
029
030import org.opencms.ade.configuration.CmsElementView;
031import org.opencms.ade.containerpage.shared.CmsCntPageData.ElementDeleteMode;
032import org.opencms.ade.contenteditor.CmsDummyTranslator;
033import org.opencms.ade.contenteditor.I_CmsContentTranslator;
034import org.opencms.ade.galleries.shared.CmsGallerySearchScope;
035import org.opencms.ade.upload.CmsDefaultUploadRestriction;
036import org.opencms.ade.upload.I_CmsUploadRestriction;
037import org.opencms.ade.upload.I_CmsVirusScanner;
038import org.opencms.configuration.CmsAdditionalLogFolderConfig;
039import org.opencms.configuration.CmsDefaultUserSettings;
040import org.opencms.db.CmsExportPoint;
041import org.opencms.db.CmsUserSettings;
042import org.opencms.db.I_CmsProjectDriver;
043import org.opencms.file.CmsFolder;
044import org.opencms.file.CmsObject;
045import org.opencms.file.CmsProject;
046import org.opencms.file.CmsPropertyDefinition;
047import org.opencms.file.CmsRequestContext;
048import org.opencms.file.CmsResource;
049import org.opencms.file.CmsResourceFilter;
050import org.opencms.file.CmsUser;
051import org.opencms.file.CmsVfsResourceNotFoundException;
052import org.opencms.file.types.CmsResourceTypeFolder;
053import org.opencms.file.types.CmsResourceTypeFolderExtended;
054import org.opencms.file.types.I_CmsResourceType;
055import org.opencms.i18n.CmsAcceptLanguageHeaderParser;
056import org.opencms.i18n.CmsEncoder;
057import org.opencms.i18n.CmsI18nInfo;
058import org.opencms.i18n.CmsLocaleComparator;
059import org.opencms.i18n.CmsLocaleManager;
060import org.opencms.i18n.I_CmsLocaleHandler;
061import org.opencms.loader.CmsLoaderException;
062import org.opencms.main.CmsBroadcast.ContentMode;
063import org.opencms.main.CmsEvent;
064import org.opencms.main.CmsException;
065import org.opencms.main.CmsLog;
066import org.opencms.main.I_CmsEventListener;
067import org.opencms.main.OpenCms;
068import org.opencms.module.CmsModule;
069import org.opencms.module.CmsModuleManager;
070import org.opencms.relations.CmsCategoryService;
071import org.opencms.security.CmsOrganizationalUnit;
072import org.opencms.security.CmsPermissionSet;
073import org.opencms.security.CmsPermissionViolationException;
074import org.opencms.security.CmsRole;
075import org.opencms.security.CmsRoleViolationException;
076import org.opencms.security.CmsSecurityException;
077import org.opencms.security.I_CmsPrincipal;
078import org.opencms.util.CmsRfsFileViewer;
079import org.opencms.util.CmsStringUtil;
080import org.opencms.util.CmsUUID;
081import org.opencms.workplace.CmsAccountInfo.Field;
082import org.opencms.workplace.editors.CmsEditorDisplayOptions;
083import org.opencms.workplace.editors.CmsEditorHandler;
084import org.opencms.workplace.editors.CmsWorkplaceEditorManager;
085import org.opencms.workplace.editors.I_CmsEditorActionHandler;
086import org.opencms.workplace.editors.I_CmsEditorCssHandler;
087import org.opencms.workplace.editors.I_CmsEditorHandler;
088import org.opencms.workplace.editors.I_CmsPreEditorActionDefinition;
089import org.opencms.workplace.editors.directedit.CmsDirectEditDefaultProvider;
090import org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider;
091import org.opencms.workplace.explorer.CmsExplorerTypeAccess;
092import org.opencms.workplace.explorer.CmsExplorerTypeSettings;
093import org.opencms.workplace.galleries.A_CmsAjaxGallery;
094import org.opencms.workplace.tools.CmsToolManager;
095
096import java.io.IOException;
097import java.io.UnsupportedEncodingException;
098import java.net.URL;
099import java.util.ArrayList;
100import java.util.Arrays;
101import java.util.Collections;
102import java.util.Enumeration;
103import java.util.HashMap;
104import java.util.HashSet;
105import java.util.Iterator;
106import java.util.List;
107import java.util.Locale;
108import java.util.Map;
109import java.util.Set;
110import java.util.concurrent.TimeUnit;
111import java.util.jar.Manifest;
112import java.util.regex.Pattern;
113import java.util.regex.PatternSyntaxException;
114
115import javax.servlet.http.HttpServletRequest;
116import javax.servlet.http.HttpSession;
117
118import org.apache.commons.logging.Log;
119
120import com.google.common.cache.Cache;
121import com.google.common.cache.CacheBuilder;
122import com.google.common.collect.Lists;
123import com.google.common.collect.Maps;
124import com.google.common.collect.Sets;
125
126/**
127 * Manages the global OpenCms workplace settings for all users.<p>
128 *
129 * This class reads the settings from the "opencms.properties" and stores them in member variables.
130 * For each setting one or more get methods are provided.<p>
131 *
132 * @since 6.0.0
133 */
134public final class CmsWorkplaceManager implements I_CmsLocaleHandler, I_CmsEventListener {
135
136    /**
137     * Helper class used to easily define default view mappings for standard resource types.<p>
138     */
139    static class ViewRules {
140
141        /**
142         * Internal view map.<p>
143         */
144        private Map<String, String> m_viewMap = Maps.newHashMap();
145
146        /**
147         * Creates a new instance.<p>
148         *
149         * @param rules an array of strings of the form 'foo,bar,baz:view1', where foo, ... are type names and view1 is a view name (explorertype)
150         */
151        public ViewRules(String... rules) {
152
153            for (String rule : rules) {
154                int colIndex = rule.indexOf(':');
155                if (colIndex != -1) {
156                    String before = rule.substring(0, colIndex);
157                    String after = rule.substring(colIndex + 1);
158                    for (String token : CmsStringUtil.splitAsList(before, ",")) {
159                        m_viewMap.put(token.trim(), after);
160                    }
161                }
162
163            }
164        }
165
166        /**
167         * Gets the view configured for the given type.<p>
168         *
169         * @param type a resource type name
170         * @return the view explorer type for the given resource type
171         */
172        public String getViewForType(String type) {
173
174            return m_viewMap.get(type);
175
176        }
177    }
178
179    /** The default encoding for the workplace (UTF-8). */
180    public static final String DEFAULT_WORKPLACE_ENCODING = CmsEncoder.ENCODING_UTF_8;
181
182    /** The workplace localization manifest attribute name. */
183    public static final String LOCALIZATION_ATTRIBUTE_NAME = "OpenCms-Localization";
184
185    /** The manifest file resource name. */
186    public static final String MANIFEST_RESOURCE_NAME = "META-INF/MANIFEST.MF";
187
188    /** The id of the "requestedResource" parameter for the OpenCms login form. */
189    public static final String PARAM_LOGIN_REQUESTED_RESOURCE = "requestedResource";
190
191    /** Key name for the session workplace settings. */
192    public static final String SESSION_WORKPLACE_SETTINGS = "__CmsWorkplace.WORKPLACE_SETTINGS";
193
194    /** Default view configuration. */
195    static ViewRules m_defaultViewRules = new ViewRules(
196        "folder,plain,jsp,htmlredirect,containerpage:view_basic",
197        "imagegallery,downloadgallery,linkgallery,subsitemap,content_folder:view_folders",
198        "formatter_config,xmlvfsbundle,propertyvfsbundle,bundledescriptor,sitemap_config,sitemap_master_config,site_plugin,attr_editor_config,module_config,elementview,seo_file,containerpage_template,inheritance_config,macro_formatter,flex_formatter,settings_config:view_configs",
199        "xmlcontent,pointer:view_other");
200
201    /** The default account infos. */
202    private static final CmsAccountInfo[] DEFAULT_ACCOUNT_INFOS = new CmsAccountInfo[] {
203        new CmsAccountInfo(Field.firstname, null, false),
204        new CmsAccountInfo(Field.lastname, null, false),
205        new CmsAccountInfo(Field.email, null, false),
206        new CmsAccountInfo(Field.institution, null, false)};
207
208    /** The logger for this class. */
209    private static final Log LOG = CmsLog.getLog(CmsWorkplaceManager.class);
210
211    /** Value of the acacia-unlock configuration option (may be null if not set). */
212    private String m_acaciaUnlock;
213
214    /** The configured account infos. */
215    private List<CmsAccountInfo> m_accountInfos;
216
217    /** The admin cms context. */
218    private CmsObject m_adminCms;
219
220    /** If enabled, gives element authors more gallery-related permissions (mostly upload/replace). */
221    private boolean m_allowElementAuthorToWorkInGalleries;
222
223    /** Indicates if auto-locking of resources is enabled or disabled. */
224    private boolean m_autoLockResources;
225
226    /** The name of the local category folder(s). */
227    private String m_categoryFolder;
228
229    /** The configured content translation engine. */
230    private I_CmsContentTranslator m_contentTranslation;
231
232    /** The default access for explorer types. */
233    private CmsExplorerTypeAccess m_defaultAccess;
234
235    /** The default content translation engine. */
236    private I_CmsContentTranslator m_defaultContentTranslation = new CmsDummyTranslator();
237
238    /** The configured default locale of the workplace. */
239    private Locale m_defaultLocale;
240
241    /** The default property setting for setting new property values. */
242    private boolean m_defaultPropertiesOnStructure;
243
244    /** The default user settings. */
245    private CmsDefaultUserSettings m_defaultUserSettings;
246
247    /** The configured dialog handlers. */
248    private Map<String, I_CmsDialogHandler> m_dialogHandler;
249
250    /** The configured direct edit provider. */
251    private I_CmsDirectEditProvider m_directEditProvider;
252
253    /** A flag, indicating if the categories should be displayed separated by repository in the category selection dialog. */
254    private boolean m_displayCategoriesByRepository;
255
256    /** A flag, indicating if the categories should be displayed separated by repository in the category selection dialog. */
257    private boolean m_displayCategorySelectionCollapsed;
258
259    /** The edit action handler. */
260    private I_CmsEditorActionHandler m_editorAction;
261
262    /** The editor CSS handlers. */
263    private List<I_CmsEditorCssHandler> m_editorCssHandlers;
264
265    /** The workplace editor display options. */
266    private CmsEditorDisplayOptions m_editorDisplayOptions;
267
268    /** The editor handler. */
269    private I_CmsEditorHandler m_editorHandler;
270
271    /** The editor manager. */
272    private CmsWorkplaceEditorManager m_editorManager;
273
274    /** The element delete mode. */
275    private ElementDeleteMode m_elementDeleteMode;
276
277    /** The flag if switching tabs in the advanced property dialog is enabled. */
278    private boolean m_enableAdvancedPropertyTabs;
279
280    /** The configured encoding of the workplace. */
281    private String m_encoding;
282
283    /** Categories column enabled? */
284    private boolean m_explorerCategoriesEnabled;
285
286    /** Show only leaf categories in explorer? */
287    private boolean m_explorerCategoriesLeavesOnly;
288
289    /** Show categories with their path in the explorer? */
290    private boolean m_explorerCategoriesWithPath;
291
292    /** The explorer type settings. */
293    private List<CmsExplorerTypeSettings> m_explorerTypeSettings;
294
295    /** The explorer type settings from the configured modules. */
296    private List<CmsExplorerTypeSettings> m_explorerTypeSettingsFromModules;
297
298    /** The explorer type settings from the XML configuration. */
299    private List<CmsExplorerTypeSettings> m_explorerTypeSettingsFromXml;
300
301    /** The explorer type settings as Map with resource type name as key. */
302    private Map<String, CmsExplorerTypeSettings> m_explorerTypeSettingsMap;
303
304    /** The element views generated from explorer types. */
305    private Map<CmsUUID, CmsElementView> m_explorerTypeViews = Maps.newHashMap();
306
307    /** The workplace export points. */
308    private Set<CmsExportPoint> m_exportPoints;
309
310    /** Maximum size of an upload file. */
311    private int m_fileMaxUploadSize;
312
313    /** The instance used for reading portions of lines of a file to choose. */
314    private CmsRfsFileViewer m_fileViewSettings;
315
316    /** The configured workplace galleries. */
317    private Map<String, A_CmsAjaxGallery> m_galleries;
318
319    /** The configured gallery default scope. */
320    private String m_galleryDefaultScope;
321
322    /** The group translation. */
323    private I_CmsGroupNameTranslation m_groupNameTranslation;
324
325    /** The configured group translation class name. */
326    private String m_groupTranslationClass;
327
328    /** Keep-alive flag. */
329    private Boolean m_keepAlive;
330
331    /** Contains all folders that should be labeled if siblings exist. */
332    private List<String> m_labelSiteFolders;
333
334    /** List of installed workplace locales, sorted ascending. */
335    private List<Locale> m_locales;
336
337    /** The configured list of localized workplace folders. */
338    private List<String> m_localizedFolders;
339
340    /** The additional log folder configuration. */
341    private CmsAdditionalLogFolderConfig m_logFolderConfig = new CmsAdditionalLogFolderConfig();
342
343    /** Max number of locale buttons to display in the editor. */
344    private int m_maxLocaleButtons = 5;
345
346    /** The workplace localized messages (mapped to the locales). */
347    private Map<Locale, CmsWorkplaceMessages> m_messages;
348
349    /** The post upload handler. */
350    private I_CmsPostUploadDialogHandler m_postUploadHandler;
351
352    /** The condition definitions for the resource types  which are triggered before opening the editor. */
353    private List<I_CmsPreEditorActionDefinition> m_preEditorConditionDefinitions;
354
355    /** The repository folder handler. */
356    private I_CmsRepositoryFolderHandler m_repositoryFolderHandler;
357
358    /** Indicates if the user management icon should be displayed in the workplace. */
359    private boolean m_showUserGroupIcon;
360
361    /** The role required for editing the sitemap configuration. */
362    private String m_sitemapConfigEditRole;
363
364    /** Configured name of the role users should have to manage detail pages from the sitemap editor. */
365    private String m_sitemapEditorDetailPageManagementRole;
366
367    /** Exclude patterns for synchronization. */
368    private ArrayList<Pattern> m_synchronizeExcludePatterns;
369
370    /** The temporary file project used by the editors. */
371    private CmsProject m_tempFileProject;
372
373    /** The tool manager. */
374    private CmsToolManager m_toolManager;
375
376    /** The upload restriction. */
377    private I_CmsUploadRestriction m_uploadRestriction = CmsDefaultUploadRestriction.unrestricted();
378
379    /** Keeps track of whether the upload restriction has been set. */
380    private boolean m_uploadRestrictionSet;
381
382    /** The user additional information configuration. */
383    private CmsWorkplaceUserInfoManager m_userInfoManager;
384
385    /** The user list mode. */
386    private String m_userListMode;
387
388    /** The configured workplace views. */
389    private List<CmsWorkplaceView> m_views;
390
391    /** The configured virus scanner. */
392    private I_CmsVirusScanner m_virusScanner;
393
394    /** True if the virus scanner is enabled. */
395    private boolean m_virusScannerEnabled;
396
397    /** Expiring cache used to limit the number of notifications sent because of invalid workplace server names. */
398    private Cache<String, String> m_workplaceServerUserChecks;
399
400    /** The XML content auto correction flag. */
401    private boolean m_xmlContentAutoCorrect;
402
403    /**
404     * Creates a new instance for the workplace manager, will be called by the workplace configuration manager.<p>
405     */
406    public CmsWorkplaceManager() {
407
408        if (CmsLog.INIT.isInfoEnabled()) {
409            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_WORKPLACE_INITIALIZE_START_0));
410        }
411
412        m_locales = new ArrayList<Locale>();
413        m_labelSiteFolders = new ArrayList<String>();
414        m_localizedFolders = new ArrayList<String>();
415        m_autoLockResources = true;
416        m_categoryFolder = CmsCategoryService.REPOSITORY_BASE_FOLDER;
417        m_xmlContentAutoCorrect = true;
418        m_showUserGroupIcon = true;
419        m_dialogHandler = new HashMap<String, I_CmsDialogHandler>();
420        m_views = new ArrayList<CmsWorkplaceView>();
421        m_exportPoints = new HashSet<CmsExportPoint>();
422        m_editorHandler = new CmsEditorHandler();
423        m_fileMaxUploadSize = -1;
424        m_fileViewSettings = new CmsRfsFileViewer();
425        m_explorerTypeSettingsFromXml = new ArrayList<CmsExplorerTypeSettings>();
426        m_explorerTypeSettingsFromModules = new ArrayList<CmsExplorerTypeSettings>();
427        m_defaultPropertiesOnStructure = true;
428        m_enableAdvancedPropertyTabs = true;
429        m_defaultUserSettings = new CmsDefaultUserSettings();
430        m_defaultAccess = new CmsExplorerTypeAccess();
431        m_galleries = new HashMap<String, A_CmsAjaxGallery>();
432        flushMessageCache();
433        m_preEditorConditionDefinitions = new ArrayList<I_CmsPreEditorActionDefinition>();
434        m_editorCssHandlers = new ArrayList<I_CmsEditorCssHandler>();
435        m_synchronizeExcludePatterns = new ArrayList<Pattern>();
436
437        // important to set this to null to avoid unnecessary overhead during configuration phase
438        m_explorerTypeSettings = null;
439        CacheBuilder<Object, Object> cb = CacheBuilder.newBuilder().expireAfterWrite(
440            2,
441            TimeUnit.MINUTES).concurrencyLevel(3);
442        m_workplaceServerUserChecks = cb.build();
443    }
444
445    /**
446     * Returns true if the provided request was done by a Workplace user.<p>
447     *
448     * @param req the request to check
449     *
450     * @return true if the provided request was done by a Workplace user
451     */
452    public static boolean isWorkplaceUser(HttpServletRequest req) {
453
454        HttpSession session = req.getSession(false);
455        if (session != null) {
456            // if a session is available, check for a workplace configuration
457            CmsWorkplaceSettings workplaceSettings = (CmsWorkplaceSettings)session.getAttribute(
458                CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS);
459            return ((null != workplaceSettings) && !workplaceSettings.getUser().isGuestUser());
460        }
461        // no session means no workplace use
462        return false;
463    }
464
465    /**
466     * Adds an account info.<p>
467     *
468     * @param info the account info to add
469     */
470    public void addAccountInfo(CmsAccountInfo info) {
471
472        if (m_accountInfos == null) {
473            m_accountInfos = new ArrayList<CmsAccountInfo>();
474        }
475        m_accountInfos.add(info);
476    }
477
478    /**
479     * Adds an account info.<p>
480     *
481     * @param field the field
482     * @param addInfoKey the additional info key
483     * @param editable the editable flag
484     */
485    public void addAccountInfo(String field, String addInfoKey, String editable) {
486
487        addAccountInfo(new CmsAccountInfo(field, addInfoKey, editable));
488    }
489
490    /**
491     * Adds a dialog handler instance to the list of configured dialog handlers.<p>
492     *
493     * @param clazz the instantiated dialog handler to add
494     */
495    public void addDialogHandler(I_CmsDialogHandler clazz) {
496
497        m_dialogHandler.put(clazz.getDialogHandler(), clazz);
498        if (CmsLog.INIT.isInfoEnabled()) {
499            CmsLog.INIT.info(
500                Messages.get().getBundle().key(
501                    Messages.INIT_ADD_DIALOG_HANDLER_2,
502                    clazz.getDialogHandler(),
503                    clazz.getClass().getName()));
504        }
505    }
506
507    /**
508     * Adds an editor CSS handler class to the list of handlers.<p>
509     *
510     * @param editorCssHandlerClassName full class name of the css handler class
511     */
512    public void addEditorCssHandler(String editorCssHandlerClassName) {
513
514        try {
515            I_CmsEditorCssHandler editorCssHandler = (I_CmsEditorCssHandler)Class.forName(
516                editorCssHandlerClassName).newInstance();
517            m_editorCssHandlers.add(editorCssHandler);
518            if (CmsLog.INIT.isInfoEnabled()) {
519                CmsLog.INIT.info(
520                    Messages.get().getBundle().key(Messages.INIT_EDITOR_CSSHANDLER_CLASS_1, editorCssHandlerClassName));
521            }
522        } catch (Exception e) {
523            LOG.error(
524                Messages.get().getBundle().key(Messages.LOG_INVALID_EDITOR_CSSHANDLER_1, editorCssHandlerClassName),
525                e);
526        }
527    }
528
529    /**
530     * Adds an editor CSS handler class at the first position of the list of handlers.<p>
531     *
532     * @param editorCssHandlerClassName full class name of the css handler class
533     */
534    public void addEditorCssHandlerToHead(String editorCssHandlerClassName) {
535
536        try {
537            I_CmsEditorCssHandler editorCssHandler = (I_CmsEditorCssHandler)Class.forName(
538                editorCssHandlerClassName).newInstance();
539
540            List<I_CmsEditorCssHandler> editorCssHandlers = new ArrayList<I_CmsEditorCssHandler>();
541            editorCssHandlers.add(editorCssHandler);
542            editorCssHandlers.addAll(m_editorCssHandlers);
543
544            m_editorCssHandlers = editorCssHandlers;
545
546            if (CmsLog.INIT.isInfoEnabled()) {
547                CmsLog.INIT.info(
548                    Messages.get().getBundle().key(Messages.INIT_EDITOR_CSSHANDLER_CLASS_1, editorCssHandlerClassName));
549            }
550        } catch (Exception e) {
551            LOG.error(
552                Messages.get().getBundle().key(Messages.LOG_INVALID_EDITOR_CSSHANDLER_1, editorCssHandlerClassName),
553                e);
554        }
555    }
556
557    /**
558     * Adds an explorer type setting object to the list of type settings.<p>
559     *
560     * @param settings the explorer type settings
561     */
562    public void addExplorerTypeSetting(CmsExplorerTypeSettings settings) {
563
564        m_explorerTypeSettingsFromXml.add(settings);
565        if (CmsLog.INIT.isInfoEnabled()) {
566            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_ADD_TYPE_SETTING_1, settings.getName()));
567        }
568        if (m_explorerTypeSettings != null) {
569            // reset the list of all explorer type settings, but not during startup
570            initExplorerTypeSettings();
571        }
572    }
573
574    /**
575     * Adds the list of explorer type settings from the given module.<p>
576     *
577     * @param module the module witch contains the explorer type settings to add
578     */
579    public void addExplorerTypeSettings(CmsModule module) {
580
581        List<CmsExplorerTypeSettings> explorerTypes = module.getExplorerTypes();
582        if ((explorerTypes != null) && (explorerTypes.size() > 0)) {
583            Iterator<CmsExplorerTypeSettings> i = explorerTypes.iterator();
584            while (i.hasNext()) {
585                CmsExplorerTypeSettings settings = i.next();
586                if (m_explorerTypeSettingsFromModules.contains(settings)) {
587                    m_explorerTypeSettingsFromModules.remove(settings);
588                }
589                m_explorerTypeSettingsFromModules.add(settings);
590                if (CmsLog.INIT.isInfoEnabled()) {
591                    CmsLog.INIT.info(
592                        Messages.get().getBundle().key(Messages.INIT_ADD_TYPE_SETTING_1, settings.getName()));
593                }
594            }
595            // reset the list of all explorer type settings
596            initExplorerTypeSettings();
597        }
598    }
599
600    /**
601     * Adds newly created export point to the workplace configuration.<p>
602     *
603     * @param uri the export point uri
604     * @param destination the export point destination
605     */
606    public void addExportPoint(String uri, String destination) {
607
608        CmsExportPoint point = new CmsExportPoint(uri, destination);
609        m_exportPoints.add(point);
610        if (CmsLog.INIT.isInfoEnabled() && (point.getDestinationPath() != null)) {
611            CmsLog.INIT.info(
612                Messages.get().getBundle().key(
613                    Messages.INIT_ADD_EXPORT_POINT_2,
614                    point.getUri(),
615                    point.getDestinationPath()));
616        }
617    }
618
619    /**
620     * Adds a folder to the list of labeled folders.<p>
621     *
622     * @param uri the folder uri to add
623     */
624    public void addLabeledFolder(String uri) {
625
626        m_labelSiteFolders.add(uri);
627        if (CmsLog.INIT.isInfoEnabled()) {
628            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_LABEL_LINKS_IN_FOLDER_1, uri));
629        }
630    }
631
632    /**
633     * Adds a new folder to the list of localized workplace folders.<p>
634     *
635     * @param uri a new folder to add to the list of localized workplace folders
636     */
637    public void addLocalizedFolder(String uri) {
638
639        m_localizedFolders.add(uri);
640        if (CmsLog.INIT.isInfoEnabled()) {
641            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_WORKPLACE_LOCALIZED_1, uri));
642        }
643    }
644
645    /**
646     * Adds an initialized condition definition class that is triggered before opening the editor.<p>
647     *
648     * @param preEditorCondition the initialized condition definition class
649     */
650    public void addPreEditorConditionDefinition(I_CmsPreEditorActionDefinition preEditorCondition) {
651
652        m_preEditorConditionDefinitions.add(preEditorCondition);
653        if (CmsLog.INIT.isInfoEnabled()) {
654            CmsLog.INIT.info(
655                Messages.get().getBundle().key(
656                    Messages.INIT_EDITOR_PRE_ACTION_2,
657                    preEditorCondition.getClass().getName(),
658                    preEditorCondition.getResourceTypeName()));
659        }
660    }
661
662    /**
663     * Adds a condition definition class for a given resource type name that is triggered before opening the editor.<p>
664     *
665     * @param resourceTypeName the name of the resource type
666     * @param preEditorConditionDefinitionClassName full class name of the condition definition class
667     */
668    public void addPreEditorConditionDefinition(String resourceTypeName, String preEditorConditionDefinitionClassName) {
669
670        try {
671            I_CmsPreEditorActionDefinition preEditorCondition = (I_CmsPreEditorActionDefinition)Class.forName(
672                preEditorConditionDefinitionClassName).newInstance();
673            preEditorCondition.setResourceTypeName(resourceTypeName);
674            m_preEditorConditionDefinitions.add(preEditorCondition);
675            if (CmsLog.INIT.isInfoEnabled()) {
676                CmsLog.INIT.info(
677                    Messages.get().getBundle().key(
678                        Messages.INIT_EDITOR_PRE_ACTION_2,
679                        preEditorConditionDefinitionClassName,
680                        resourceTypeName));
681            }
682        } catch (Exception e) {
683            LOG.error(
684                Messages.get().getBundle().key(
685                    Messages.LOG_INVALID_EDITOR_PRE_ACTION_1,
686                    preEditorConditionDefinitionClassName),
687                e);
688        }
689    }
690
691    /**
692     * Adds a pattern to be excluded in VFS synchronization.<p>
693     *
694     * @param pattern a java regex to applied on the file name
695     */
696    public void addSynchronizeExcludePattern(String pattern) {
697
698        try {
699            m_synchronizeExcludePatterns.add(Pattern.compile(pattern));
700        } catch (PatternSyntaxException e) {
701            LOG.error(Messages.get().getBundle().key(Messages.LOG_INVALID_SYNCHRONIZE_EXCLUDE_PATTERN_1, pattern), e);
702        }
703    }
704
705    /**
706     * Returns if the autolock resources feature is enabled.<p>
707     *
708     * @return true if the autolock resources feature is enabled, otherwise false
709     */
710    public boolean autoLockResources() {
711
712        return m_autoLockResources;
713    }
714
715    /**
716     * Checks if the user in the given context has permissions for uploading.
717     *
718     * @param cms a CMS context
719     * @throws CmsSecurityException if the user doesn't have permission
720     */
721    public void checkAdeGalleryUpload(CmsObject cms) throws CmsSecurityException {
722
723        OpenCms.getRoleManager().checkRole(cms, getUploadRole());
724    }
725
726    /**
727     * Checks whether the workplace is accessed through the workplace server, and sends an error message otherwise.<p>
728     *
729     * @param request the request to check
730     * @param cms the CmsObject to use
731     */
732    public void checkWorkplaceRequest(HttpServletRequest request, CmsObject cms) {
733
734        try {
735            if ((OpenCms.getSiteManager().getSites().size() > 1)
736                && !OpenCms.getSiteManager().isWorkplaceRequest(request)) {
737                // this is a multi site-configuration, but not a request to the configured Workplace site
738
739                CmsUser user = cms.getRequestContext().getCurrentUser();
740                // to limit the number of times broadcast is called for a user, we use an expiring cache
741                // with the user name as  key
742                if (null == m_workplaceServerUserChecks.getIfPresent(user.getName())) {
743                    m_workplaceServerUserChecks.put(user.getName(), "");
744                    OpenCms.getSessionManager().sendBroadcast(
745                        null,
746                        Messages.get().getBundle(getWorkplaceLocale(cms)).key(
747                            Messages.ERR_WORKPLACE_SERVER_CHECK_FAILED_0),
748                        user,
749                        ContentMode.plain);
750
751                }
752
753            }
754        } catch (Exception e) {
755            LOG.error(e.getLocalizedMessage(), e);
756        }
757    }
758
759    /**
760     * Implements the event listener of this class.<p>
761     *
762     * @see org.opencms.main.I_CmsEventListener#cmsEvent(org.opencms.main.CmsEvent)
763     */
764    public void cmsEvent(CmsEvent event) {
765
766        switch (event.getType()) {
767            case I_CmsEventListener.EVENT_CLEAR_CACHES:
768                flushMessageCache();
769                m_editorDisplayOptions.clearCache();
770                if (LOG.isDebugEnabled()) {
771                    LOG.debug(Messages.get().getBundle().key(Messages.LOG_EVENT_CLEAR_CACHES_0));
772                }
773                break;
774            default: // no operation
775        }
776    }
777
778    /**
779     * Creates a temporary file which is needed while working in an editor with preview option.<p>
780     *
781     * <i>Note</i>: This method is synchronized to avoid rare issues that might be caused by
782     * double requests fired by some browser/OS combinations.<p>
783     *
784     * @param cms the cms context
785     * @param resourceName the name of the resource to copy
786     * @param currentProjectId the id of the project to work with
787     *
788     * @return the file name of the temporary file
789     *
790     * @throws CmsException if something goes wrong
791     */
792    public synchronized String createTempFile(CmsObject cms, String resourceName, CmsUUID currentProjectId)
793    throws CmsException {
794
795        // check that the current user has write permissions
796        if (!cms.hasPermissions(cms.readResource(resourceName, CmsResourceFilter.ALL), CmsPermissionSet.ACCESS_WRITE)) {
797            throw new CmsPermissionViolationException(
798                org.opencms.db.Messages.get().container(org.opencms.db.Messages.ERR_PERM_DENIED_2, resourceName, "w"));
799        }
800
801        // initialize admin cms context
802        CmsObject adminCms = getAdminCms(cms);
803
804        // generate the filename of the temporary file
805        String temporaryFilename = CmsWorkplace.getTemporaryFileName(resourceName);
806
807        // check if the temporary file is already present
808        if (adminCms.existsResource(temporaryFilename, CmsResourceFilter.ALL)) {
809            // delete old temporary file
810            if (!cms.getLock(temporaryFilename).isUnlocked()) {
811                // steal lock
812                cms.changeLock(temporaryFilename);
813            } else {
814                // lock resource to current user
815                cms.lockResource(temporaryFilename);
816            }
817            cms.deleteResource(temporaryFilename, CmsResource.DELETE_PRESERVE_SIBLINGS);
818        }
819
820        try {
821            // switch to the temporary file project
822            adminCms.getRequestContext().setCurrentProject(cms.readProject(getTempFileProjectId()));
823            // copy the file to edit to a temporary file
824            adminCms.copyResource(resourceName, temporaryFilename, CmsResource.COPY_AS_NEW);
825        } finally {
826            // switch back to current project
827            adminCms.getRequestContext().setCurrentProject(cms.readProject(currentProjectId));
828        }
829
830        try {
831            // switch to the temporary file project
832            cms.getRequestContext().setCurrentProject(
833                cms.readProject(OpenCms.getWorkplaceManager().getTempFileProjectId()));
834            // lock the temporary file
835            cms.changeLock(temporaryFilename);
836            // touch the temporary file
837            cms.setDateLastModified(temporaryFilename, System.currentTimeMillis(), false);
838            // set the temporary file flag
839            CmsResource tempFile = cms.readResource(temporaryFilename, CmsResourceFilter.ALL);
840            int flags = tempFile.getFlags();
841            if ((flags & CmsResource.FLAG_TEMPFILE) == 0) {
842                flags += CmsResource.FLAG_TEMPFILE;
843            }
844            cms.chflags(temporaryFilename, flags);
845            // remove eventual release & expiration date from temporary file to make preview in editor work
846            cms.setDateReleased(temporaryFilename, CmsResource.DATE_RELEASED_DEFAULT, false);
847            cms.setDateExpired(temporaryFilename, CmsResource.DATE_EXPIRED_DEFAULT, false);
848            // remove visibility permissions for everybody on temporary file if possible
849            if (cms.hasPermissions(tempFile, CmsPermissionSet.ACCESS_CONTROL)) {
850                cms.chacc(
851                    temporaryFilename,
852                    I_CmsPrincipal.PRINCIPAL_GROUP,
853                    OpenCms.getDefaultUsers().getGroupUsers(),
854                    "-v");
855            }
856        } finally {
857            // switch back to current project
858            cms.getRequestContext().setCurrentProject(cms.readProject(currentProjectId));
859        }
860
861        return temporaryFilename;
862    }
863
864    /**
865     * Flushes the cached workplace messages.<p>
866     */
867    public void flushMessageCache() {
868
869        // clear the cached message objects
870        m_messages = new HashMap<Locale, CmsWorkplaceMessages>();
871        if (LOG.isDebugEnabled()) {
872            try {
873                throw new RuntimeException("Tracing exception");
874            } catch (Exception e) {
875                LOG.info("Tracing call to CmsWorkplaceManager.flushMessageCache method.", e);
876            }
877        }
878    }
879
880    /**
881     * Gets the value of the acacia-unlock configuration option (null if not set explicitly).<p>
882     *
883     * @return the value of the acacia-unlock configuration option
884     */
885    public String getAcaciaUnlock() {
886
887        return m_acaciaUnlock;
888    }
889
890    /**
891     * Returns the account infos.<p>
892     *
893     * @return the account infos
894     */
895    public List<CmsAccountInfo> getAccountInfos() {
896
897        if (m_accountInfos == null) {
898            return Collections.unmodifiableList(Arrays.asList(DEFAULT_ACCOUNT_INFOS));
899        } else {
900            return Collections.unmodifiableList(m_accountInfos);
901        }
902    }
903
904    /**
905     * Gets the additional log folder configuration.<p>
906     *
907     * @return the additional log folder configuration
908     */
909    public CmsAdditionalLogFolderConfig getAdditionalLogFolderConfiguration() {
910
911        return m_logFolderConfig;
912    }
913
914    /**
915     * Returns the name of the local category folder(s).<p>
916     *
917     * @return the name of the local category folder(s)
918     */
919    public String getCategoryFolder() {
920
921        return m_categoryFolder;
922    }
923
924    /**
925     * Returns the configured account infos.<p>
926     *
927     * @return the configured account infos
928     */
929    public List<CmsAccountInfo> getConfiguredAccountInfos() {
930
931        return m_accountInfos;
932    }
933
934    /**
935     * Gets the content translation engine, and if none is configured, returns a dummy implementation.
936     *
937     * @return the content translation engine
938     */
939    public I_CmsContentTranslator getContentTranslation() {
940
941        return getContentTranslation(m_defaultContentTranslation);
942    }
943
944    /**
945     * Gets the configured content translation engine, or the provided default value if no content translation is configured.
946     *
947     * @param defaultValue the default value
948     * @return the content translation engine, or the default value if none is configured
949     */
950    public I_CmsContentTranslator getContentTranslation(I_CmsContentTranslator defaultValue) {
951
952        if (m_contentTranslation != null) {
953            return m_contentTranslation;
954        }
955        return defaultValue;
956    }
957
958    /**
959     * Gets the access object of the type settings.<p>
960     *
961     * @return access object of the type settings
962     */
963    public CmsExplorerTypeAccess getDefaultAccess() {
964
965        return m_defaultAccess;
966    }
967
968    /**
969     * Returns the Workplace default locale.<p>
970     *
971     * @return  the Workplace default locale
972     */
973    public Locale getDefaultLocale() {
974
975        return m_defaultLocale;
976    }
977
978    /**
979     * Gets the default name pattern for the given type.<p>
980     *
981     * @param type the type name
982     * @return the default name pattern for the type
983     */
984    public String getDefaultNamePattern(String type) {
985
986        CmsExplorerTypeSettings settings = getExplorerTypeSetting(type);
987        if ((settings != null) && (settings.getNamePattern() != null)) {
988            return settings.getNamePattern();
989        }
990        if (type.equals("sitemap_config") || type.equals("module_config")) {
991            return ".config%(number)";
992        }
993        if (type.equals("content_folder")) {
994            return ".content%(number)";
995        }
996        return "new_" + type + "%(number)";
997    }
998
999    /**
1000     * Returns the Workplace default user settings.<p>
1001     *
1002     * @return  the Workplace default user settings
1003     */
1004    public CmsDefaultUserSettings getDefaultUserSettings() {
1005
1006        return m_defaultUserSettings;
1007    }
1008
1009    /**
1010     * Returns all instantiated dialog handlers for the workplace.<p>
1011     *
1012     * @return all instantiated dialog handlers for the workplace
1013     */
1014    public Map<String, I_CmsDialogHandler> getDialogHandler() {
1015
1016        return m_dialogHandler;
1017    }
1018
1019    /**
1020     * Returns the instantiated dialog handler class for the key or null, if there is no mapping for the key.<p>
1021     *
1022     * @param key the key whose associated value is to be returned
1023     *
1024     * @return the instantiated dialog handler class for the key
1025     */
1026    public I_CmsDialogHandler getDialogHandler(String key) {
1027
1028        return m_dialogHandler.get(key);
1029    }
1030
1031    /**
1032     * Returns a new instance of the configured direct edit provider.<p>
1033     *
1034     * @return a new instance of the configured direct edit provider
1035     */
1036    public I_CmsDirectEditProvider getDirectEditProvider() {
1037
1038        return m_directEditProvider.newInstance();
1039    }
1040
1041    /**
1042     * Returns the instantiated editor action handler class.<p>
1043     *
1044     * @return the instantiated editor action handler class
1045     */
1046    public I_CmsEditorActionHandler getEditorActionHandler() {
1047
1048        return m_editorAction;
1049    }
1050
1051    /**
1052     * Returns the instantiated editor CSS handler classes.<p>
1053     *
1054     * @return the instantiated editor CSS handler classes
1055     */
1056    public List<I_CmsEditorCssHandler> getEditorCssHandlers() {
1057
1058        return m_editorCssHandlers;
1059    }
1060
1061    /**
1062     * Returns the instantiated editor display option class.<p>
1063     *
1064     * @return the instantiated editor display option class
1065     */
1066    public CmsEditorDisplayOptions getEditorDisplayOptions() {
1067
1068        return m_editorDisplayOptions;
1069    }
1070
1071    /**
1072     * Returns the instantiated editor handler class.<p>
1073     *
1074     * @return the instantiated editor handler class
1075     */
1076    public I_CmsEditorHandler getEditorHandler() {
1077
1078        return m_editorHandler;
1079    }
1080
1081    /**
1082     * Gets the maximum number of locale buttons to display in the content editor.
1083     */
1084    public int getEditorMaxLocaleButtons() {
1085
1086        return m_maxLocaleButtons;
1087    }
1088
1089    /**
1090     * Returns the element delete mode.<p>
1091     *
1092     * @return the element delete mode
1093     */
1094    public ElementDeleteMode getElementDeleteMode() {
1095
1096        return m_elementDeleteMode;
1097    }
1098
1099    /**
1100     * Returns the configured workplace encoding.<p>
1101     *
1102     * @return the configured workplace encoding
1103     */
1104    public String getEncoding() {
1105
1106        return m_encoding;
1107    }
1108
1109    /**
1110     * Returns the explorer type settings for the specified resource type.<p>
1111     *
1112     * @param type the resource type for which the settings are required
1113     *
1114     * @return the explorer type settings for the specified resource type
1115     */
1116    public CmsExplorerTypeSettings getExplorerTypeSetting(String type) {
1117
1118        return m_explorerTypeSettingsMap.get(type);
1119    }
1120
1121    /**
1122     * Returns the list of explorer type settings.<p>
1123     *
1124     * These settings provide information for the new resource dialog and the context menu appearance.<p>
1125     *
1126     * @return the list of explorer type settings
1127     */
1128    public List<CmsExplorerTypeSettings> getExplorerTypeSettings() {
1129
1130        if (m_explorerTypeSettings == null) {
1131            // initialize all explorer type settings if not already done
1132            initExplorerTypeSettings();
1133        }
1134
1135        return m_explorerTypeSettings;
1136    }
1137
1138    /**
1139     * Gets the explorer types for the given view name.<p>
1140     *
1141     * @param viewName the view name
1142     *
1143     * @return the explorer names for the given view names
1144     */
1145    public List<CmsExplorerTypeSettings> getExplorerTypesForView(String viewName) {
1146
1147        List<CmsExplorerTypeSettings> result = Lists.newArrayList();
1148        for (CmsExplorerTypeSettings explorerType : getExplorerTypeSettings()) {
1149
1150            String currentViewName = explorerType.getElementView();
1151            if (currentViewName == null) {
1152                currentViewName = getDefaultView(explorerType.getName());
1153            }
1154            if ((currentViewName != null) && currentViewName.equals(viewName)) {
1155                if (OpenCms.getResourceManager().hasResourceType(explorerType.getName())) {
1156                    result.add(explorerType);
1157                }
1158            } else if (CmsResourceTypeFolder.getStaticTypeName().equals(explorerType.getName())
1159                && "view_folders|view_basic".contains(viewName)) {
1160                result.add(explorerType);
1161            }
1162
1163        }
1164        return result;
1165    }
1166
1167    /**
1168     * Gets the element views generated from explorer types.<p>
1169     *
1170     * @return the map of element views from the explorer types
1171     */
1172    public Map<CmsUUID, CmsElementView> getExplorerTypeViews() {
1173
1174        return Collections.unmodifiableMap(m_explorerTypeViews);
1175
1176    }
1177
1178    /**
1179     * Returns the set of configured export points for the workplace.<p>
1180     *
1181     * @return the set of configured export points for the workplace
1182     */
1183    public Set<CmsExportPoint> getExportPoints() {
1184
1185        return m_exportPoints;
1186    }
1187
1188    /**
1189     * Returns the value (in bytes) for the maximum file upload size of the current user.<p>
1190     *
1191     * @param cms the initialized CmsObject
1192     *
1193     * @return the value (in bytes) for the maximum file upload size
1194     */
1195    public long getFileBytesMaxUploadSize(CmsObject cms) {
1196
1197        int maxFileSize = getFileMaxUploadSize();
1198        long maxFileSizeBytes = maxFileSize * 1024;
1199        // check if current user belongs to Admin group, if so no file upload limit
1200        if ((maxFileSize <= 0) || OpenCms.getRoleManager().hasRole(cms, CmsRole.VFS_MANAGER)) {
1201            maxFileSizeBytes = -1;
1202        }
1203        return maxFileSizeBytes;
1204    }
1205
1206    /**
1207     * Returns the value (in kb) for the maximum file upload size.<p>
1208     *
1209     * @return the value (in kb) for the maximum file upload size
1210     */
1211    public int getFileMaxUploadSize() {
1212
1213        return m_fileMaxUploadSize;
1214    }
1215
1216    /**
1217     * Returns the system-wide file view settings for the workplace.<p>
1218     *
1219     * Note that this instance may not modified (invocation of setters) directly or a
1220     * <code>{@link org.opencms.main.CmsRuntimeException}</code> will be thrown.<p>
1221     *
1222     * It has to be cloned first and then may be written back to the workplace settings using
1223     * method {@link #setFileViewSettings(CmsObject, org.opencms.util.CmsRfsFileViewer)}.<p>
1224     *
1225     * @return the system-wide file view settings for the workplace
1226     */
1227    public CmsRfsFileViewer getFileViewSettings() {
1228
1229        return m_fileViewSettings;
1230    }
1231
1232    /**
1233     * Returns a collection of all available galleries.<p>
1234     *
1235     * The Map has the gallery type name as key and an instance of the
1236     * gallery class (not completely initialized) as value.<p>
1237     *
1238     * @return a collection of all available galleries
1239     */
1240    public Map<String, A_CmsAjaxGallery> getGalleries() {
1241
1242        return m_galleries;
1243    }
1244
1245    /**
1246     * Returns the gallery default scope.<p>
1247     *
1248     * @return the gallery default scope
1249     */
1250    public CmsGallerySearchScope getGalleryDefaultScope() {
1251
1252        CmsGallerySearchScope result = CmsGallerySearchScope.siteShared;
1253        if (m_galleryDefaultScope != null) {
1254            try {
1255                result = CmsGallerySearchScope.valueOf(m_galleryDefaultScope);
1256            } catch (Throwable t) {
1257                // ignore
1258            }
1259        }
1260        return result;
1261    }
1262
1263    /**
1264     * Gets the configured gallery default scope as a string.<p>
1265     *
1266     * @return the gallery default scope as a string
1267     */
1268    public String getGalleryDefaultScopeString() {
1269
1270        return m_galleryDefaultScope;
1271    }
1272
1273    /**
1274     * Returns the object used for translating group names.<p>
1275     *
1276     * @return the group name translator
1277     */
1278    public I_CmsGroupNameTranslation getGroupNameTranslation() {
1279
1280        if (m_groupNameTranslation != null) {
1281            return m_groupNameTranslation;
1282        }
1283        if (m_groupTranslationClass != null) {
1284            try {
1285                m_groupNameTranslation = (I_CmsGroupNameTranslation)Class.forName(
1286                    m_groupTranslationClass).newInstance();
1287                return m_groupNameTranslation;
1288            } catch (ClassNotFoundException e) {
1289                LOG.error(e.getLocalizedMessage(), e);
1290            } catch (IllegalAccessException e) {
1291                LOG.error(e.getLocalizedMessage(), e);
1292            } catch (InstantiationException e) {
1293                LOG.error(e.getLocalizedMessage(), e);
1294            } catch (ClassCastException e) {
1295                LOG.error(e.getLocalizedMessage(), e);
1296            }
1297            m_groupNameTranslation = getDefaultGroupNameTranslation();
1298            return m_groupNameTranslation;
1299        } else {
1300            m_groupNameTranslation = getDefaultGroupNameTranslation();
1301            return m_groupNameTranslation;
1302        }
1303    }
1304
1305    /**
1306     * Returns the configured class name for translating group names.<p>
1307     *
1308     * @return the group translation class name
1309     */
1310    public String getGroupTranslationClass() {
1311
1312        return m_groupTranslationClass;
1313    }
1314
1315    /**
1316     * @see org.opencms.i18n.I_CmsLocaleHandler#getI18nInfo(javax.servlet.http.HttpServletRequest, org.opencms.file.CmsUser, org.opencms.file.CmsProject, java.lang.String)
1317     */
1318    public CmsI18nInfo getI18nInfo(HttpServletRequest req, CmsUser user, CmsProject project, String resource) {
1319
1320        Locale locale = null;
1321        // try to read locale from session
1322        if (req != null) {
1323            // set the request character encoding
1324            try {
1325                req.setCharacterEncoding(m_encoding);
1326            } catch (UnsupportedEncodingException e) {
1327                // should not ever really happen
1328                LOG.error(Messages.get().getBundle().key(Messages.LOG_UNSUPPORTED_ENCODING_SET_1, m_encoding), e);
1329            }
1330            // read workplace settings
1331            HttpSession session = req.getSession(false);
1332            if (session != null) {
1333                CmsWorkplaceSettings settings = (CmsWorkplaceSettings)session.getAttribute(
1334                    CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS);
1335                if (settings != null) {
1336                    locale = settings.getUserSettings().getLocale();
1337                }
1338            }
1339        }
1340
1341        if (locale == null) {
1342            // no session available, try to read the locale form the user additional info
1343            if (!user.isGuestUser()) {
1344                // check user settings only for "real" users
1345                CmsUserSettings settings = new CmsUserSettings(user);
1346                locale = settings.getLocale();
1347
1348            }
1349            if (req != null) {
1350                List<Locale> acceptedLocales = (new CmsAcceptLanguageHeaderParser(
1351                    req,
1352                    getDefaultLocale())).getAcceptedLocales();
1353                if ((locale != null) && (!acceptedLocales.contains(locale))) {
1354                    acceptedLocales.add(0, locale);
1355                }
1356                locale = OpenCms.getLocaleManager().getFirstMatchingLocale(acceptedLocales, m_locales);
1357            }
1358
1359            // if no locale was found, use the default
1360            if (locale == null) {
1361                locale = getDefaultLocale();
1362            }
1363        }
1364
1365        return new CmsI18nInfo(locale, m_encoding);
1366    }
1367
1368    /**
1369     * Returns a list of site folders which generate labeled links.<p>
1370     *
1371     * @return a list of site folders which generate labeled links
1372     */
1373    public List<String> getLabelSiteFolders() {
1374
1375        return m_labelSiteFolders;
1376    }
1377
1378    /**
1379     * Returns the list of available workplace locales, sorted ascending.<p>
1380     *
1381     * Please note: Be careful not to modify the returned Set as it is not a clone.<p>
1382     *
1383     * @return the set of available workplace locales
1384     */
1385    public List<Locale> getLocales() {
1386
1387        return m_locales;
1388    }
1389
1390    /**
1391     * Returns the configured list of localized workplace folders.<p>
1392     *
1393     * @return the configured list of localized workplace folders
1394     */
1395    public List<String> getLocalizedFolders() {
1396
1397        return m_localizedFolders;
1398    }
1399
1400    /**
1401     * Returns the {@link CmsWorkplaceMessages} for the given locale.<p>
1402     *
1403     * The workplace messages are a collection of resource bundles, containing the messages
1404     * for all OpenCms core bundles and of all initialized modules.<p>
1405     *
1406     * Please note that the message objects are cached internally.
1407     * The returned message object should therefore never be modified directly in any way.<p>
1408     *
1409     * @param locale the locale to get the messages for
1410     *
1411     * @return the {@link CmsWorkplaceMessages} for the given locale
1412     */
1413    public CmsWorkplaceMessages getMessages(Locale locale) {
1414
1415        CmsWorkplaceMessages result = m_messages.get(locale);
1416        if (result != null) {
1417            // messages have already been read
1418            return result;
1419        }
1420
1421        // messages have not been read so far
1422        synchronized (this) {
1423            // check again
1424            result = m_messages.get(locale);
1425            if (result == null) {
1426                result = new CmsWorkplaceMessages(locale);
1427                m_messages.put(locale, result);
1428            }
1429        }
1430        return result;
1431    }
1432
1433    /**
1434     * Returns the post upload handler.<p>
1435     *
1436     * @return the post upload handler
1437     */
1438    public I_CmsPostUploadDialogHandler getPostUploadHandler() {
1439
1440        return m_postUploadHandler;
1441    }
1442
1443    /**
1444     * Returns the condition definition for the given resource type that is triggered before opening the editor.<p>
1445     *
1446     * @param resourceType the resource type
1447     *
1448     * @return the condition definition for the given resource type class name or null if none is found
1449     */
1450    public I_CmsPreEditorActionDefinition getPreEditorConditionDefinition(I_CmsResourceType resourceType) {
1451
1452        Iterator<I_CmsPreEditorActionDefinition> i = m_preEditorConditionDefinitions.iterator();
1453        I_CmsPreEditorActionDefinition result = null;
1454        int matchResult = -1;
1455        while (i.hasNext()) {
1456            I_CmsPreEditorActionDefinition currentDefinition = i.next();
1457            if (resourceType.getClass().isInstance(currentDefinition.getResourceType())) {
1458                // now determine the match count...
1459                int matchDistance = 0;
1460                Class<?> superClass = resourceType.getClass();
1461                while (true) {
1462                    // check if a super class is present
1463                    if (superClass == null) {
1464                        break;
1465                    }
1466                    if (superClass.getName().equals(currentDefinition.getResourceType().getClass().getName())) {
1467                        break;
1468                    }
1469                    matchDistance += 1;
1470                    superClass = superClass.getSuperclass();
1471                }
1472                if (matchResult != -1) {
1473                    if (matchDistance < matchResult) {
1474                        matchResult = matchDistance;
1475                        result = currentDefinition;
1476                    }
1477                } else {
1478                    matchResult = matchDistance;
1479                    result = currentDefinition;
1480                }
1481            }
1482        }
1483        return result;
1484    }
1485
1486    /**
1487     * Returns the condition definitions for the different resource
1488     * types which are triggered before opening the editor.<p>
1489     *
1490     * @return the condition definitions
1491     */
1492    public List<I_CmsPreEditorActionDefinition> getPreEditorConditionDefinitions() {
1493
1494        return m_preEditorConditionDefinitions;
1495    }
1496
1497    /**
1498     * Returns the repository folder handler.<p>
1499     *
1500     * @return the repository folder handler
1501     */
1502    public I_CmsRepositoryFolderHandler getRepositoryFolderHandler() {
1503
1504        if (m_repositoryFolderHandler == null) {
1505            // handler has not been configured, use the default one
1506            m_repositoryFolderHandler = new CmsRepositoryFolderHandler();
1507        }
1508        return m_repositoryFolderHandler;
1509    }
1510
1511    /**
1512     * Gets the name of the role necessary for editing the sitemap configuration.
1513     *
1514     * @return the name of the role necessary for editing the sitemap configuration
1515     */
1516    public String getSitemapConfigEditRole() {
1517
1518        return m_sitemapConfigEditRole;
1519    }
1520
1521    /**
1522     * Gets the name of the role users should have to be able to edit detail pages from the sitemap editor
1523     *
1524     * @return the role name, or null
1525     */
1526    public String getSitemapEditorDetailPageManagementRole() {
1527
1528        return m_sitemapEditorDetailPageManagementRole;
1529    }
1530
1531    /**
1532     * Returns Regex patterns that should be excluded from synchronization.<p>
1533     *
1534     * @return the exclude patterns
1535     */
1536    public ArrayList<Pattern> getSynchronizeExcludePatterns() {
1537
1538        return m_synchronizeExcludePatterns;
1539    }
1540
1541    /**
1542     * Returns the id of the temporary file project required by the editors.<p>
1543     *
1544     * @return the id of the temporary file project required by the editors
1545     */
1546    public CmsUUID getTempFileProjectId() {
1547
1548        if (m_tempFileProject != null) {
1549            return m_tempFileProject.getUuid();
1550        } else {
1551            return null;
1552        }
1553    }
1554
1555    /**
1556     * Returns the tool manager.<p>
1557     *
1558     * @return the tool manager
1559     */
1560    public CmsToolManager getToolManager() {
1561
1562        if (m_toolManager == null) {
1563            m_toolManager = new CmsToolManager();
1564        }
1565        return m_toolManager;
1566    }
1567
1568    /**
1569     * Gets the upload hook URI which should be opened for an upload to a given folder.<p>
1570     * This method will return null if no upload hook should be used for the given upload folder.<p>
1571     *
1572     * The API for this upload hook is as follows:
1573     *
1574     * The upload hook will be called with the following parameters:
1575     *
1576     * resources (required): a comma separated list of the structure ids of the uploaded resources
1577     *                       if this is omitted
1578     * closelink (optional): a link which should be opened once the upload hook has finished whatever
1579     *                       it is doing
1580     *
1581     * @param cms the current CMS context
1582     * @param uploadFolder the folder for which the upload hook should be found
1583     *
1584     * @return the URI of the upload hook or null
1585     */
1586    public String getUploadHook(CmsObject cms, String uploadFolder) {
1587
1588        if (m_postUploadHandler != null) {
1589            return m_postUploadHandler.getUploadHook(cms, uploadFolder);
1590        }
1591        I_CmsDialogHandler handler = getDialogHandler(CmsDialogSelector.DIALOG_PROPERTY);
1592        if ((handler != null) && (handler instanceof I_CmsPostUploadDialogHandler)) {
1593            return ((I_CmsPostUploadDialogHandler)handler).getUploadHook(cms, uploadFolder);
1594        } else {
1595            return null;
1596        }
1597    }
1598
1599    /**
1600     * Gets the upload restriction.
1601     *
1602     * @return the upload restriction
1603     */
1604    public I_CmsUploadRestriction getUploadRestriction() {
1605
1606        return m_uploadRestriction;
1607    }
1608
1609    /**
1610     * Returns the user additional information configuration Manager.<p>
1611     *
1612     * @return the user additional information configuration manager
1613     */
1614    public CmsWorkplaceUserInfoManager getUserInfoManager() {
1615
1616        return m_userInfoManager;
1617    }
1618
1619    /**
1620     * Returns the user list mode as a string.<p>
1621     *
1622     * @return the user list mode as a string
1623     */
1624    public String getUserListModeString() {
1625
1626        return m_userListMode;
1627    }
1628
1629    /**
1630     * Returns the map of configured workplace views.<p>
1631     *
1632     * @return the map of configured workplace views
1633     */
1634    public List<CmsWorkplaceView> getViews() {
1635
1636        return m_views;
1637    }
1638
1639    /**
1640     * Gets the configured virus scanner (may be null).
1641     *
1642     * @return the configured virus scanner
1643     */
1644    public I_CmsVirusScanner getVirusScanner() {
1645
1646        return m_virusScanner;
1647    }
1648
1649    /**
1650     * Returns the instantiated workplace editor manager class.<p>
1651     *
1652     * @return the instantiated workplace editor manager class
1653     */
1654    public CmsWorkplaceEditorManager getWorkplaceEditorManager() {
1655
1656        return m_editorManager;
1657    }
1658
1659    /**
1660     * Returns the list of explorer type settings configured in the opencms-workplace.xml file.<p>
1661     *
1662     * @return the list of explorer type settings
1663     */
1664    public List<CmsExplorerTypeSettings> getWorkplaceExplorerTypeSettings() {
1665
1666        return Collections.unmodifiableList(m_explorerTypeSettingsFromXml);
1667    }
1668
1669    /**
1670     * Returns the workplace locale from the current user's settings.<p>
1671     *
1672     * @param cms the current cms object
1673     *
1674     * @return the workplace locale
1675     */
1676    public Locale getWorkplaceLocale(CmsObject cms) {
1677
1678        return getWorkplaceLocale(cms.getRequestContext());
1679    }
1680
1681    /**
1682     * Gets the workplace locale for the given request context.<p>
1683     *
1684     * @param requestContext the request context
1685     *
1686     * @return the workplace locale for the request context
1687     */
1688    public Locale getWorkplaceLocale(CmsRequestContext requestContext) {
1689
1690        Locale wpLocale = new CmsUserSettings(requestContext.getCurrentUser()).getLocale();
1691        if (wpLocale == null) {
1692            // fall back
1693            wpLocale = getDefaultLocale();
1694            if (wpLocale == null) {
1695                // fall back
1696                wpLocale = requestContext.getLocale();
1697            }
1698        }
1699        return wpLocale;
1700
1701    }
1702
1703    /**
1704     * Returns the workplace locale for the user.
1705     * @param user the user to get the workplace locale for.
1706     * @return the workplace locale for the user.
1707     */
1708    public Locale getWorkplaceLocale(CmsUser user) {
1709
1710        Locale wpLocale = new CmsUserSettings(user).getLocale();
1711        if (wpLocale == null) {
1712            // fall back
1713            wpLocale = OpenCms.getWorkplaceManager().getDefaultLocale();
1714            if (wpLocale == null) {
1715                // fall back
1716                wpLocale = CmsLocaleManager.MASTER_LOCALE;
1717            }
1718        }
1719        return wpLocale;
1720
1721    }
1722
1723    /**
1724     * @see org.opencms.i18n.I_CmsLocaleHandler#initHandler(org.opencms.file.CmsObject)
1725     */
1726    public void initHandler(CmsObject cms) {
1727
1728        // initialize the workplace locale set
1729        m_locales = initWorkplaceLocales(cms);
1730    }
1731
1732    /**
1733     * Initializes the workplace manager with the OpenCms system configuration.<p>
1734     *
1735     * @param cms an OpenCms context object that must have been initialized with "Admin" permissions
1736     *
1737     * @throws CmsRoleViolationException if the provided OpenCms user context does
1738     *      not have <code>{@link CmsRole#WORKPLACE_MANAGER}</code> role permissions
1739     * @throws CmsException if something goes wrong
1740     */
1741    public synchronized void initialize(CmsObject cms) throws CmsException, CmsRoleViolationException {
1742
1743        try {
1744            // ensure that the current user has permissions to initialize the workplace
1745            OpenCms.getRoleManager().checkRole(cms, CmsRole.WORKPLACE_MANAGER);
1746
1747            // set the workplace encoding
1748            try {
1749                // workplace encoding is set on the workplace parent folder /system/workplace/
1750                CmsResource wpFolderRes = cms.readResource(CmsWorkplace.VFS_PATH_WORKPLACE);
1751                m_encoding = CmsLocaleManager.getResourceEncoding(cms, wpFolderRes);
1752            } catch (CmsVfsResourceNotFoundException e) {
1753                // workplace parent folder could not be read - use configured default encoding
1754                m_encoding = OpenCms.getSystemInfo().getDefaultEncoding();
1755            }
1756
1757            // configure direct edit provider with default if not available
1758            if (m_directEditProvider == null) {
1759                m_directEditProvider = new CmsDirectEditDefaultProvider();
1760            }
1761
1762            // throw away all currently configured module explorer types
1763            m_explorerTypeSettingsFromModules.clear();
1764            // now add the additional explorer types found in the modules
1765            CmsModuleManager moduleManager = OpenCms.getModuleManager();
1766            Iterator<String> moduleNameIterator = moduleManager.getModuleNames().iterator();
1767            while (moduleNameIterator.hasNext()) {
1768                CmsModule module = moduleManager.getModule(moduleNameIterator.next());
1769                if (module != null) {
1770                    addExplorerTypeSettings(module);
1771                }
1772            }
1773            // initialize the explorer type settings
1774            initExplorerTypeSettings();
1775            // initialize the workplace views
1776            initWorkplaceViews(cms);
1777            // initialize the workplace editor manager
1778            m_editorManager = new CmsWorkplaceEditorManager(cms);
1779            // initialize the locale handler
1780            initHandler(cms);
1781
1782            if (CmsLog.INIT.isInfoEnabled()) {
1783                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_ACCESS_INITIALIZED_0));
1784            }
1785            try {
1786                // read the temporary file project
1787                m_tempFileProject = cms.readProject(I_CmsProjectDriver.TEMP_FILE_PROJECT_NAME);
1788            } catch (CmsException e) {
1789                // during initial setup of OpenCms the temp file project does not yet exist...
1790                LOG.error(Messages.get().getBundle().key(Messages.LOG_NO_TEMP_FILE_PROJECT_0));
1791            }
1792            // create an instance of editor display options
1793            m_editorDisplayOptions = new CmsEditorDisplayOptions();
1794
1795            // throw away all current gallery settings
1796            m_galleries.clear();
1797            // read out the configured gallery classes
1798            Iterator<I_CmsResourceType> typesIterator = OpenCms.getResourceManager().getResourceTypes().iterator();
1799            while (typesIterator.hasNext()) {
1800                I_CmsResourceType resourceType = typesIterator.next();
1801                if (resourceType instanceof CmsResourceTypeFolderExtended) {
1802                    // found a configured extended folder resource type
1803                    CmsResourceTypeFolderExtended galleryType = (CmsResourceTypeFolderExtended)resourceType;
1804                    String folderClassName = galleryType.getFolderClassName();
1805                    if (CmsStringUtil.isNotEmpty(folderClassName)) {
1806                        // only process this as a gallery if the folder name is not empty
1807                        try {
1808                            // check, if the folder class is a subclass of A_CmsGallery
1809                            if (A_CmsAjaxGallery.class.isAssignableFrom(Class.forName(folderClassName))) {
1810                                // create gallery class instance
1811                                A_CmsAjaxGallery galleryInstance = (A_CmsAjaxGallery)Class.forName(
1812                                    folderClassName).newInstance();
1813                                // set gallery folder resource type
1814                                galleryInstance.setResourceType(galleryType);
1815                                // store the gallery class instance with the type name as lookup key
1816                                m_galleries.put(galleryType.getTypeName(), galleryInstance);
1817                            }
1818                        } catch (ClassNotFoundException e) {
1819                            LOG.error(e.getLocalizedMessage());
1820                        } catch (InstantiationException e) {
1821                            LOG.error(e.getLocalizedMessage());
1822                        } catch (IllegalAccessException e) {
1823                            LOG.error(e.getLocalizedMessage());
1824                        }
1825                    }
1826                }
1827            }
1828
1829            getDefaultUserSettings().initPreferences(this);
1830
1831            // configures the tool manager
1832            getToolManager().configure(cms);
1833
1834            flushMessageCache();
1835            getUploadRestriction().setAdminCmsObject(cms);
1836
1837            if (getContentTranslation() != null) {
1838                getContentTranslation().initialize(cms);
1839            }
1840
1841            // register this object as event listener
1842            OpenCms.addCmsEventListener(this, new int[] {I_CmsEventListener.EVENT_CLEAR_CACHES});
1843        } catch (CmsException e) {
1844            if (LOG.isErrorEnabled()) {
1845                LOG.error(e.getLocalizedMessage(), e);
1846            }
1847            throw new CmsException(Messages.get().container(Messages.ERR_INITIALIZE_WORKPLACE_0));
1848        }
1849        m_adminCms = cms;
1850    }
1851
1852    /**
1853     * Returns true if gallery upload is disabled for the user in the given context.
1854     *
1855     * @param cms a CMS context
1856     * @return true if the upload is disabled
1857     */
1858    public boolean isAdeGalleryUploadDisabled(CmsObject cms) {
1859
1860        return !OpenCms.getRoleManager().hasRole(cms, getUploadRole());
1861
1862    }
1863
1864    /**
1865     * Checks if element authors have special permission to work in galleries (upload/replace).
1866     * @return true in the case above
1867     */
1868
1869    public boolean isAllowElementAuthorToWorkInGalleries() {
1870
1871        return m_allowElementAuthorToWorkInGalleries;
1872    }
1873
1874    /**
1875     * Returns the default property editing mode on resources.<p>
1876     *
1877     * @return the default property editing mode on resources
1878     */
1879    public boolean isDefaultPropertiesOnStructure() {
1880
1881        return m_defaultPropertiesOnStructure;
1882    }
1883
1884    /**
1885     * Returns a flag, indicating if the categories should be displayed separated by repository in the category selection dialog.
1886     *
1887     * @return a flag, indicating if the categories should be displayed separated by repository in the category selection dialog.
1888     */
1889    public boolean isDisplayCategoriesByRepository() {
1890
1891        return m_displayCategoriesByRepository;
1892    }
1893
1894    /**
1895     * Returns a flag, indicating if the category selection dialog should have all entries completely collapsed when opened.
1896     *
1897     * @return a flag, indicating if the category selection dialog should have all entries completely collapsed when opened.
1898     */
1899    public boolean isDisplayCategorySelectionCollapsed() {
1900
1901        return m_displayCategorySelectionCollapsed;
1902    }
1903
1904    /**
1905     * Returns if tabs in the advanced property dialog are enabled.<p>
1906     *
1907     * @return <code>true</code> if tabs should be enabled, otherwise <code>false</code>
1908     */
1909    public boolean isEnableAdvancedPropertyTabs() {
1910
1911        return m_enableAdvancedPropertyTabs;
1912    }
1913
1914    /**
1915     * Checks if the 'Categories' column in the explorer should be enabled
1916     *
1917     * @return true if the categories column in the explorer should be enabled
1918     */
1919    public boolean isExplorerCategoriesEnabled() {
1920
1921        return m_explorerCategoriesEnabled;
1922    }
1923
1924    /**
1925     * Checks if only 'leaf' categories should be shown in the explorer 'Categories' column, i.e. only those which don't have child categories assigned to the same resource.
1926     *
1927     * @return true if only 'leaf' categories should be shown
1928     */
1929    public boolean isExplorerCategoriesLeavesOnly() {
1930
1931        return m_explorerCategoriesLeavesOnly;
1932    }
1933
1934    /**
1935     * Checks if categories should be shown with their path in the explorer 'Categories' column.
1936     *
1937     * @return true if categories should be shown with their path
1938     */
1939    public boolean isExplorerCategoriesWithPath() {
1940
1941        return m_explorerCategoriesWithPath;
1942    }
1943
1944    /**
1945     * Returns true if "keep alive" mode is active.
1946     *
1947     * @return true if the session should be kept alive
1948     */
1949    public boolean isKeepAlive() {
1950
1951        return isKeepAlive(true).booleanValue();
1952    }
1953
1954    /**
1955     * Returns true if the session should be kept alive.<p>
1956     *
1957     * @param useDefault if true, the default value will be returned if the "keep alive" setting is not explicitly configured
1958     *
1959     * @return True if the "keep alive" mode is active
1960     */
1961    public Boolean isKeepAlive(boolean useDefault) {
1962
1963        if (m_keepAlive != null) {
1964            return m_keepAlive;
1965        }
1966        if (useDefault) {
1967            return Boolean.TRUE;
1968        } else {
1969            return null;
1970        }
1971
1972    }
1973
1974    /**
1975     * Checks if the virus scanner is enabled.
1976     *
1977     * @return true if the virus scanner is enabled
1978     */
1979    public boolean isVirusScannerEnabled() {
1980
1981        return m_virusScannerEnabled;
1982    }
1983
1984    /**
1985     * Returns if XML content is automatically corrected when opened with the editor.<p>
1986     *
1987     * @return <code>true</code> if XML content is automatically corrected when opened with the editor, otherwise <code>false</code>
1988     */
1989    public boolean isXmlContentAutoCorrect() {
1990
1991        return m_xmlContentAutoCorrect;
1992    }
1993
1994    /**
1995     * Returns if lazy user lists are enabled.<p>
1996     *
1997     * @return <code>true</code> if lazy user lists are enabled
1998     */
1999    public boolean lazyUserListsEnabled() {
2000
2001        return true;
2002    }
2003
2004    /**
2005     * Removes the list of explorer type settings from the given module.<p>
2006     *
2007     * @param module the module witch contains the explorer type settings to remove
2008     */
2009    public void removeExplorerTypeSettings(CmsModule module) {
2010
2011        List<CmsExplorerTypeSettings> explorerTypes = module.getExplorerTypes();
2012        if ((explorerTypes != null) && (explorerTypes.size() > 0)) {
2013            Iterator<CmsExplorerTypeSettings> i = explorerTypes.iterator();
2014            while (i.hasNext()) {
2015                CmsExplorerTypeSettings settings = i.next();
2016                if (m_explorerTypeSettingsFromModules.contains(settings)) {
2017                    m_explorerTypeSettingsFromModules.remove(settings);
2018                    if (CmsLog.INIT.isInfoEnabled()) {
2019                        CmsLog.INIT.info(
2020                            Messages.get().getBundle().key(
2021                                Messages.INIT_REMOVE_EXPLORER_TYPE_SETTING_1,
2022                                settings.getName()));
2023                    }
2024                }
2025            }
2026            // reset the list of all explorer type settings
2027            initExplorerTypeSettings();
2028        }
2029    }
2030
2031    /**
2032     * Sets the value of the acacia-unlock configuration option.<p>
2033     *
2034     * @param value the value of the acacia-unlock configuration option
2035     */
2036    public void setAcaciaUnlock(String value) {
2037
2038        m_acaciaUnlock = value;
2039
2040    }
2041
2042    /**
2043     * Sets the additional log folder configuration.<p>
2044     *
2045     * @param logConfig the additional log folder configuration
2046     */
2047    public void setAdditionalLogFolderConfiguration(CmsAdditionalLogFolderConfig logConfig) {
2048
2049        m_logFolderConfig = logConfig;
2050    }
2051
2052    /**
2053     * Enables/disables special permissions for element authors to work with galleries (upload/replace).
2054     * @param allowElementAuthorToWorkInGalleries true if the special permissions should be enabled for element authors
2055      */
2056    public void setAllowElementAuthorToWorkInGalleries(boolean allowElementAuthorToWorkInGalleries) {
2057
2058        m_allowElementAuthorToWorkInGalleries = allowElementAuthorToWorkInGalleries;
2059    }
2060
2061    /**
2062     * Sets if the autolock resources feature is enabled.<p>
2063     *
2064     * @param value <code>"true"</code> if the autolock resources feature is enabled, otherwise false
2065     */
2066    public void setAutoLock(String value) {
2067
2068        m_autoLockResources = Boolean.valueOf(value).booleanValue();
2069        if (CmsLog.INIT.isInfoEnabled()) {
2070            CmsLog.INIT.info(
2071                Messages.get().getBundle().key(
2072                    m_autoLockResources ? Messages.INIT_AUTO_LOCK_ENABLED_0 : Messages.INIT_AUTO_LOCK_DISABLED_0));
2073        }
2074    }
2075
2076    /**
2077     * Sets the category display options that affect how the category selection dialog is shown.
2078     *
2079     * @param displayCategoriesByRepository if true, the categories are shown separated by repository.
2080     * @param displayCategorySelectionCollapsed if true, the selection dialog opens showing only the top-level categories
2081     *              (or the various repositories) in collapsed state.
2082     */
2083    public void setCategoryDisplayOptions(
2084        String displayCategoriesByRepository,
2085        String displayCategorySelectionCollapsed) {
2086
2087        m_displayCategoriesByRepository = Boolean.parseBoolean(displayCategoriesByRepository);
2088        m_displayCategorySelectionCollapsed = Boolean.parseBoolean(displayCategorySelectionCollapsed);
2089    }
2090
2091    /**
2092     * Sets the name of the local category folder(s).<p>
2093     *
2094     * @param categoryFolder the name of the local category folder(s)
2095     */
2096    public void setCategoryFolder(String categoryFolder) {
2097
2098        m_categoryFolder = categoryFolder;
2099    }
2100
2101    /**
2102     * Sets the content translation engine.
2103     *
2104     * @param contentTranslation the instance of the content translator
2105     */
2106    public void setContentTranslation(I_CmsContentTranslator contentTranslation) {
2107
2108        m_contentTranslation = contentTranslation;
2109        try {
2110            m_contentTranslation.initConfiguration();
2111        } catch (Exception e) {
2112            throw new RuntimeException(e);
2113        }
2114    }
2115
2116    /**
2117     * Sets the access object of the type settings.<p>
2118     *
2119     * @param access access object
2120     */
2121    public void setDefaultAccess(CmsExplorerTypeAccess access) {
2122
2123        m_defaultAccess = access;
2124    }
2125
2126    /**
2127     * Sets the Workplace default locale.<p>
2128     *
2129     * @param locale the locale to set
2130     */
2131    public void setDefaultLocale(String locale) {
2132
2133        try {
2134            m_defaultLocale = CmsLocaleManager.getLocale(locale);
2135        } catch (Exception e) {
2136            if (CmsLog.INIT.isWarnEnabled()) {
2137                CmsLog.INIT.warn(Messages.get().getBundle().key(Messages.INIT_NONCRIT_ERROR_0), e);
2138            }
2139        }
2140        if (CmsLog.INIT.isInfoEnabled()) {
2141            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DEFAULT_LOCALE_1, m_defaultLocale));
2142        }
2143    }
2144
2145    /**
2146     * Sets the default property editing mode on resources.<p>
2147     *
2148     * @param defaultPropertiesOnStructure the default property editing mode on resources
2149     */
2150    public void setDefaultPropertiesOnStructure(String defaultPropertiesOnStructure) {
2151
2152        m_defaultPropertiesOnStructure = Boolean.valueOf(defaultPropertiesOnStructure).booleanValue();
2153        if (CmsLog.INIT.isInfoEnabled()) {
2154            CmsLog.INIT.info(
2155                Messages.get().getBundle().key(
2156                    m_defaultPropertiesOnStructure
2157                    ? Messages.INIT_PROP_ON_STRUCT_TRUE_0
2158                    : Messages.INIT_PROP_ON_STRUCT_FALSE_0));
2159        }
2160    }
2161
2162    /**
2163     * Sets the Workplace default user settings.<p>
2164     *
2165     * @param defaultUserSettings the user settings to set
2166     */
2167    public void setDefaultUserSettings(CmsDefaultUserSettings defaultUserSettings) {
2168
2169        m_defaultUserSettings = defaultUserSettings;
2170
2171        if (CmsLog.INIT.isInfoEnabled()) {
2172            CmsLog.INIT.info(
2173                Messages.get().getBundle().key(
2174                    Messages.INIT_DEFAULT_USER_SETTINGS_1,
2175                    m_defaultUserSettings.getClass().getName()));
2176        }
2177    }
2178
2179    /**
2180     * Sets the direct edit provider.<p>
2181     *
2182     * @param clazz the direct edit provider to set
2183     */
2184    public void setDirectEditProvider(I_CmsDirectEditProvider clazz) {
2185
2186        m_directEditProvider = clazz;
2187        if (CmsLog.INIT.isInfoEnabled()) {
2188            CmsLog.INIT.info(
2189                Messages.get().getBundle().key(
2190                    Messages.INIT_DIRECT_EDIT_PROVIDER_1,
2191                    m_directEditProvider.getClass().getName()));
2192        }
2193    }
2194
2195    /**
2196     * Sets the editor action class.<p>
2197     *
2198     * @param clazz the editor action class to set
2199     */
2200    public void setEditorAction(I_CmsEditorActionHandler clazz) {
2201
2202        m_editorAction = clazz;
2203        if (CmsLog.INIT.isInfoEnabled()) {
2204            CmsLog.INIT.info(
2205                Messages.get().getBundle().key(
2206                    Messages.INIT_EDITOR_ACTION_CLASS_1,
2207                    m_editorAction.getClass().getName()));
2208        }
2209    }
2210
2211    /**
2212     * Sets the editor display option class.<p>
2213     *
2214     * @param clazz the editor display option class to set
2215     */
2216    public void setEditorDisplayOptions(CmsEditorDisplayOptions clazz) {
2217
2218        m_editorDisplayOptions = clazz;
2219        if (CmsLog.INIT.isInfoEnabled()) {
2220            CmsLog.INIT.info(
2221                Messages.get().getBundle().key(
2222                    Messages.INIT_EDITOR_DISPLAY_OPTS_1,
2223                    m_editorAction.getClass().getName()));
2224        }
2225    }
2226
2227    /**
2228     * Sets the editor handler class.<p>
2229     *
2230     * @param clazz the editor handler class to set
2231     */
2232    public void setEditorHandler(I_CmsEditorHandler clazz) {
2233
2234        m_editorHandler = clazz;
2235        if (CmsLog.INIT.isInfoEnabled()) {
2236            CmsLog.INIT.info(
2237                Messages.get().getBundle().key(
2238                    Messages.INIT_EDITOR_HANDLER_CLASS_1,
2239                    m_editorHandler.getClass().getName()));
2240        }
2241    }
2242
2243    /**
2244     * Sets the maximum number of locale buttons to display in the content editor.
2245     * @param maxLocaleButtons the number of buttons, as a string
2246     */
2247    public void setEditorMaxLocaleButtons(String maxLocaleButtons) {
2248
2249        m_maxLocaleButtons = Math.max(0, Integer.valueOf(maxLocaleButtons));
2250    }
2251
2252    /**
2253     * Sets the element delete mode.<p>
2254     *
2255     * @param deleteMode the element delete mode
2256     */
2257    public void setElementDeleteMode(String deleteMode) {
2258
2259        try {
2260            m_elementDeleteMode = ElementDeleteMode.valueOf(deleteMode);
2261        } catch (Throwable t) {
2262            m_elementDeleteMode = ElementDeleteMode.askDelete;
2263        }
2264    }
2265
2266    /**
2267     * Sets if tabs in the advanced property dialog are enabled.<p>
2268     *
2269     * @param enableAdvancedPropertyTabs true if tabs should be enabled, otherwise false
2270     */
2271    public void setEnableAdvancedPropertyTabs(String enableAdvancedPropertyTabs) {
2272
2273        m_enableAdvancedPropertyTabs = Boolean.valueOf(enableAdvancedPropertyTabs).booleanValue();
2274        if (CmsLog.INIT.isInfoEnabled()) {
2275            CmsLog.INIT.info(
2276                Messages.get().getBundle().key(
2277                    m_enableAdvancedPropertyTabs
2278                    ? Messages.INIT_ADV_PROP_DIALOG_SHOW_TABS_0
2279                    : Messages.INIT_ADV_PROP_DIALOG_HIDE_TABS_0));
2280        }
2281    }
2282
2283    /**
2284     * Sets the options related to the 'Categories' column in the file explorer.
2285     *
2286     * @param enabled 'true' if the column should be enabled
2287     * @param leavesOnly 'true' if parent categories should be omitted
2288     * @param withPath 'true' if category labels should include the whole path (i.e. the titles of parent categories)
2289     */
2290    public void setExplorerCategoryOptions(String enabled, String leavesOnly, String withPath) {
2291
2292        m_explorerCategoriesEnabled = Boolean.parseBoolean(enabled);
2293        m_explorerCategoriesLeavesOnly = Boolean.parseBoolean(leavesOnly);
2294        m_explorerCategoriesWithPath = Boolean.parseBoolean(withPath);
2295
2296    }
2297
2298    /**
2299     * Sets the value (in kb) for the maximum file upload size.<p>
2300     *
2301     * @param value the value (in kb) for the maximum file upload size
2302     */
2303    public void setFileMaxUploadSize(String value) {
2304
2305        try {
2306            m_fileMaxUploadSize = Integer.valueOf(value).intValue();
2307        } catch (NumberFormatException e) {
2308            // can usually be ignored
2309            if (LOG.isInfoEnabled()) {
2310                LOG.info(e.getLocalizedMessage());
2311            }
2312            m_fileMaxUploadSize = -1;
2313        }
2314        if (CmsLog.INIT.isInfoEnabled()) {
2315            if (m_fileMaxUploadSize > 0) {
2316                CmsLog.INIT.info(
2317                    Messages.get().getBundle().key(
2318                        Messages.INIT_MAX_FILE_UPLOAD_SIZE_1,
2319                        Integer.valueOf(m_fileMaxUploadSize)));
2320            } else {
2321                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_MAX_FILE_UPLOAD_SIZE_UNLIMITED_0));
2322            }
2323
2324        }
2325    }
2326
2327    /**
2328     * Sets the system-wide file view settings for the workplace.<p>
2329     *
2330     * @param cms the CmsObject for ensuring security constraints.
2331     *
2332     * @param fileViewSettings the system-wide file view settings for the workplace to set
2333     *
2334     * @throws CmsRoleViolationException if the current user does not own the administrator role ({@link CmsRole#ROOT_ADMIN})
2335     * */
2336    public void setFileViewSettings(CmsObject cms, CmsRfsFileViewer fileViewSettings) throws CmsRoleViolationException {
2337
2338        if (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_2_INITIALIZING) {
2339            OpenCms.getRoleManager().checkRole(cms, CmsRole.ROOT_ADMIN);
2340        }
2341        m_fileViewSettings = fileViewSettings;
2342        // disallow modifications of this "new original"
2343        m_fileViewSettings.setFrozen(true);
2344    }
2345
2346    /**
2347     * Sets the gallery default scope.<p>
2348     *
2349     * @param galleryDefaultScope the gallery default scope
2350     */
2351    public void setGalleryDefaultScope(String galleryDefaultScope) {
2352
2353        m_galleryDefaultScope = galleryDefaultScope;
2354        try {
2355            CmsGallerySearchScope.valueOf(galleryDefaultScope);
2356        } catch (Throwable t) {
2357            LOG.warn(t.getLocalizedMessage(), t);
2358        }
2359    }
2360
2361    /**
2362     * Sets the group translation class name.<p>
2363     *
2364     * @param translationClassName the group translation class name
2365     */
2366    public void setGroupTranslationClass(String translationClassName) {
2367
2368        m_groupTranslationClass = translationClassName;
2369    }
2370
2371    /**
2372     * Sets the "keep alive" mode.<p>
2373     *
2374     * @param keepAlive the keep-alive mode
2375     */
2376    public void setKeepAlive(String keepAlive) {
2377
2378        m_keepAlive = Boolean.valueOf(keepAlive);
2379    }
2380
2381    /**
2382     * Sets the post upload dialog handler.<p>
2383     *
2384     * @param uploadHandler the post upload handler
2385     */
2386    public void setPostUploadHandler(I_CmsPostUploadDialogHandler uploadHandler) {
2387
2388        m_postUploadHandler = uploadHandler;
2389    }
2390
2391    /**
2392     * Sets the repository folder handler.<p>
2393     *
2394     * @param clazz the repository folder handler
2395     */
2396    public void setRepositoryFolderHandler(I_CmsRepositoryFolderHandler clazz) {
2397
2398        m_repositoryFolderHandler = clazz;
2399        if (CmsLog.INIT.isInfoEnabled()) {
2400            CmsLog.INIT.info(
2401                org.opencms.configuration.Messages.get().getBundle().key(
2402                    org.opencms.configuration.Messages.INIT_REPOSITORY_FOLDER_1,
2403                    m_repositoryFolderHandler.getClass().getName()));
2404        }
2405    }
2406
2407    /**
2408     * Sets the name of the role necessary for editing the sitemap configuration.
2409     *
2410     * @param roleName the name of the role necessary for editing the sitemap configuration
2411     */
2412    public void setSitemapConfigEditRole(String roleName) {
2413
2414        m_sitemapConfigEditRole = roleName;
2415    }
2416
2417    /**
2418     * Sets the role users should have to be able to manage detail pages from the sitemap editor.
2419     *
2420     * @param sitemapEditorDetailPageManagementRole the role name
2421     */
2422    public void setSitemapEditorDetailPageManagementRole(String sitemapEditorDetailPageManagementRole) {
2423
2424        m_sitemapEditorDetailPageManagementRole = sitemapEditorDetailPageManagementRole;
2425    }
2426
2427    /**
2428     * Sets the tool Manager object.<p>
2429     *
2430     * @param toolManager the tool Manager object to set
2431     */
2432    public void setToolManager(CmsToolManager toolManager) {
2433
2434        m_toolManager = toolManager;
2435    }
2436
2437    /**
2438     * Sets the upload restriciton.
2439     *
2440     * @param uploadRestriction the upload restriction
2441     */
2442    public void setUploadRestriction(I_CmsUploadRestriction uploadRestriction) {
2443
2444        if (m_uploadRestrictionSet) {
2445            throw new IllegalStateException("Upload restriction has already been set.");
2446        }
2447        m_uploadRestriction = uploadRestriction;
2448        m_uploadRestrictionSet = true;
2449    }
2450
2451    /**
2452     * Sets the user additional information configuration manager.<p>
2453     *
2454     * @param userInfoManager the manager to set
2455     */
2456    public void setUserInfoManager(CmsWorkplaceUserInfoManager userInfoManager) {
2457
2458        m_userInfoManager = userInfoManager;
2459    }
2460
2461    /**
2462     * Sets the user list mode.<p>
2463     *
2464     * @param mode the user list mode
2465     */
2466    public void setUserListMode(String mode) {
2467
2468        m_userListMode = mode;
2469    }
2470
2471    /**
2472     * Controls if the user/group icon in the administration view should be shown.<p>
2473     *
2474     * @param value <code>"true"</code> if the user/group icon in the administration view should be shown, otherwise false
2475     */
2476    public void setUserManagementEnabled(String value) {
2477
2478        m_showUserGroupIcon = Boolean.valueOf(value).booleanValue();
2479        if (CmsLog.INIT.isInfoEnabled()) {
2480            if (m_showUserGroupIcon) {
2481                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_USER_MANAGEMENT_ICON_ENABLED_0));
2482            } else {
2483                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_USER_MANAGEMENT_ICON_DISABLED_0));
2484            }
2485        }
2486    }
2487
2488    /**
2489     * Sets the virus scanner.
2490     *
2491     * @param virusScanner the virus scanner to set
2492     */
2493    public void setVirusScanner(I_CmsVirusScanner virusScanner) {
2494
2495        m_virusScanner = virusScanner;
2496    }
2497
2498    /**
2499     * Sets the virus scanner to enabled/disabled.
2500     *
2501     * @param enabled true if the virus scanner should be enabled
2502     */
2503    public void setVirusScannerEnabled(boolean enabled) {
2504
2505        m_virusScannerEnabled = enabled;
2506    }
2507
2508    /**
2509     * Sets the auto correction of XML contents when they are opened with the editor.<p>
2510     *
2511     * @param xmlContentAutoCorrect if "true", the content will be corrected without notification, otherwise a confirmation is needed
2512     */
2513    public void setXmlContentAutoCorrect(String xmlContentAutoCorrect) {
2514
2515        m_xmlContentAutoCorrect = Boolean.valueOf(xmlContentAutoCorrect).booleanValue();
2516        if (CmsLog.INIT.isInfoEnabled()) {
2517            CmsLog.INIT.info(
2518                Messages.get().getBundle().key(
2519                    m_xmlContentAutoCorrect
2520                    ? Messages.INIT_XMLCONTENT_AUTOCORRECT_ENABLED_0
2521                    : Messages.INIT_XMLCONTENT_AUTOCORRECT_DISABLED_0));
2522        }
2523    }
2524
2525    /**
2526     * Returns true if the Acacia editor in standalone mode should automatically unlock resources.<p>
2527     *
2528     * @return true if resources should be automatically unlocked in standalone mode
2529     */
2530    public boolean shouldAcaciaUnlock() {
2531
2532        if (m_acaciaUnlock == null) {
2533            return true;
2534        } else {
2535            return Boolean.parseBoolean(m_acaciaUnlock);
2536        }
2537    }
2538
2539    /**
2540     * Returns if the user/group icon in the administration view should be shown.<p>
2541     *
2542     * @return true if the user/group icon in the administration view should be shown, otherwise false
2543     */
2544    public boolean showUserGroupIcon() {
2545
2546        return m_showUserGroupIcon;
2547    }
2548
2549    /**
2550     * Returns true if lazy user lists should be used.<p>
2551     *
2552     * @return true if lazy user lists should be used
2553     */
2554    public boolean supportsLazyUserLists() {
2555
2556        boolean result = "lazy".equalsIgnoreCase(m_userListMode);
2557        if (org.opencms.db.mssql.CmsUserDriver.isInstantiated()) {
2558            LOG.warn("Lazy user lists currently not supported on MSSQL, using classic user list mode as a fallback.");
2559            result = false;
2560        }
2561        return result;
2562
2563    }
2564
2565    /**
2566     * Translates a group name using the configured {@link I_CmsGroupNameTranslation}.<p>
2567     *
2568     * @param groupName the group name
2569     * @param keepOu if true, the OU will be appended to the translated name
2570     *
2571     * @return the translated group name
2572     */
2573    public String translateGroupName(String groupName, boolean keepOu) {
2574
2575        I_CmsGroupNameTranslation translation = getGroupNameTranslation();
2576        return translation.translateGroupName(groupName, keepOu);
2577    }
2578
2579    /**
2580     * Gets the default view name ( = explorer type) for the given type.<p>
2581     *
2582     * @param typeName a resource type name
2583     * @return the default view for the given type
2584     */
2585    String getDefaultView(String typeName) {
2586
2587        String result = m_defaultViewRules.getViewForType(typeName);
2588        if (result == null) {
2589            result = "view_other";
2590            try {
2591                if (OpenCms.getResourceManager().hasResourceType(typeName)
2592                    && OpenCms.getResourceManager().getResourceType(typeName).isFolder()) {
2593                    result = "view_folders";
2594                }
2595            } catch (CmsLoaderException e) {
2596                LOG.error(e.getLocalizedMessage(), e);
2597            }
2598        }
2599        return result;
2600    }
2601
2602    /**
2603     * Creates a copy of the admin cms object which is initialize with the data of the current cms object.<p>
2604     *
2605     * @param cms the current cms object
2606     * @return the new admin cms object
2607     *
2608     * @throws CmsException if something goes wrong
2609     */
2610    private CmsObject getAdminCms(CmsObject cms) throws CmsException {
2611
2612        CmsObject adminCms = OpenCms.initCmsObject(m_adminCms);
2613        adminCms.getRequestContext().setSiteRoot(cms.getRequestContext().getSiteRoot());
2614        adminCms.getRequestContext().setRequestTime(cms.getRequestContext().getRequestTime());
2615        adminCms.getRequestContext().setCurrentProject(cms.getRequestContext().getCurrentProject());
2616        adminCms.getRequestContext().setEncoding(cms.getRequestContext().getEncoding());
2617        adminCms.getRequestContext().setUri(cms.getRequestContext().getUri());
2618        return adminCms;
2619    }
2620
2621    /**
2622     * Returns a dummy group name translation which leaves the group names unchanged.<p>
2623     *
2624     * @return a dummy group name translation
2625     */
2626    private I_CmsGroupNameTranslation getDefaultGroupNameTranslation() {
2627
2628        return new I_CmsGroupNameTranslation() {
2629
2630            public String translateGroupName(String group, boolean keepOu) {
2631
2632                return keepOu ? group : CmsOrganizationalUnit.getSimpleName(group);
2633            }
2634        };
2635    }
2636
2637    /**
2638     * Returns the role required for enabling the upload functionality.
2639     *
2640     * @return the upload role
2641     */
2642    private CmsRole getUploadRole() {
2643
2644        return isAllowElementAuthorToWorkInGalleries() ? CmsRole.ELEMENT_AUTHOR : CmsRole.EDITOR;
2645    }
2646
2647    /**
2648     * Initializes the configured explorer type settings.<p>
2649     */
2650    private synchronized void initExplorerTypeSettings() {
2651
2652        Map<String, CmsExplorerTypeSettings> explorerTypeSettingsMap = new HashMap<String, CmsExplorerTypeSettings>();
2653        List<CmsExplorerTypeSettings> explorerTypeSettings = new ArrayList<CmsExplorerTypeSettings>();
2654
2655        if (m_defaultAccess.getAccessControlList() == null) {
2656            try {
2657                // initialize the default access control configuration
2658                m_defaultAccess.createAccessControlList(CmsExplorerTypeAccess.PRINCIPAL_DEFAULT);
2659            } catch (CmsException e) {
2660                if (CmsLog.INIT.isInfoEnabled()) {
2661                    CmsLog.INIT.info(
2662                        Messages.get().getBundle().key(
2663                            Messages.INIT_ADD_TYPE_SETTING_FAILED_1,
2664                            CmsExplorerTypeAccess.PRINCIPAL_DEFAULT),
2665                        e);
2666                }
2667            }
2668        }
2669
2670        explorerTypeSettings.addAll(m_explorerTypeSettingsFromXml);
2671        explorerTypeSettings.addAll(m_explorerTypeSettingsFromModules);
2672
2673        for (int i = 0; i < explorerTypeSettings.size(); i++) {
2674            CmsExplorerTypeSettings settings = explorerTypeSettings.get(i);
2675            // put the settings in the lookup map
2676            explorerTypeSettingsMap.put(settings.getName(), settings);
2677            if (getDefaultAccess() == settings.getAccess()) {
2678                continue;
2679            }
2680            try {
2681                // initialize the access control configuration of the explorer type
2682                settings.getAccess().createAccessControlList(settings.getName());
2683            } catch (CmsException e) {
2684                if (CmsLog.INIT.isInfoEnabled()) {
2685                    CmsLog.INIT.info(
2686                        Messages.get().getBundle().key(Messages.INIT_ADD_TYPE_SETTING_FAILED_1, settings.getName()),
2687                        e);
2688                }
2689            }
2690        }
2691        // sort the explorer type settings
2692        Collections.sort(explorerTypeSettings);
2693        // make the settings unmodifiable and store them in the global variables
2694        m_explorerTypeSettings = Collections.unmodifiableList(explorerTypeSettings);
2695        m_explorerTypeSettingsMap = Collections.unmodifiableMap(explorerTypeSettingsMap);
2696
2697        m_explorerTypeViews = Maps.newHashMap();
2698        Set<String> explorerTypeViews = Sets.newHashSet();
2699        for (CmsExplorerTypeSettings explorerType : getExplorerTypeSettings()) {
2700            if (explorerType.isView()) {
2701                explorerTypeViews.add(explorerType.getName());
2702            }
2703        }
2704
2705        for (String typeName : explorerTypeViews) {
2706            CmsExplorerTypeSettings explorerType = OpenCms.getWorkplaceManager().getExplorerTypeSetting(typeName);
2707            CmsElementView elemView = new CmsElementView(explorerType);
2708            m_explorerTypeViews.put(elemView.getId(), elemView);
2709        }
2710
2711    }
2712
2713    /**
2714     * Initializes the workplace locale set.<p>
2715     *
2716     * Currently, this is defined by the existence of a special folder
2717     * <code>/system/workplace/locales/{locale-name}/</code>.
2718     * This is likely to change in future implementations.<p>
2719     *
2720     * @param cms an OpenCms context object that must have been initialized with "Admin" permissions
2721     *
2722     * @return the workplace locale set
2723     */
2724    private List<Locale> initWorkplaceLocales(CmsObject cms) {
2725
2726        Set<Locale> locales = new HashSet<Locale>();
2727
2728        // collect locales from the VFS
2729        if (cms.existsResource(CmsWorkplace.VFS_PATH_LOCALES)) {
2730            List<CmsResource> localeFolders;
2731            try {
2732                localeFolders = cms.getSubFolders(CmsWorkplace.VFS_PATH_LOCALES);
2733            } catch (CmsException e) {
2734                LOG.warn(
2735                    Messages.get().getBundle().key(
2736                        Messages.LOG_WORKPLACE_INIT_NO_LOCALES_1,
2737                        CmsWorkplace.VFS_PATH_LOCALES),
2738                    e);
2739                // can not throw exception here since then OpenCms would not even start in shell mode (runlevel 2)
2740                localeFolders = new ArrayList<CmsResource>();
2741            }
2742            Iterator<CmsResource> i = localeFolders.iterator();
2743            while (i.hasNext()) {
2744                CmsFolder folder = (CmsFolder)i.next();
2745                Locale locale = CmsLocaleManager.getLocale(folder.getName());
2746                // add locale
2747                locales.add(locale);
2748                // add less specialized locale
2749                locales.add(new Locale(locale.getLanguage(), locale.getCountry()));
2750                // add even less specialized locale
2751                locales.add(new Locale(locale.getLanguage()));
2752            }
2753        }
2754        // collect locales from JAR manifests
2755        try {
2756            Enumeration<URL> resources = getClass().getClassLoader().getResources(MANIFEST_RESOURCE_NAME);
2757
2758            while (resources.hasMoreElements()) {
2759                URL resUrl = resources.nextElement();
2760                try {
2761                    Manifest manifest = new Manifest(resUrl.openStream());
2762                    String localeString = manifest.getMainAttributes().getValue(LOCALIZATION_ATTRIBUTE_NAME);
2763                    if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(localeString)) {
2764                        Locale locale = CmsLocaleManager.getLocale(localeString);
2765                        // add locale
2766                        locales.add(locale);
2767                        // add less specialized locale
2768                        locales.add(new Locale(locale.getLanguage(), locale.getCountry()));
2769                        // add even less specialized locale
2770                        locales.add(new Locale(locale.getLanguage()));
2771                    }
2772                } catch (IOException e) {
2773                    LOG.warn(
2774                        "Error reading manifest from " + resUrl + " while evaluating available workplace localization.",
2775                        e);
2776                }
2777            }
2778        } catch (IOException e) {
2779            LOG.error("Error evaluating available workplace localization from JAR manifests.", e);
2780        }
2781
2782        // sort the result
2783        ArrayList<Locale> result = new ArrayList<Locale>();
2784        result.addAll(locales);
2785        Collections.sort(result, CmsLocaleComparator.getComparator());
2786        return result;
2787    }
2788
2789    /**
2790     * Initializes the available workplace views.<p>
2791     *
2792     * Currently, this is defined by iterating the subfolder of the folder
2793     * <code>/system/workplace/views/</code>.
2794     * These subfolders must have the properties NavPos, NavText and default-file set.<p>
2795     *
2796     * @param cms an OpenCms context object that must have been initialized with "Admin" permissions
2797     * @return the available workplace views
2798     */
2799    private List<CmsWorkplaceView> initWorkplaceViews(CmsObject cms) {
2800
2801        List<CmsResource> viewFolders;
2802        try {
2803            // get the subfolders of the "views" folder
2804            viewFolders = cms.getSubFolders(CmsWorkplace.VFS_PATH_VIEWS);
2805        } catch (CmsException e) {
2806            if ((OpenCms.getRunLevel() > OpenCms.RUNLEVEL_2_INITIALIZING) && LOG.isInfoEnabled()) {
2807                LOG.info(
2808                    Messages.get().getBundle().key(Messages.LOG_WORKPLACE_INIT_NO_VIEWS_1, CmsWorkplace.VFS_PATH_VIEWS),
2809                    e);
2810            }
2811            // can not throw exception here since then OpenCms would not even start in shell mode (runlevel 2)
2812            viewFolders = new ArrayList<CmsResource>();
2813        }
2814        m_views = new ArrayList<CmsWorkplaceView>(viewFolders.size());
2815        for (int i = 0; i < viewFolders.size(); i++) {
2816            // loop through all view folders
2817            CmsFolder folder = (CmsFolder)viewFolders.get(i);
2818            String folderPath = cms.getSitePath(folder);
2819            try {
2820                // get view information from folder properties
2821                String order = cms.readPropertyObject(
2822                    folderPath,
2823                    CmsPropertyDefinition.PROPERTY_NAVPOS,
2824                    false).getValue();
2825                String key = cms.readPropertyObject(
2826                    folderPath,
2827                    CmsPropertyDefinition.PROPERTY_NAVTEXT,
2828                    false).getValue();
2829                String viewUri = cms.readPropertyObject(
2830                    folderPath,
2831                    CmsPropertyDefinition.PROPERTY_DEFAULT_FILE,
2832                    false).getValue();
2833                if (viewUri == null) {
2834                    // no view URI found
2835                    viewUri = folderPath;
2836                } else if (!viewUri.startsWith("/")) {
2837                    // default file is in current view folder, create absolute path to view URI
2838                    viewUri = folderPath + viewUri;
2839                }
2840                if (order == null) {
2841                    // no valid NavPos property value found, use loop count as order value
2842                    order = "" + i;
2843                }
2844                Float orderValue;
2845                try {
2846                    // create Float order object
2847                    orderValue = Float.valueOf(order);
2848                } catch (NumberFormatException e) {
2849                    // String was not formatted correctly, use loop counter
2850                    orderValue = Float.valueOf(i);
2851                }
2852                if (key == null) {
2853                    // no language key found, use default String to avoid NullPointerException
2854                    key = "View " + i;
2855                    // if no navtext is given do not display the view
2856                    continue;
2857                }
2858                // create new view object
2859                CmsWorkplaceView view = new CmsWorkplaceView(key, viewUri, orderValue);
2860                m_views.add(view);
2861                // log the view
2862                if (CmsLog.INIT.isInfoEnabled()) {
2863                    CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_WORKPLACE_VIEW_1, view.getUri()));
2864                }
2865            } catch (CmsException e) {
2866                // should usually never happen
2867                LOG.error(Messages.get().getBundle().key(Messages.LOG_READING_VIEW_FOLDER_FAILED_1, folderPath), e);
2868            }
2869        }
2870        // sort the views by their order number
2871        Collections.sort(m_views);
2872        return m_views;
2873    }
2874
2875}