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