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.main;
029
030import org.opencms.file.CmsObject;
031import org.opencms.i18n.CmsEncoder;
032import org.opencms.jsp.util.I_CmsJspDeviceSelector;
033import org.opencms.mail.CmsMailSettings;
034import org.opencms.util.CmsFileUtil;
035import org.opencms.util.CmsStringUtil;
036
037import java.io.File;
038import java.util.Collections;
039import java.util.Map;
040import java.util.Properties;
041import java.util.TreeMap;
042import java.util.jar.JarFile;
043
044/**
045 * Provides access to system wide "read only" information about the running OpenCms instance.<p>
046 *
047 * Contains information about:
048 * <ul>
049 * <li>version and build number</li>
050 * <li>server name</li>
051 * <li>mail settings</li>
052 * <li>configuration paths</li>
053 * <li>default character encoding</li>
054 * <li>...and more.</li>
055 * </ul>
056 *
057 * @since 6.0.0
058 */
059public class CmsSystemInfo {
060
061    /**
062     * Wrapper class used to access build information.<p>
063     */
064    public class BuildInfoItem {
065
066        /** The key name. */
067        private String m_keyName;
068
069        /** The nice name for display. */
070        private String m_niceName;
071
072        /** The build information value. */
073        private String m_value;
074
075        /**
076         * Creates a new instance wrapping a build info string array.<p>
077         *
078         * @param value the value
079         * @param niceName the nice name
080         * @param keyName the key name
081         */
082        public BuildInfoItem(String value, String niceName, String keyName) {
083
084            m_value = value;
085            m_niceName = niceName;
086            m_keyName = keyName;
087        }
088
089        /**
090         * Gets the key name for this build info item.<p>
091         *
092         * @return the value
093         */
094        public String getKeyName() {
095
096            return m_keyName;
097        }
098
099        /**
100         * Gets the nice name for this build info item.<p>
101         *
102         * @return the nice name
103         */
104        public String getNiceName() {
105
106            return m_niceName;
107        }
108
109        /**
110         * Gets the value for this build info item.<p>
111         *
112         * @return the value
113         */
114        public String getValue() {
115
116            return m_value;
117        }
118    }
119
120    /** Name of the config folder property provides as Java VM parameter -Dopencms.config=.*/
121    public static final String CONFIG_FOLDER_PROPERTY = "opencms.config";
122
123    /** Relative path to persistence.xml file. */
124    public static final String FILE_PERSISTENCE = "classes"
125        + File.separatorChar
126        + "META-INF"
127        + File.separatorChar
128        + "persistence.xml";
129
130    /** The name of the opencms.properties file. */
131    public static final String FILE_PROPERTIES = "opencms.properties";
132
133    /** The name of the opencms.tld file. */
134    public static final String FILE_TLD = "opencms.tld";
135
136    /** Path to the default "config" folder relative to the "WEB-INF" directory of the application. */
137    public static final String FOLDER_CONFIG_DEFAULT = "config" + File.separatorChar;
138
139    /** The name of the module folder in the package path. */
140    public static final String FOLDER_MODULES = "modules" + File.separatorChar;
141
142    /** Path to the "packages" folder relative to the "WEB-INF" directory of the application. */
143    public static final String FOLDER_PACKAGES = "packages" + File.separatorChar;
144
145    /** Path to the "WEB-INF" folder relative to the directory of the application. */
146    public static final String FOLDER_WEBINF = "WEB-INF" + File.separatorChar;
147
148    /** The workplace UI servlet name. */
149    public static final String WORKPLACE_PATH = "/workplace";
150
151    /** Default encoding. */
152    private static final String DEFAULT_ENCODING = CmsEncoder.ENCODING_UTF_8;
153
154    /** Static version id to use if version.properties can not be read. */
155    private static final String DEFAULT_VERSION_ID = "Static";
156
157    /** Static version number to use if version.properties can not be read. */
158    private static final String DEFAULT_VERSION_NUMBER = "9.x.y";
159
160    /** The VFS config files folder. */
161    public static final String VFS_CONFIG_FOLDER = "/system/config/";
162
163    /** The folder to contain configuration file overrides. */
164    public static final String VFS_CONFIG_OVERRIDE_FOLDER = VFS_CONFIG_FOLDER + "overrides/";
165
166    /** The list of additional version information that was contained in the version.properties file. */
167    private Map<String, BuildInfoItem> m_buildInfo;
168
169    /** The absolute path to the "opencms.properties" configuration file (in the "real" file system). */
170    private String m_configurationFileRfsPath;
171
172    /** Default encoding, can be set in opencms-system.xml. */
173    private String m_defaultEncoding;
174
175    /** The device selector instance. */
176    private I_CmsJspDeviceSelector m_deviceSelector;
177
178    /** Indicates if the version history is enabled. */
179    private boolean m_historyEnabled;
180
181    /** The maximum number of entries in the version history (per resource). */
182    private int m_historyVersions;
183
184    /** The maximum number of versions in the VFS version history for deleted resources. */
185    private int m_historyVersionsAfterDeletion;
186
187    /** The HTTP basic authentication settings. */
188    private CmsHttpAuthenticationSettings m_httpAuthenticationSettings;
189
190    /** The settings for the internal OpenCms email service. */
191    private CmsMailSettings m_mailSettings;
192
193    /** The project in which time stamps for the content notification are read. */
194    private String m_notificationProject;
195
196    /** The duration after which responsible resource owners will be notified about out-dated content (in days). */
197    private int m_notificationTime;
198
199    /** The absolute path to the "packages" folder (in the "real" file system). */
200    private String m_packagesRfsPath;
201
202    /** The absolute path to the persistence.xml file (in the "real" file system). */
203    private String m_persistenceFileRfsPath;
204
205    /** True if detail contents are restricted to detail pages from the same site. */
206    private boolean m_restrictDetailContents;
207
208    /** The name of the OpenCms server. */
209    private String m_serverName;
210
211    /** The servlet container specific settings. */
212    private CmsServletContainerSettings m_servletContainerSettings;
213
214    /** The startup time of this OpenCms instance. */
215    private long m_startupTime;
216
217    /** The static resource version parameter. */
218    private String m_staticResourcePathFragment;
219
220    /** The version identifier of this OpenCms installation, contains "OpenCms/" and the version number. */
221    private String m_version;
222
223    /** The version ID of this OpenCms installation, usually set by the build system. */
224    private String m_versionId;
225
226    /** The version number of this OpenCms installation. */
227    private String m_versionNumber;
228
229    /**
230     * Creates a new system info container.<p>
231     */
232    public CmsSystemInfo() {
233
234        // set startup time
235        m_startupTime = System.currentTimeMillis();
236        // init version information
237        initVersion();
238        // set default encoding (will be changed again later when properties have been read)
239        m_defaultEncoding = DEFAULT_ENCODING.intern();
240        // this may look odd, but initMembers in OpenCms core has to initialize this (e.g. for setup to avoid NPE)
241        m_servletContainerSettings = new CmsServletContainerSettings(null);
242    }
243
244    /**
245     * Returns an absolute path (to a directory or a file in the "real" file system) from a path relative to
246     * the web application folder of OpenCms.<p>
247     *
248     * If the provided path is already absolute, then it is returned unchanged.
249     * If the provided path is a folder, the result will always end with a folder separator.<p>
250     *
251     * @param path the path (relative) to generate an absolute path from
252     * @return an absolute path (to a directory or a file) from a path relative to the web application folder of OpenCms
253     */
254    public String getAbsoluteRfsPathRelativeToWebApplication(String path) {
255
256        if ((path == null) || (getWebApplicationRfsPath() == null)) {
257            return null;
258        }
259        // check for absolute path is system depended, let's just use the standard check
260        File f = new File(path);
261        if (f.isAbsolute()) {
262            // apparently this is an absolute path already
263            path = f.getAbsolutePath();
264            if (f.isDirectory() && !path.endsWith(File.separator)) {
265                // make sure all folder paths end with a separator
266                path = path.concat(File.separator);
267            }
268            return path;
269        }
270        return CmsFileUtil.normalizePath(getWebApplicationRfsPath() + path);
271    }
272
273    /**
274     * Returns an absolute path (to a directory or a file in the "real" file system) from a path relative to
275     * the "WEB-INF" folder of the OpenCms web application.<p>
276     *
277     * If the provided path is already absolute, then it is returned unchanged.<p>
278     *
279     * @param path the path (relative) to generate an absolute path from
280     * @return an absolute path (to a directory or a file) from a path relative to the "WEB-INF" folder
281     */
282    public String getAbsoluteRfsPathRelativeToWebInf(String path) {
283
284        if (path == null) {
285            return null;
286        }
287        // check for absolute path is system depended, let's just use the standard check
288        File f = new File(path);
289        if (f.isAbsolute()) {
290            // apparently this is an absolute path already
291            return f.getAbsolutePath();
292        }
293        return CmsFileUtil.normalizePath(getWebInfRfsPath() + path);
294    }
295
296    /**
297     * Returns the map of additional build information that was contained in the version.properties file.<p>
298     *
299     * The values are String arrays of length 2. First in this array is the actual value,
300     * and second the "nice name" for the value that can be used to display the value somewhere.
301     * In case no nice name was provided, the second value will repeat the key name.<p>
302     *
303     * @return the map of additional build information that was contained in the version.properties file
304     *
305     * @since 9.5.0
306     */
307    public Map<String, BuildInfoItem> getBuildInfo() {
308
309        return m_buildInfo;
310    }
311
312    /**
313     * Returns the path to a configuration file.<p>
314     * This will either be a file below /system/config/ or in case an override file exists below /system/config/overrides/.<p>
315     *
316     * @param cms the cms ontext
317     * @param configFile the config file path within /system/config/
318     *
319     * @return the file path
320     */
321    public String getConfigFilePath(CmsObject cms, String configFile) {
322
323        String path = CmsStringUtil.joinPaths(VFS_CONFIG_OVERRIDE_FOLDER, configFile);
324        if (!cms.existsResource(path)) {
325            path = CmsStringUtil.joinPaths(VFS_CONFIG_FOLDER, configFile);
326        }
327        return path;
328    }
329
330    /**
331     * Gets the path of the opencms config folder.<p>
332     * Per default this is the "/WEB-INF/config/ folder.
333     * If configured with the "-Dopencms.config=..." java startup parameter, OpenCms can access an external config
334     * folder outside its webapplication.
335     * @return complete rfs path to the config folder.
336     */
337    public String getConfigFolder() {
338
339        // check if the system property is set and return its value
340        if (CmsStringUtil.isNotEmpty(System.getProperty(CONFIG_FOLDER_PROPERTY))) {
341            return System.getProperty(CONFIG_FOLDER_PROPERTY);
342        } else {
343            return getAbsoluteRfsPathRelativeToWebInf(FOLDER_CONFIG_DEFAULT);
344        }
345    }
346
347    /**
348     * Returns the absolute path to the "opencms.properties" configuration file (in the "real" file system).<p>
349     *
350     * @return the absolute path to the "opencms.properties" configuration file
351     */
352    public String getConfigurationFileRfsPath() {
353
354        if (m_configurationFileRfsPath == null) {
355            m_configurationFileRfsPath = getConfigFolder() + FILE_PROPERTIES;
356        }
357        return m_configurationFileRfsPath;
358    }
359
360    /**
361     * Returns the web application context path, e.g. "" (empty String) if the web application
362     * is the default web application (usually "ROOT"), or "/opencms" if the web application
363     * is called "opencms".<p>
364     *
365     * <i>From the Java Servlet Specification v2.4:</i><br>
366     * <b>Context Path:</b> The path prefix associated with the ServletContext that this
367     * servlet is a part of. If this context is the "default" context rooted at the base of
368     * the web server's URL name space, this path will be an empty string. Otherwise,
369     * if the context is not rooted at the root of the server's name space, the path starts
370     * with a "/" character but does not end with a "/" character.<p>
371     *
372     * @return the web application context path
373     * @see #getWebApplicationName()
374     * @see #getServletPath()
375     * @see #getOpenCmsContext()
376     */
377    public String getContextPath() {
378
379        return m_servletContainerSettings.getContextPath();
380    }
381
382    /**
383     * Return the OpenCms default character encoding.<p>
384     *
385     * The default is set in the opencms-system.xml file.
386     * If this is not set in opencms-system.xml the default
387     * is "UTF-8".<p>
388     *
389     * @return the default encoding, e.g. "UTF-8" or "ISO-8859-1"
390     */
391    public String getDefaultEncoding() {
392
393        return m_defaultEncoding;
394    }
395
396    /**
397     * Returns the default web application name (usually "ROOT").<p>
398     *
399     * @return the default web application name
400     */
401    public String getDefaultWebApplicationName() {
402
403        return m_servletContainerSettings.getDefaultWebApplicationName();
404    }
405
406    /**
407     * Gets the device selector.<p>
408     *
409     * @return the device selector
410     */
411    public I_CmsJspDeviceSelector getDeviceSelector() {
412
413        return m_deviceSelector;
414    }
415
416    /**
417     * Returns the maximum number of versions that are kept per file in the VFS version history.<p>
418     *
419     * If the version history is disabled, this setting has no effect.<p>
420     *
421     * @return the maximum number of versions that are kept per file
422     * @see #isHistoryEnabled()
423     */
424    public int getHistoryVersions() {
425
426        return m_historyVersions;
427    }
428
429    /**
430     * Returns the number of versions in the VFS version history that should be
431     * kept after a resource is deleted.<p>
432     *
433     * For resources in folders where the history.removedeleted property is set to "true", this setting is ignored.
434     *
435     * @return the number versions in the VFS version history for deleted resources
436     */
437    public int getHistoryVersionsAfterDeletion() {
438
439        return m_historyVersionsAfterDeletion;
440    }
441
442    /**
443     * Returns the HTTP authentication settings.<p>
444     *
445     * @return the HTTP authentication settings
446     */
447    public CmsHttpAuthenticationSettings getHttpAuthenticationSettings() {
448
449        return m_httpAuthenticationSettings;
450    }
451
452    /**
453     * Returns the absolute path to the folder of the main OpenCms log file
454     * (in the "real" file system).<p>
455     *
456     * If the method returns <code>null</code>, this means that the log
457     * file is not managed by OpenCms.<p>
458     *
459     * @return the absolute path to the folder of the main OpenCms log file (in
460     * the "real" file system)
461     */
462    public String getLogFileRfsFolder() {
463
464        return CmsLog.getLogFileRfsFolder();
465    }
466
467    /**
468     * Returns the filename of the log file (in the "real" file system).<p>
469     *
470     * If the method returns <code>null</code>, this means that the log
471     * file is not managed by OpenCms.<p>
472     *
473     * @return the filename of the log file (in the "real" file system)
474     */
475    public String getLogFileRfsPath() {
476
477        return CmsLog.getLogFileRfsPath();
478    }
479
480    /**
481     * Returns the settings for the internal OpenCms email service.<p>
482     *
483     * @return the settings for the internal OpenCms email service
484     */
485    public CmsMailSettings getMailSettings() {
486
487        return m_mailSettings;
488    }
489
490    /**
491     * Returns the project in which time stamps for the content notification are read.<p>
492     *
493     * @return the project in which time stamps for the content notification are read
494     */
495    public String getNotificationProject() {
496
497        return m_notificationProject;
498    }
499
500    /**
501     * Returns the duration after which responsible resource owners will be notified about out-dated content (in days).<p>
502     *
503     * @return the duration after which responsible resource owners will be notified about out-dated content
504     */
505    public int getNotificationTime() {
506
507        return m_notificationTime;
508    }
509
510    /**
511     * Returns the OpenCms request context, e.g. "/opencms/opencms".<p>
512     *
513     * The OpenCms context will always start with a "/" and never have a trailing "/".
514     * The OpenCms context is identical to <code>getContexPath() + getServletPath()</code>.<p>
515     *
516     * @return the OpenCms request context, e.g. "/opencms/opencms"
517     * @see #getContextPath()
518     * @see #getServletPath()
519     */
520    public String getOpenCmsContext() {
521
522        return m_servletContainerSettings.getOpenCmsContext();
523    }
524
525    /**
526     * Returns the absolute path to the "packages" folder (in the "real" file system).<p>
527     *
528     * @return the absolute path to the "packages" folder
529     */
530    public String getPackagesRfsPath() {
531
532        if (m_packagesRfsPath == null) {
533            m_packagesRfsPath = getAbsoluteRfsPathRelativeToWebInf(CmsSystemInfo.FOLDER_PACKAGES);
534        }
535        return m_packagesRfsPath;
536    }
537
538    /**
539     * Returns the absolute path to the "persistence.xml" file (in the "real" file system).<p>
540     *
541     * @return the absolute path to the "persistence.xml" configuration file
542     */
543    public String getPersistenceFileRfsPath() {
544
545        if (m_persistenceFileRfsPath == null) {
546            m_persistenceFileRfsPath = getAbsoluteRfsPathRelativeToWebInf(FILE_PERSISTENCE);
547        }
548        return m_persistenceFileRfsPath;
549    }
550
551    /**
552     * Returns the time this OpenCms instance is running in milliseconds.<p>
553     *
554     * @return the time this OpenCms instance is running in milliseconds
555     */
556    public long getRuntime() {
557
558        return System.currentTimeMillis() - m_startupTime;
559    }
560
561    /**
562     * Returns the OpenCms server name, e.g. "OpenCmsServer".<p>
563     *
564     * The server name is set in <code>opencms.properties</code>.
565     * It is not related to any DNS name the server might also have.
566     * The server name is useful e.g. in a cluster to distinguish different servers,
567     * or if you compare log files from multiple servers.<p>
568     *
569     * @return the OpenCms server name
570     */
571    public String getServerName() {
572
573        return m_serverName;
574    }
575
576    /**
577     * Returns the servlet container specific settings.<p>
578     *
579     * @return the servlet container specific settings
580     */
581    public CmsServletContainerSettings getServletContainerSettings() {
582
583        return m_servletContainerSettings;
584    }
585
586    /**
587     * Returns the OpenCms servlet path, e.g. "/opencms".<p>
588     *
589     * <i>From the Java Servlet Specification v2.4:</i><br>
590     * <b>Servlet Path:</b> The path section that directly corresponds to the mapping
591     * which activated this request. This path starts with a?/? character except in the
592     * case where the request is matched with the ?/*? pattern, in which case it is the
593     * empty string.<p>
594     *
595     * @return the OpenCms servlet path
596     * @see #getContextPath()
597     * @see #getWebApplicationName()
598     * @see #getOpenCmsContext()
599     */
600    public String getServletPath() {
601
602        return m_servletContainerSettings.getServletPath();
603    }
604
605    /**
606     * Returns the time this OpenCms instance was started in milliseconds.<p>
607     *
608     * @return the time this OpenCms instance was started in milliseconds
609     */
610    public long getStartupTime() {
611
612        return m_startupTime;
613    }
614
615    /**
616     * Returns the context for static resources served from the class path, e.g. "/opencms/opencms/handleStatic".<p>
617     *
618     * @return the static resource context
619     */
620    public String getStaticResourceContext() {
621
622        if (m_staticResourcePathFragment == null) {
623            m_staticResourcePathFragment = CmsStaticResourceHandler.getStaticResourceContext(
624                OpenCms.getStaticExportManager().getVfsPrefix(),
625                getVersionNumber());
626        }
627        return m_staticResourcePathFragment;
628    }
629
630    /**
631     * Returns the identifier "OpenCms/" plus the OpenCms version number.<p>
632     *
633     * This information is used for example to identify OpenCms in HTTP response headers.<p>
634     *
635     * @return the identifier "OpenCms/" plus the OpenCms version number
636     */
637    public String getVersion() {
638
639        return m_version;
640    }
641
642    /**
643     * Returns the version ID of this OpenCms system.<p>
644     *
645     * The version ID is usually set dynamically by the build system.
646     * It can be used to identify intermediate builds when the main
647     * version number has not changed.<p>
648     *
649     * @return the version ID of this OpenCms system
650     *
651     * @since 9.5.0
652     */
653    public String getVersionId() {
654
655        return m_versionId;
656    }
657
658    /**
659     * Returns the version number of this OpenCms system, for example <code>9.5.0</code>.<p>
660     *
661     * @return the version number of this OpenCms system
662     *
663     * @since 7.0.2
664     */
665    public String getVersionNumber() {
666
667        return m_versionNumber;
668    }
669
670    /**
671     * Returns the OpenCms web application name, e.g. "opencms" or "ROOT" (no leading or trailing "/").<p>
672     *
673     * The web application name is stored for informational purposes only.
674     * If you want to construct an URI, use either {@link #getContextPath()} and
675     * {@link #getServletPath()}, or for links to the OpenCms VFS use {@link  #getOpenCmsContext()}.<p>
676     *
677     * @return the OpenCms web application name
678     * @see #getContextPath()
679     * @see #getServletPath()
680     * @see #getOpenCmsContext()
681     */
682    public String getWebApplicationName() {
683
684        return m_servletContainerSettings.getWebApplicationName();
685    }
686
687    /**
688     * Returns the OpenCms web application folder in the servlet container.<p>
689     *
690     * @return the OpenCms web application folder in the servlet container
691     */
692    public String getWebApplicationRfsPath() {
693
694        return m_servletContainerSettings.getWebApplicationRfsPath();
695    }
696
697    /**
698     * Returns the OpenCms web application "WEB-INF" directory path.<p>
699     *
700     * @return the OpenCms web application "WEB-INF" directory path
701     */
702    public String getWebInfRfsPath() {
703
704        return m_servletContainerSettings.getWebInfRfsPath();
705    }
706
707    /**
708     * Returns the OpenCms workplace request context, e.g. "/opencms/workplace".<p>
709     *
710     * The OpenCms workplace context will always start with a "/" and never have a trailing "/".
711     * The OpenCms context is identical to <code>getContexPath() + WORKPLACE_PATH</code>.<p>
712     *
713     * @return the OpenCms request context, e.g. "/opencms/workplace"
714     * @see #getContextPath()
715     * @see #WORKPLACE_PATH
716     */
717    public String getWorkplaceContext() {
718
719        return getContextPath() + WORKPLACE_PATH;
720    }
721
722    /**
723     * Returns if the VFS version history is enabled.<p>
724     *
725     * @return if the VFS version history is enabled
726     */
727    public boolean isHistoryEnabled() {
728
729        return m_historyEnabled;
730    }
731
732    /**
733     * Return true if detail contents are restricted to detail pages from the same site.<p>
734     *
735     * @return true if detail contents are restricted to detail pages from the same site
736     */
737    public boolean isRestrictDetailContents() {
738
739        return m_restrictDetailContents;
740    }
741
742    /**
743     * Sets the project in which time stamps for the content notification are read.<p>
744     *
745     * @param notificationProject the project in which time stamps for the content notification are read
746     */
747    public void setNotificationProject(String notificationProject) {
748
749        m_notificationProject = notificationProject;
750    }
751
752    /**
753     * Sets the duration after which responsible resource owners will be notified about out-dated content (in days).<p>
754     *
755     * @param notificationTime the duration after which responsible resource owners will be notified about out-dated content
756     */
757    public void setNotificationTime(int notificationTime) {
758
759        m_notificationTime = notificationTime;
760    }
761
762    /**
763     * VFS version history settings are set here.<p>
764     *
765     * @param historyEnabled if true the history is enabled
766     * @param historyVersions the maximum number of versions that are kept per VFS resource
767     * @param historyVersionsAfterDeletion the maximum number of versions that are kept for deleted resources
768     */
769    public void setVersionHistorySettings(
770        boolean historyEnabled,
771        int historyVersions,
772        int historyVersionsAfterDeletion) {
773
774        m_historyEnabled = historyEnabled;
775        m_historyVersions = historyVersions;
776        if (historyVersionsAfterDeletion < 0) {
777            m_historyVersionsAfterDeletion = historyVersions;
778        } else {
779            m_historyVersionsAfterDeletion = historyVersionsAfterDeletion;
780        }
781    }
782
783    /**
784     * Sets the OpenCms web application "WEB-INF" directory path (in the "real" file system).<p>
785     *
786     * @param settings container specific information needed for this system info
787     */
788    protected void init(CmsServletContainerSettings settings) {
789
790        m_servletContainerSettings = settings;
791    }
792
793    /**
794     * Sets the default encoding, called after the configuration files have been read.<p>
795     *
796     * @param encoding the default encoding to set
797     */
798    protected void setDefaultEncoding(String encoding) {
799
800        m_defaultEncoding = encoding.intern();
801        if (CmsLog.INIT.isInfoEnabled()) {
802            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.LOG_SET_DEFAULT_ENCODING_1, m_defaultEncoding));
803        }
804    }
805
806    /**
807     * Sets the device selector.<p>
808     *
809     * @param selector the device selector to set
810     */
811    protected void setDeviceSelector(I_CmsJspDeviceSelector selector) {
812
813        m_deviceSelector = selector;
814    }
815
816    /**
817     * Sets the HTTP authentication settings.<p>
818     *
819     * @param httpAuthenticationSettings the HTTP authentication settings to set
820     */
821    protected void setHttpAuthenticationSettings(CmsHttpAuthenticationSettings httpAuthenticationSettings) {
822
823        m_httpAuthenticationSettings = httpAuthenticationSettings;
824    }
825
826    /**
827     * Sets the settings for the internal OpenCms email service.<p>
828     *
829     * @param mailSettings the settings for the internal OpenCms email service to set
830     */
831    protected void setMailSettings(CmsMailSettings mailSettings) {
832
833        m_mailSettings = mailSettings;
834    }
835
836    /**
837     * Sets the value of the 'restrict detail contents' option.<p>
838     *
839     * @param restrictDetailContents the new value for the option
840     */
841    protected void setRestrictDetailContents(boolean restrictDetailContents) {
842
843        m_restrictDetailContents = restrictDetailContents;
844    }
845
846    /**
847     * Sets the server name.<p>
848     *
849     * The server name is set in <code>opencms.properties</code>.
850     * It is not related to any DNS name the server might also have.
851     * The server name is useful e.g. in a cluster to distinguish different servers,
852     * or if you compare log files from multiple servers.<p>
853     *
854     * @param serverName the server name to set
855     */
856    protected void setServerName(String serverName) {
857
858        m_serverName = serverName;
859        if (CmsLog.INIT.isInfoEnabled()) {
860            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.LOG_SET_SERVERNAME_1, m_serverName));
861        }
862    }
863
864    /**
865     * Initializes the version for this OpenCms, will be called by
866     * {@link OpenCmsServlet} or {@link CmsShell} upon system startup.<p>
867     */
868    private void initVersion() {
869
870        // initialize version information with static defaults
871        m_versionNumber = DEFAULT_VERSION_NUMBER;
872        m_versionId = DEFAULT_VERSION_ID;
873        m_version = "OpenCms/" + m_versionNumber;
874        m_buildInfo = Collections.emptyMap();
875        // read the version-informations from properties
876        Properties props = new Properties();
877        try {
878            props.load(this.getClass().getClassLoader().getResourceAsStream("org/opencms/main/version.properties"));
879        } catch (Throwable t) {
880            // no properties found - we just use the defaults
881            return;
882        }
883        // initialize OpenCms version information from the property values
884        m_versionNumber = props.getProperty("version.number", DEFAULT_VERSION_NUMBER);
885        m_versionId = props.getProperty("version.id", DEFAULT_VERSION_ID);
886        m_version = "OpenCms/" + m_versionNumber;
887        m_buildInfo = new TreeMap<String, BuildInfoItem>();
888
889        // iterate the properties and generate the build information from the entries
890        for (String key : props.stringPropertyNames()) {
891            if (!"version.number".equals(key) && !"version.id".equals(key) && !key.startsWith("nicename")) {
892                String value = props.getProperty(key);
893                String nicename = props.getProperty("nicename." + key, key);
894                if ("build.date".equals(key) && CmsStringUtil.isEmptyOrWhitespaceOnly(value)) {
895                    try (JarFile jarFile = new JarFile(
896                        new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()))) {
897                        m_buildInfo.put(
898                            key,
899                            new BuildInfoItem(
900                                jarFile.getManifest().getMainAttributes().getValue("Build-Time") + " (manual build)",
901                                nicename,
902                                key));
903                    } catch (Exception e) {
904                        // when running test cases there is no JAR file
905                        m_buildInfo.put(key, new BuildInfoItem("(not set, manual build)", nicename, key));
906                    }
907                } else {
908                    m_buildInfo.put(key, new BuildInfoItem(value, nicename, key));
909                }
910            }
911        }
912        // make the map unmodifiable
913        m_buildInfo = Collections.unmodifiableMap(m_buildInfo);
914    }
915}