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.site;
029
030import org.opencms.file.CmsObject;
031import org.opencms.file.CmsResource;
032import org.opencms.i18n.CmsLocaleManager;
033import org.opencms.i18n.CmsSingleTreeLocaleHandler;
034import org.opencms.main.CmsLog;
035import org.opencms.main.OpenCms;
036import org.opencms.util.CmsPath;
037import org.opencms.util.CmsStringUtil;
038import org.opencms.util.CmsUUID;
039
040import java.io.Serializable;
041import java.util.ArrayList;
042import java.util.List;
043import java.util.Locale;
044import java.util.Map;
045import java.util.Optional;
046import java.util.SortedMap;
047import java.util.TreeMap;
048
049import org.apache.commons.logging.Log;
050
051import com.google.common.collect.Lists;
052import com.google.common.collect.Maps;
053
054/**
055 * Describes a configured site in OpenCms.<p>
056 *
057 * @since 6.0.0
058 */
059public final class CmsSite implements Cloneable, Comparable<CmsSite>, Serializable {
060
061    /**
062     * The site localization modes.<p>
063     */
064    public enum LocalizationMode {
065        /** The multi tree localization mode. */
066        multiTree,
067
068        /** The single tree localization mode. */
069        singleTree,
070
071        /** The default mode. */
072        standard
073    }
074
075    /** The localization mode parameter name. */
076    public static final String PARAM_LOCALIZATION_MODE = "localizationMode";
077
078    /** Parameter name for the main locale. */
079    public static final String PARAM_MAIN_LOCALE = "locale.main";
080
081    /** Parameter name for the secondary locales. */
082    public static final String PARAM_SECONDARY_LOCALES = "locale.secondary";
083
084    /** Log instance. */
085    private static final Log LOG = CmsLog.getLog(CmsSite.class);
086
087    /** The serial version id. */
088    private static final long serialVersionUID = 815429861399510277L;
089    /** The aliases for this site, a vector of CmsSiteMatcher Objects. */
090    private List<CmsSiteMatcher> m_aliases = new ArrayList<CmsSiteMatcher>();
091
092    /** Alternative site root mapping. */
093    private CmsAlternativeSiteRootMapping m_alternativeSiteRootMapping;
094
095    /** The URI to use as error page for this site. */
096    private String m_errorPage;
097
098    /** If exclusive, and set to true will generate a 404 error, if set to false will redirect to secure url. */
099    private boolean m_exclusiveError;
100
101    /** If set to true, secure resources will only be available using the configured secure url. */
102    private boolean m_exclusiveUrl;
103
104    /** True if site is generated. */
105    private boolean m_generated;
106
107    /**Indicates is this site was published once to the online repo. */
108    private boolean m_isOnlineUpdated;
109
110    /** The localization mode. */
111    private LocalizationMode m_localizationMode;
112
113    /** The site parameters. */
114    private SortedMap<String, String> m_parameters;
115
116    /** This value defines a relative sorting order. */
117    private float m_position;
118
119    /** The Url of the secure server. */
120    private CmsSiteMatcher m_secureServer;
121
122    /** The site matcher that describes the site. */
123    private CmsSiteMatcher m_siteMatcher;
124
125    /** Root directory of this site in the OpenCms VFS. */
126    private String m_siteRoot;
127
128    /** UUID of this site's root directory in the OpenCms VFS. */
129    private CmsUUID m_siteRootUUID;
130
131    /** The SSL Mode of the site. */
132    private CmsSSLMode m_sslMode = CmsSSLMode.SECURE_SERVER;
133
134    /** True if subsite selection is enabled for this site. */
135    private boolean m_subsiteSelectionEnabled;
136
137    /** Display title of this site. */
138    private String m_title;
139
140    /** True if permanent redirects should be used when redirecting to the secure URL of this site. */
141    private boolean m_usesPermanentRedirects;
142
143    /** Indicates whether this site should be considered when writing the web server configuration. */
144    private boolean m_webserver = true;
145
146    /** Cached list of configured translation locales, the first locale being the main translation locale. */
147    private transient List<Locale> m_translationLocales;
148
149    /**
150     * Constructs a new site object without title and id information,
151     * this is to be used for lookup purposes only.<p>
152     *
153     * @param siteRoot root directory of this site in the OpenCms VFS
154     * @param siteMatcher the site matcher for this site
155     */
156    public CmsSite(String siteRoot, CmsSiteMatcher siteMatcher) {
157
158        this(siteRoot, CmsUUID.getNullUUID(), siteRoot, siteMatcher, "");
159    }
160
161    /**
162     * Constructs a new site object with a default (wildcard) a site matcher,
163     * this is to be used for display purposes only.<p>
164     *
165     * @param siteRoot root directory of this site in the OpenCms VFS
166     * @param siteRootUUID UUID of this site's root directory in the OpenCms VFS
167     * @param title display name of this site
168     */
169    public CmsSite(String siteRoot, CmsUUID siteRootUUID, String title) {
170
171        this(siteRoot, siteRootUUID, title, CmsSiteMatcher.DEFAULT_MATCHER, "");
172    }
173
174    /**
175     * Constructs a new site object.<p>
176     *
177     * @param siteRoot root directory of this site in the OpenCms VFS
178     * @param siteRootUUID UUID of this site's root directory in the OpenCms VFS
179     * @param title display name of this site
180     * @param siteMatcher the site matcher for this site
181     * @param position the sorting position
182     */
183    public CmsSite(String siteRoot, CmsUUID siteRootUUID, String title, CmsSiteMatcher siteMatcher, String position) {
184
185        setSiteRoot(siteRoot);
186        setSiteRootUUID(siteRootUUID);
187        setTitle(title);
188        setSiteMatcher(siteMatcher);
189        // init the position value
190        m_position = Float.MAX_VALUE;
191        try {
192            if (position != null) {
193                m_position = Float.parseFloat(position);
194            }
195        } catch (Throwable e) {
196            // m_position will have Float.MAX_VALUE, so this site will appear last
197        }
198    }
199
200    /**
201     * Constructs a new site object.<p>
202     *
203     * @param siteRoot root directory of this site in the OpenCms VFS
204     * @param siteRootUUID UUID of this site's root directory in the OpenCms VFS
205     * @param title display name of this site
206     * @param siteMatcher the site matcher for this site
207     * @param position the sorting position
208     * @param errorPage the optional error page for this site
209     * @param secureSite the secure site
210     * @param exclusiveUrl the exclusive flag
211     * @param exclusiveError the exclusive error flag
212     * @param webserver indicates whether to write the web server configuration for this site or not
213     * @param aliases the aliases
214     * @param subsiteSelection enable/disable subsite selection for this site
215     */
216    public CmsSite(
217        String siteRoot,
218        CmsUUID siteRootUUID,
219        String title,
220        CmsSiteMatcher siteMatcher,
221        String position,
222        String errorPage,
223        CmsSiteMatcher secureSite,
224        boolean exclusiveUrl,
225        boolean exclusiveError,
226        boolean webserver,
227        List<CmsSiteMatcher> aliases,
228        boolean subsiteSelection) {
229
230        setSiteRoot(siteRoot);
231        setSiteRootUUID(siteRootUUID);
232        setTitle(title);
233        setSiteMatcher(siteMatcher);
234        // init the position value
235        m_position = Float.MAX_VALUE;
236        try {
237            m_position = Float.parseFloat(position);
238        } catch (Throwable e) {
239            // m_position will have Float.MAX_VALUE, so this site will appear last
240        }
241        setErrorPage(errorPage);
242        setSecureServer(secureSite);
243        setExclusiveUrl(exclusiveUrl);
244        setExclusiveError(exclusiveError);
245        setWebserver(webserver);
246        setAliases(aliases);
247        m_subsiteSelectionEnabled = subsiteSelection;
248    }
249
250    /**
251     * Constructs a new site object without title and id information,
252     * with a site matcher generated from the provided URL.<p>
253     *
254     * This is to be used for test purposes only.<p>
255     *
256     * @param siteRoot root directory of this site in the OpenCms VFS
257     * @param siteURL the URL to create the site matcher for this site from
258     */
259    public CmsSite(String siteRoot, String siteURL) {
260
261        this(siteRoot, new CmsSiteMatcher(siteURL));
262    }
263
264    /**
265     * Returns a clone of this Objects instance.<p>
266     *
267     * @return a clone of this instance
268     */
269    @Override
270    public CmsSite clone() {
271
272        CmsSite res = new CmsSite(
273            getSiteRoot(),
274            (CmsUUID)getSiteRootUUID().clone(),
275            getTitle(),
276            (CmsSiteMatcher)getSiteMatcher().clone(),
277            String.valueOf(getPosition()),
278            getErrorPage(),
279            getSecureServer(),
280            isExclusiveUrl(),
281            isExclusiveError(),
282            isWebserver(),
283            getAliases(),
284            m_subsiteSelectionEnabled);
285        res.setParameters(getParameters());
286        res.setSSLMode(getSSLMode());
287        res.setGenerated(isGenerated());
288        res.setAlternativeSiteRootMapping(getAlternativeSiteRootMapping());
289        return res;
290    }
291
292    /**
293     * @see java.lang.Comparable#compareTo(java.lang.Object)
294     */
295    public int compareTo(CmsSite that) {
296
297        if (that == this) {
298            return 0;
299        }
300        float thatPos = that.getPosition();
301        // please note: can't just subtract and cast to int here because of float precision loss
302        if (m_position == thatPos) {
303            if (m_position == Float.MAX_VALUE) {
304                // if they both do not have any position, sort by title
305                return m_title.compareTo((that).getTitle());
306            }
307            return 0;
308        }
309        return (m_position < thatPos) ? -1 : 1;
310    }
311
312    /**
313     * Creates a generated site for the extension folder configured on this site, or null if no extension folder is set.
314     *
315     * @return the generated site for the extension folder
316     */
317    public CmsSite createAlternativeSiteRootSite() {
318
319        Optional<CmsAlternativeSiteRootMapping> optMapping = getAlternativeSiteRootMapping();
320        if (optMapping.isPresent()) {
321            CmsSite result = clone();
322            CmsAlternativeSiteRootMapping mapping = optMapping.get();
323            result.setSiteRoot(mapping.getSiteRoot().asString());
324            result.setTitle(getTitle() + " [" + mapping.getTitleSuffix() + "]");
325            result.setGenerated(true);
326            return result;
327        }
328        return null;
329    }
330
331    /**
332     * @see java.lang.Object#equals(java.lang.Object)
333     */
334    @Override
335    public boolean equals(Object obj) {
336
337        if (obj == this) {
338            return true;
339        }
340        if (obj instanceof CmsSite) {
341            return (m_siteMatcher != null) && m_siteMatcher.equals(((CmsSite)obj).m_siteMatcher);
342        }
343        return false;
344    }
345
346    /**
347     * Returns the aliases for this site.<p>
348     *
349     * @return a ArrayList with the aliases
350     */
351    public List<CmsSiteMatcher> getAliases() {
352
353        return m_aliases;
354    }
355
356    /**
357     * Gets all site matchers which should be used for matching the site.<p>
358     *
359     * @return all site matchers to be used for matching the site
360     */
361    public List<CmsSiteMatcher> getAllMatchers() {
362
363        List<CmsSiteMatcher> result = Lists.newArrayList();
364        switch (getSSLMode()) {
365            case LETS_ENCRYPT:
366            case MANUAL_EP_TERMINATION:
367                List<CmsSiteMatcher> baseMatchers = Lists.newArrayList();
368                baseMatchers.add(m_siteMatcher);
369                for (CmsSiteMatcher alias : m_aliases) {
370                    baseMatchers.add(alias);
371                }
372                // For each matcher, compute both a https and http variant.
373                // Store them in a map, so we don't get duplicates if the variants have both
374                // been manually defined
375                Map<String, CmsSiteMatcher> matchersByUrl = Maps.newHashMap();
376                for (CmsSiteMatcher matcher : baseMatchers) {
377                    CmsSiteMatcher httpMatcher = matcher.forDifferentScheme("http");
378                    CmsSiteMatcher httpsMatcher = matcher.forDifferentScheme("https");
379                    for (CmsSiteMatcher current : new CmsSiteMatcher[] {httpMatcher, httpsMatcher}) {
380                        matchersByUrl.put(current.getUrl(), current);
381                    }
382                }
383                return Lists.newArrayList(matchersByUrl.values());
384
385            case NO:
386            case SECURE_SERVER:
387            case MANUAL:
388            default:
389                result = Lists.newArrayList();
390                result.add(m_siteMatcher);
391                for (CmsSiteMatcher alias : m_aliases) {
392                    result.add(alias);
393                }
394                if (m_secureServer != null) {
395                    result.add(m_secureServer);
396                }
397                return result;
398
399        }
400
401    }
402
403    /**
404     * Gets the (optional) alternative site root mapping.
405     *
406     * @return the alternative site root mapping
407     */
408    public Optional<CmsAlternativeSiteRootMapping> getAlternativeSiteRootMapping() {
409
410        return m_alternativeSiteRootMapping != null ? Optional.of(m_alternativeSiteRootMapping) : Optional.empty();
411    }
412
413    /**
414     * Returns the errorPage.<p>
415     *
416     * @return the errorPage
417     */
418    public String getErrorPage() {
419
420        return m_errorPage;
421    }
422
423    /**
424     * Returns the localization mode.<p>
425     *
426     * @return the localization mode
427     */
428    public LocalizationMode getLocalizationMode() {
429
430        if (m_localizationMode == null) {
431            try {
432                m_localizationMode = LocalizationMode.valueOf(m_parameters.get(PARAM_LOCALIZATION_MODE));
433            } catch (Exception e) {
434                m_localizationMode = LocalizationMode.standard;
435            }
436        }
437        return m_localizationMode;
438    }
439
440    /**
441     * Gets the main translation locale for this site.<p>
442     *
443     * @param defaultValue the value to return as a default when no main translation locale is set
444     * @return the main translation locale
445     */
446    public Locale getMainTranslationLocale(Locale defaultValue) {
447
448        Map<String, String> params = getParameters();
449        String value = params.get(PARAM_MAIN_LOCALE);
450        if (!CmsStringUtil.isEmpty(value)) {
451            return CmsLocaleManager.getLocale(value);
452        } else {
453            return defaultValue;
454        }
455    }
456
457    /**
458     * Returns the parameters.<p>
459     *
460     * @return the parameters
461     */
462    public SortedMap<String, String> getParameters() {
463
464        return m_parameters;
465    }
466
467    /**
468     * Returns the sorting position.<p>
469     *
470     * @return the sorting position
471     */
472    public float getPosition() {
473
474        return m_position;
475    }
476
477    /**
478     * Gets the list of secondary translation locales.<p>
479     *
480     * @return the list of secondary translation locales
481     */
482    public List<Locale> getSecondaryTranslationLocales() {
483
484        List<Locale> result = Lists.newArrayList();
485        Map<String, String> params = getParameters();
486        String value = params.get(PARAM_SECONDARY_LOCALES);
487        if (!CmsStringUtil.isEmpty(value)) {
488            String[] tokens = value.trim().split(" *, *");
489            for (String token : tokens) {
490                Locale locale = CmsLocaleManager.getLocale(token);
491                if (!result.contains(locale)) {
492                    result.add(locale);
493                }
494            }
495        }
496        return result;
497    }
498
499    /**
500     * Returns the secureServer.<p>
501     *
502     * @return the secureServer
503     */
504    public CmsSiteMatcher getSecureServer() {
505
506        return m_secureServer;
507    }
508
509    /**
510     * Returns the secure server url of this site root.<p>
511     *
512     * @return the secure server url
513     */
514    public String getSecureUrl() {
515
516        if (m_secureServer != null) {
517            return m_secureServer.getUrl();
518        } else {
519            LOG.warn(Messages.get().getBundle().key(Messages.ERR_SECURESERVER_MISSING_1, toString()));
520            return getUrl();
521        }
522    }
523
524    /**
525     * Returns the server prefix for the given resource in this site, used to distinguish between
526     * secure (https) and non-secure (http) sites.<p>
527     *
528     * This is required since a resource may have an individual "secure" setting using the property
529     * {@link org.opencms.file.CmsPropertyDefinition#PROPERTY_SECURE}, which means this resource
530     * must be delivered only using a secure protocol.<p>
531     *
532     * The result will look like <code>http://site.enterprise.com:8080/</code> or <code>https://site.enterprise.com/</code>.<p>
533     *
534     * @param cms the current users OpenCms context
535     * @param resource the resource to use
536     *
537     * @return the server prefix for the given resource in this site
538     *
539     * @see #getServerPrefix(CmsObject, String)
540     */
541    public String getServerPrefix(CmsObject cms, CmsResource resource) {
542
543        return getServerPrefix(cms, resource.getRootPath());
544    }
545
546    /**
547     * Returns the server prefix for the given resource in this site, used to distinguish between
548     * secure (https) and non-secure (http) sites.<p>
549     *
550     * This is required since a resource may have an individual "secure" setting using the property
551     * {@link org.opencms.file.CmsPropertyDefinition#PROPERTY_SECURE}, which means this resource
552     * must be delivered only using a secure protocol.<p>
553     *
554     * The result will look like <code>http://site.enterprise.com:8080/</code> or <code>https://site.enterprise.com/</code>.<p>
555     *
556     * @param cms the current users OpenCms context
557     * @param resourceName the resource name
558     *
559     * @return the server prefix for the given resource in this site
560     *
561     * @see #getSecureUrl()
562     * @see #getUrl()
563     */
564    public String getServerPrefix(CmsObject cms, String resourceName) {
565
566        if (resourceName.startsWith(cms.getRequestContext().getSiteRoot())) {
567            // make sure this can also be used with a resource root path
568            resourceName = resourceName.substring(cms.getRequestContext().getSiteRoot().length());
569        }
570        boolean secure = OpenCms.getStaticExportManager().isSecureLink(
571            cms,
572            resourceName,
573            cms.getRequestContext().isSecureRequest());
574
575        return (secure ? getSecureUrl() : getUrl());
576    }
577
578    /**
579     * Returns the site matcher that describes the URL of this site.<p>
580     *
581     * @return the site matcher that describes the URL of this site
582     */
583    public CmsSiteMatcher getSiteMatcher() {
584
585        return m_siteMatcher;
586    }
587
588    /**
589     * Returns the site path for the given root path in case the root path
590     * actually starts with this site root, or <code>null</code> in case
591     * the root path does not.<p>
592     *
593     * @param rootPath the root path to get the site path for
594     *
595     * @return the site path for the given root path in case the root path
596     *      actually starts with this site root, or <code>null</code> in case
597     *      the root path does not
598     */
599    public String getSitePath(String rootPath) {
600
601        String result = null;
602        if (CmsStringUtil.isNotEmpty(rootPath)) {
603            if (rootPath.startsWith(m_siteRoot)) {
604                result = rootPath.substring(m_siteRoot.length());
605            }
606        }
607        return result;
608    }
609
610    /**
611     * Returns the path of this site's root directory in the OpenCms VFS without tailing slash.<p>
612     * <ul><li><code>e.g. /sites/default</code></li></ul>
613     *
614     * @return the path of this site's root directory in the OpenCms VFS without tailing slash
615     */
616    public String getSiteRoot() {
617
618        return m_siteRoot;
619    }
620
621    /**
622     * Returns the UUID of this site's root directory in the OpenCms VFS.<p>
623     *
624     * @return the UUID of this site's root directory in the OpenCms VFS
625     */
626    public CmsUUID getSiteRootUUID() {
627
628        return m_siteRootUUID;
629    }
630
631    /**
632     * Gets the SSLMode of the site.<p>
633     *
634     * @return CmsSSLMode
635     */
636    public CmsSSLMode getSSLMode() {
637
638        return m_sslMode;
639    }
640
641    /**
642     * Returns the display title of this site.<p>
643     *
644     * @return the display title of this site
645     */
646    public String getTitle() {
647
648        return m_title;
649    }
650
651    /**
652     * Returns all configured translation locales for this site.<p>
653     *
654     * The first entry in the list will be the main translation locale.
655     * If the main translation locale is not correctly configured, an empty list is returned.<p>
656     *
657     * @return all configured translation locales for this site
658     */
659    public List<Locale> getTranslationLocales() {
660
661        if (m_translationLocales == null) {
662            m_translationLocales = new ArrayList<Locale>();
663            Locale main = getMainTranslationLocale(null);
664            if (main != null) {
665                // locales are configured correctly for translation
666                m_translationLocales.add(main);
667                m_translationLocales.addAll(getSecondaryTranslationLocales());
668            }
669        }
670        return m_translationLocales;
671    }
672
673    /**
674     * Returns the server url of this site root.<p>
675     *
676     * @return the server url
677     */
678    public String getUrl() {
679
680        if (m_siteMatcher == null) {
681            return null;
682        }
683        return m_siteMatcher.getUrl();
684    }
685
686    /**
687     * @see java.lang.Object#hashCode()
688     */
689    @Override
690    public int hashCode() {
691
692        return m_siteRootUUID.hashCode();
693    }
694
695    /**
696     * Returns true, if the site has a secure server.<p>
697     *
698     * @return true, if the site has a secure server
699     */
700    public boolean hasSecureServer() {
701
702        return m_secureServer != null;
703    }
704
705    /**
706     * Returns the exclusive error flag.<p>
707     *
708     * @return <code>true</code> will generate a 404 error,
709     *      or <code>false</code> will redirect to secure url.
710     */
711    public boolean isExclusiveError() {
712
713        return m_exclusiveError;
714    }
715
716    /**
717     * Returns the exclusive protocol flag.<p>
718     *
719     * @return <code>true</code> secure resources will only be available using the configured secure url,
720     *      or <code>false</code> if the uri (protocol + servername) does not really matter.
721     */
722    public boolean isExclusiveUrl() {
723
724        return m_exclusiveUrl;
725    }
726
727    /**
728     * Returns true if this is an automatically generated site (and thus should not be used in the site management UI).
729     *
730     * @return true if this is a generated site
731     */
732    public boolean isGenerated() {
733
734        return m_generated;
735    }
736
737    /**
738     * Checks if the site it in the online project.<p>
739     * @return true if it is in online project
740     */
741    public boolean isOnlineUpdated() {
742
743        return m_isOnlineUpdated;
744    }
745
746    /**
747     * Returns a flag indicating if the site is the shared site.
748     *
749     * @return <code>true</code> if the site is the shared site,
750     *      or <code>false</code> if it is not the shared site.
751     */
752    public boolean isSharedSite() {
753
754        return OpenCms.getSiteManager().getSharedFolder().equals(m_siteRoot + "/");
755    }
756
757    /**
758     * Returns true if subsite selection is enabled for this site.
759     *
760     * @return true if subsite selection is enabled for this site
761     */
762    public boolean isSubsiteSelectionEnabled() {
763
764        return m_subsiteSelectionEnabled;
765    }
766
767    /**
768     * Returns the web server.<p>
769     *
770     * @return the web server
771     */
772    public boolean isWebserver() {
773
774        return m_webserver;
775    }
776
777    /**
778     * Returns true if there is an alternative site root mapping configured for this site, and it matches the given path.
779     *
780     * @param path the path from the request
781     * @return true if the alternative site root mapping matches the path
782     */
783    public boolean matchAlternativeSiteRoot(String path) {
784
785        Optional<CmsAlternativeSiteRootMapping> optMapping = getAlternativeSiteRootMapping();
786        if (optMapping.isPresent()) {
787            CmsAlternativeSiteRootMapping extConfig = optMapping.get();
788            if (getLocalizationMode() == LocalizationMode.singleTree) {
789                Locale locale = CmsSingleTreeLocaleHandler.getLocaleFromPath(path);
790                if (locale != null) {
791                    path = path.substring(locale.toString().length() + 1);
792                }
793            }
794            for (CmsPath prefix : extConfig.getPrefixes()) {
795                if (prefix.isPrefixOfStr(path)) {
796                    return true;
797                }
798            }
799        }
800        return false;
801
802    }
803
804    /**
805     * Sets the alternative site root mapping.
806     *
807     * @param alternativeSiteRootMapping the alternative site root mapping
808     */
809    public void setAlternativeSiteRootMapping(Optional<CmsAlternativeSiteRootMapping> alternativeSiteRootMapping) {
810
811        m_alternativeSiteRootMapping = alternativeSiteRootMapping.isPresent() ? alternativeSiteRootMapping.get() : null;
812    }
813
814    /**
815     * Sets the errorPage.<p>
816     *
817     * @param errorPage the errorPage to set
818     */
819    public void setErrorPage(String errorPage) {
820
821        m_errorPage = errorPage;
822    }
823
824    /**
825     * Sets the exclusive error flag.<p>
826     *
827     * @param error the exclusive error flag
828     */
829    public void setExclusiveError(boolean error) {
830
831        m_exclusiveError = error;
832    }
833
834    /**
835     * Sets the exclusive protocol flag.<p>
836     *
837     * @param exclusive the exclusive protocol flag
838     */
839    public void setExclusiveUrl(boolean exclusive) {
840
841        m_exclusiveUrl = exclusive;
842    }
843
844    /**
845     * Sets the online status.
846     *
847     * @param isOnline true -> site has online version
848     */
849    public void sethasOnlineUpdated(boolean isOnline) {
850
851        m_isOnlineUpdated = isOnline;
852
853    }
854
855    /**
856     * Sets the parameters.<p>
857     *
858     * @param parameters the parameters to set
859     */
860    public void setParameters(SortedMap<String, String> parameters) {
861
862        m_parameters = new TreeMap<String, String>(parameters);
863    }
864
865    /**
866     * Sets the server URL prefix to which this site is mapped.<p>
867     *
868     * @param siteRoot the server URL prefix to which this site is mapped
869     */
870    public void setSiteRoot(String siteRoot) {
871
872        // site roots must never end with a "/"
873        siteRoot = siteRoot.trim();
874        if (siteRoot.endsWith("/")) {
875            m_siteRoot = siteRoot.substring(0, siteRoot.length() - 1).trim();
876
877        } else {
878            m_siteRoot = siteRoot.trim();
879        }
880    }
881
882    /**
883     * Sets the SSLMode of the site.<p>
884     *
885     * @param mode the CmsSSLMode
886     */
887    public void setSSLMode(CmsSSLMode mode) {
888
889        m_sslMode = mode;
890    }
891
892    /**
893     * Enables / disables subsite selection for this site.
894     *
895     * @param enabled true if subsite selection should be enabled
896     */
897    public void setSubsiteSelectionEnabled(boolean enabled) {
898
899        m_subsiteSelectionEnabled = enabled;
900
901    }
902
903    /**
904     * Enables use of permanent redirects instead of temporary redirects to the secure site.<p>
905     *
906     * @param usePermanentRedirects true if permanent redirects should be used
907     */
908    public void setUsePermanentRedirects(boolean usePermanentRedirects) {
909
910        m_usesPermanentRedirects = usePermanentRedirects;
911    }
912
913    /**
914     * Sets the web server.<p>
915     *
916     * @param webserver the web server to set
917     */
918    public void setWebserver(boolean webserver) {
919
920        m_webserver = webserver;
921    }
922
923    /**
924     * @see java.lang.Object#toString()
925     */
926    @Override
927    public String toString() {
928
929        StringBuffer result = new StringBuffer(128);
930        result.append("server: ");
931        result.append(m_siteMatcher != null ? m_siteMatcher.toString() : "null");
932        // some extra effort to make debugging easier
933        if (m_siteRoot != null) {
934            result.append(" siteRoot: ");
935            result.append(m_siteRoot);
936        } else {
937            result.append(" (no siteRoot)");
938        }
939        if (m_title != null) {
940            result.append(" title: ");
941            result.append(m_title);
942        } else {
943            result.append(" (no title)");
944        }
945        return result.toString();
946    }
947
948    /**
949     * Returns true if permanent redirects should be used for redirecting to the secure URL for this site.<p>
950     *
951     * @return true if permanent redirects should be used
952     */
953    public boolean usesPermanentRedirects() {
954
955        return m_usesPermanentRedirects;
956    }
957
958    /**
959     * Adds an alias for the site.<p>
960     *
961     * @param aliasServer the sitematcher for the alias
962     */
963    protected void addAlias(CmsSiteMatcher aliasServer) {
964
965        m_aliases.add(aliasServer);
966    }
967
968    /**
969     * Returns the site matcher for the secure site, or null if no secure site is defined.<p>
970     *
971     * @return the site matcher for the secure site
972     */
973    protected CmsSiteMatcher getSecureServerMatcher() {
974
975        return m_secureServer;
976    }
977
978    /**
979     * Sets the aliases for the site.<p>
980     *
981     * @param aliases the aliases for the site
982     */
983    protected void setAliases(List<CmsSiteMatcher> aliases) {
984
985        m_aliases = aliases;
986    }
987
988    /**
989     * Sets the display title of this site.<p>
990     *
991     * @param position the display title of this site
992     */
993    protected void setPosition(float position) {
994
995        m_position = position;
996    }
997
998    /**
999     * Sets the secure server.<p>
1000     *
1001     * @param secureServer the sitematcher of the secure server
1002     */
1003    protected void setSecureServer(CmsSiteMatcher secureServer) {
1004
1005        m_secureServer = secureServer;
1006    }
1007
1008    /**
1009     * Sets the site matcher that describes the URL of this site.<p>
1010     *
1011     * @param siteMatcher the site matcher that describes the URL of this site
1012     */
1013    protected void setSiteMatcher(CmsSiteMatcher siteMatcher) {
1014
1015        m_siteMatcher = siteMatcher;
1016    }
1017
1018    /**
1019     * Sets the UUID of this site's root directory in the OpenCms VFS.<p>
1020     *
1021     * @param siteRootUUID the UUID of this site's root directory in the OpenCms VFS
1022     */
1023    protected void setSiteRootUUID(CmsUUID siteRootUUID) {
1024
1025        m_siteRootUUID = siteRootUUID;
1026    }
1027
1028    /**
1029     * Sets the display title of this site.<p>
1030     *
1031     * @param name the display title of this site
1032     */
1033    protected void setTitle(String name) {
1034
1035        m_title = name;
1036    }
1037
1038    /**
1039     * Enables/disableds the 'generated' state, i.e. if this site is automatically generated.
1040     *
1041     * @param generated true to mark the site as generated
1042     */
1043    void setGenerated(boolean generated) {
1044
1045        m_generated = generated;
1046    }
1047
1048}