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