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