All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencms.configuration.CmsSitesConfiguration Maven / Gradle / Ivy

Go to download

OpenCms is an enterprise-ready, easy to use website content management system based on Java and XML technology. Offering a complete set of features, OpenCms helps content managers worldwide to create and maintain beautiful websites fast and efficiently.

There is a newer version: 17.0
Show newest version
/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * For further information about Alkacon Software, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.configuration;

import org.opencms.file.CmsObject;
import org.opencms.letsencrypt.CmsLetsEncryptConfiguration;
import org.opencms.letsencrypt.CmsLetsEncryptConfiguration.Trigger;
import org.opencms.letsencrypt.CmsSiteConfigToLetsEncryptConfigConverter;
import org.opencms.main.CmsLog;
import org.opencms.main.OpenCms;
import org.opencms.report.CmsLogReport;
import org.opencms.site.CmsAlternativeSiteRootMapping;
import org.opencms.site.CmsSSLMode;
import org.opencms.site.CmsSite;
import org.opencms.site.CmsSiteManagerImpl;
import org.opencms.site.CmsSiteMatcher;
import org.opencms.site.CmsSiteMatcher.RedirectMode;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.digester3.CallMethodRule;
import org.apache.commons.digester3.Digester;
import org.apache.commons.digester3.NodeCreateRule;
import org.apache.commons.digester3.ObjectCreateRule;
import org.apache.commons.digester3.Rule;

import org.dom4j.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;

/**
 * Class to read and write the OpenCms site configuration.

*/ public class CmsSitesConfiguration extends A_CmsXmlConfiguration implements I_CmsXmlConfigurationWithUpdateHandler { /** The "error" attribute. */ public static final String A_ERROR = "error"; /** The "errorPage" attribute. */ public static final String A_ERROR_PAGE = "errorPage"; /** The "exclusive" attribute. */ public static final String A_EXCLUSIVE = "exclusive"; /** The attribute name for the alias offset. */ public static final String A_OFFSET = "offset"; /** The "position" attribute. */ public static final String A_POSITION = "position"; /** The "redirect" attribute. */ public static final String A_REDIRECT = "redirect"; /** The "server" attribute. */ public static final String A_SERVER = "server"; /** The ssl mode attribute.*/ public static final String A_SSL = "sslmode"; /** Attribute name for the subsiteSelection option. */ public static final String A_SUBSITE_SELECTION = "subsiteSelection"; /** The "title" attribute. */ public static final String A_TITLE = "title"; /** The "usePermanentRedirects" attribute. */ public static final String A_USE_PERMANENT_REDIRECTS = "usePermanentRedirects"; /** The "webserver" attribute. */ public static final String A_WEBSERVER = "webserver"; /** The name of the DTD for this configuration. */ public static final String CONFIGURATION_DTD_NAME = "opencms-sites.dtd"; /** The name of the default XML file for this configuration. */ public static final String DEFAULT_XML_FILE_NAME = "opencms-sites.xml"; /** The node name for the alias node. */ public static final String N_ALIAS = "alias"; /** The node name for the default-uri node. */ public static final String N_DEFAULT_URI = "default-uri"; /** New secure modes node. */ public static final String N_OLD_STYLE_SECURE_SERVER = "oldStyleSecureServer"; /** The node name for the parameters. */ public static final String N_PARAMETERS = "parameters"; /** The node name for the secure site. */ public static final String N_SECURE = "secure"; /** Shared folder node name. */ public static final String N_SHARED_FOLDER = "shared-folder"; /** The node name for the sites node. */ public static final String N_SITES = "sites"; /** The node name which indicates if apache should be configurable in sitemanager. */ public static final String N_WEBSERVERSCRIPTING = "webserver-scripting"; /** Configuration node name. */ public static final String N_WEBSERVERSCRIPTING_CONFIGTEMPLATE = "configtemplate"; /** Configuration node name. */ public static final String N_WEBSERVERSCRIPTING_FILENAMEPREFIX = "filenameprefix"; /** Configuration node name. */ public static final String N_WEBSERVERSCRIPTING_LOGGINGDIR = "loggingdir"; /** Configuration node name. */ public static final String N_WEBSERVERSCRIPTING_SECURETEMPLATE = "securetemplate"; /** Configuration node name. */ public static final String N_WEBSERVERSCRIPTING_TARGETPATH = "targetpath"; /** Configuration node name. */ public static final String N_WEBSERVERSCRIPTING_WEBSERVERSCRIPT = "webserverscript"; /** The node name for the workplace-server node. */ public static final String N_WORKPLACE_SERVER = "workplace-server"; /** The CmsObject with admin privileges. */ private CmsObject m_adminCms; /** The configured site manager. */ private CmsSiteManagerImpl m_siteManager; /** Future for the LetsEncrypt async update. */ private ScheduledFuture m_updateFuture; /** * @see org.opencms.configuration.I_CmsXmlConfiguration#addXmlDigesterRules(org.apache.commons.digester3.Digester) */ public void addXmlDigesterRules(Digester digester) { // add site configuration rule digester.addObjectCreate("*/" + N_SITES, CmsSiteManagerImpl.class); digester.addCallMethod("*/" + N_SITES + "/" + N_WORKPLACE_SERVER, "addWorkplaceServer", 2); digester.addCallParam("*/" + N_SITES + "/" + N_WORKPLACE_SERVER, 0); digester.addCallParam("*/" + N_SITES + "/" + N_WORKPLACE_SERVER, 1, A_SSL); digester.addCallMethod("*/" + N_SITES + "/" + N_DEFAULT_URI, "setDefaultUri", 0); digester.addCallMethod("*/" + N_SITES + "/" + N_OLD_STYLE_SECURE_SERVER, "setOldStyleSecureServerAllowed", 0); String configApachePath = "*/" + N_SITES + "/" + N_WEBSERVERSCRIPTING; digester.addCallMethod(configApachePath, "setWebServerScripting", 6); digester.addCallParam(configApachePath + "/" + N_WEBSERVERSCRIPTING_WEBSERVERSCRIPT, 0); digester.addCallParam(configApachePath + "/" + N_WEBSERVERSCRIPTING_TARGETPATH, 1); digester.addCallParam(configApachePath + "/" + N_WEBSERVERSCRIPTING_CONFIGTEMPLATE, 2); digester.addCallParam(configApachePath + "/" + N_WEBSERVERSCRIPTING_SECURETEMPLATE, 3); digester.addCallParam(configApachePath + "/" + N_WEBSERVERSCRIPTING_FILENAMEPREFIX, 4); digester.addCallParam(configApachePath + "/" + N_WEBSERVERSCRIPTING_LOGGINGDIR, 5); digester.addSetNext("*/" + N_SITES, "setSiteManager"); // add site configuration rule String siteXpath = "*/" + N_SITES + "/" + N_SITE; digester.addRule( siteXpath, new CallMethodRule( "addSiteInternally", 15, new Class[] { String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, SortedMap.class, List.class, Optional.class}) { @Override public void begin(String namespace, String name, Attributes attributes) throws Exception { super.begin(namespace, name, attributes); getDigester().peekParams()[12] = new TreeMap(); getDigester().peekParams()[13] = new ArrayList(); getDigester().peekParams()[14] = Optional.empty(); // non-string parameters must be initialized to a non-null value, so we have to use Optional } }); digester.addCallParam(siteXpath, 0, A_SERVER); digester.addCallParam(siteXpath, 1, A_URI); digester.addCallParam(siteXpath, 2, A_TITLE); digester.addCallParam(siteXpath, 3, A_POSITION); digester.addCallParam(siteXpath, 4, A_ERROR_PAGE); digester.addCallParam(siteXpath, 5, A_WEBSERVER); digester.addCallParam(siteXpath, 6, A_SSL); digester.addCallParam("*/" + N_SITES + "/" + N_SITE + "/" + N_SECURE, 7, A_SERVER); digester.addCallParam("*/" + N_SITES + "/" + N_SITE + "/" + N_SECURE, 8, A_EXCLUSIVE); digester.addCallParam("*/" + N_SITES + "/" + N_SITE + "/" + N_SECURE, 9, A_ERROR); digester.addCallParam("*/" + N_SITES + "/" + N_SITE + "/" + N_SECURE, 10, A_USE_PERMANENT_REDIRECTS); digester.addCallParam(siteXpath, 11, A_SUBSITE_SELECTION); digester.addRule(siteXpath + "/" + N_PARAMETERS, new ObjectCreateRule(TreeMap.class) { @Override public void end(String namespace, String name) throws Exception { getDigester().peekParams()[12] = getDigester().peek(); super.end(namespace, name); } }); digester.addCallMethod(siteXpath + "/" + N_PARAMETERS + "/" + N_PARAM, "put", 2); digester.addCallParam(siteXpath + "/" + N_PARAMETERS + "/" + N_PARAM, 0, A_NAME); digester.addCallParam(siteXpath + "/" + N_PARAMETERS + "/" + N_PARAM, 1); digester.addRule("*/" + N_SITES + "/" + N_SITE + "/" + N_ALIAS, new Rule() { @Override public void begin(String namespace, String name, Attributes attributes) throws Exception { String server = attributes.getValue(A_SERVER); String redirect = attributes.getValue(A_REDIRECT); String offset = attributes.getValue(A_OFFSET); CmsSiteMatcher matcher = CmsSiteManagerImpl.createAliasSiteMatcher(server, redirect, offset); Object[] params = getDigester().peekParams(); ((ArrayList)params[13]).add(matcher); } }); try { digester.addRule( "*/" + N_SITES + "/" + N_SITE + "/" + CmsAlternativeSiteRootMapping.N_ALTERNATIVE_SITE_ROOT_MAPPING, new NodeCreateRule() { @Override public void end(String namespace, String name) throws Exception { org.w3c.dom.Element elem = (org.w3c.dom.Element)digester.peek(); String uri = elem.getAttribute(I_CmsXmlConfiguration.A_URI); String titlePrefix = elem.getAttribute(CmsAlternativeSiteRootMapping.A_TITLE_SUFFIX); NodeList nodes = elem.getElementsByTagName(CmsAlternativeSiteRootMapping.N_PATH); List paths = new ArrayList<>(); for (int i = 0; i < nodes.getLength(); i++) { org.w3c.dom.Element pathElem = (org.w3c.dom.Element)nodes.item(i); String path = pathElem.getTextContent().trim(); paths.add(path); } CmsAlternativeSiteRootMapping mapping = new CmsAlternativeSiteRootMapping( uri, paths, titlePrefix); getDigester().peekParams()[14] = Optional.of(mapping); super.end(namespace, name); } }); } catch (ParserConfigurationException e) { throw new RuntimeException(e); } digester.addCallMethod("*/" + N_SITES + "/" + N_SHARED_FOLDER, "setSharedFolder", 0); } /** * @see org.opencms.configuration.I_CmsXmlConfiguration#generateXml(org.dom4j.Element) */ public Element generateXml(Element parent) { // create node Element sitesElement = parent.addElement(N_SITES); if (OpenCms.getRunLevel() >= OpenCms.RUNLEVEL_3_SHELL_ACCESS) { m_siteManager = OpenCms.getSiteManager(); } Map workplaceMap = m_siteManager.getWorkplaceServersMap(); for (String server : workplaceMap.keySet()) { Element workplaceElement = sitesElement.addElement(N_WORKPLACE_SERVER).addText(server); workplaceElement.addAttribute(A_SSL, workplaceMap.get(server).getXMLValue()); } sitesElement.addElement(N_DEFAULT_URI).addText(m_siteManager.getDefaultUri()); String sharedFolder = m_siteManager.getSharedFolder(); if (sharedFolder != null) { sitesElement.addElement(N_SHARED_FOLDER).addText(sharedFolder); } String oldStyleSecureAllowed = String.valueOf(m_siteManager.isOldStyleSecureServerAllowed()); sitesElement.addElement(N_OLD_STYLE_SECURE_SERVER).addText(oldStyleSecureAllowed); if (m_siteManager.isConfigurableWebServer()) { Element configServer = sitesElement.addElement(N_WEBSERVERSCRIPTING); Map configServerMap = m_siteManager.getWebServerConfig(); configServer.addElement(N_WEBSERVERSCRIPTING_WEBSERVERSCRIPT).addText( configServerMap.get(CmsSiteManagerImpl.WEB_SERVER_CONFIG_WEBSERVERSCRIPT)); configServer.addElement(N_WEBSERVERSCRIPTING_TARGETPATH).addText( configServerMap.get(CmsSiteManagerImpl.WEB_SERVER_CONFIG_TARGETPATH)); configServer.addElement(N_WEBSERVERSCRIPTING_CONFIGTEMPLATE).addText( configServerMap.get(CmsSiteManagerImpl.WEB_SERVER_CONFIG_CONFIGTEMPLATE)); configServer.addElement(N_WEBSERVERSCRIPTING_SECURETEMPLATE).addText( configServerMap.get(CmsSiteManagerImpl.WEB_SERVER_CONFIG_SECURETEMPLATE)); configServer.addElement(N_WEBSERVERSCRIPTING_FILENAMEPREFIX).addText( configServerMap.get(CmsSiteManagerImpl.WEB_SERVER_CONFIG_FILENAMEPREFIX)); configServer.addElement(N_WEBSERVERSCRIPTING_LOGGINGDIR).addText( configServerMap.get(CmsSiteManagerImpl.WEB_SERVER_CONFIG_LOGGINGDIR)); } Iterator siteIterator = new HashSet(m_siteManager.getSites().values()).iterator(); while (siteIterator.hasNext()) { CmsSite site = siteIterator.next(); // create subnode(s) Element siteElement = sitesElement.addElement(N_SITE); siteElement.addAttribute(A_SERVER, site.getSiteMatcher().toString()); siteElement.addAttribute(A_URI, site.getSiteRoot().concat("/")); siteElement.addAttribute(A_TITLE, site.getTitle()); siteElement.addAttribute(A_POSITION, Float.toString(site.getPosition())); siteElement.addAttribute(A_ERROR_PAGE, site.getErrorPage()); siteElement.addAttribute(A_WEBSERVER, String.valueOf(site.isWebserver())); siteElement.addAttribute(A_SSL, site.getSSLMode().getXMLValue()); siteElement.addAttribute(A_SUBSITE_SELECTION, "" + site.isSubsiteSelectionEnabled()); // create subnode if (site.hasSecureServer()) { Element secureElem = siteElement.addElement(N_SECURE); secureElem.addAttribute(A_SERVER, site.getSecureUrl()); secureElem.addAttribute(A_EXCLUSIVE, String.valueOf(site.isExclusiveUrl())); secureElem.addAttribute(A_ERROR, String.valueOf(site.isExclusiveError())); if (site.usesPermanentRedirects()) { secureElem.addAttribute(A_USE_PERMANENT_REDIRECTS, Boolean.TRUE.toString()); } } if ((site.getParameters() != null) && !site.getParameters().isEmpty()) { Element parametersElem = siteElement.addElement(N_PARAMETERS); for (Map.Entry entry : site.getParameters().entrySet()) { Element paramElem = parametersElem.addElement(N_PARAM); paramElem.addAttribute(A_NAME, entry.getKey()); paramElem.addText(entry.getValue()); } } // create subnode(s) Iterator aliasIterator = site.getAliases().iterator(); while (aliasIterator.hasNext()) { CmsSiteMatcher matcher = aliasIterator.next(); Element aliasElement = siteElement.addElement(N_ALIAS); aliasElement.addAttribute(A_SERVER, matcher.getUrl()); RedirectMode redirectMode = matcher.getRedirectMode(); String redirectModeStr = null; switch (redirectMode) { case permanent: redirectModeStr = "permanent"; break; case temporary: redirectModeStr = "true"; break; case none: default: redirectModeStr = "false"; break; } aliasElement.addAttribute(A_REDIRECT, redirectModeStr); if (matcher.getTimeOffset() != 0) { aliasElement.addAttribute(A_OFFSET, "" + (matcher.getTimeOffset() / 1000)); } } java.util.Optional altSiteRoot = site.getAlternativeSiteRootMapping(); if (altSiteRoot.isPresent()) { altSiteRoot.get().appendXml(siteElement); } } return sitesElement; } /** * @see org.opencms.configuration.I_CmsXmlConfiguration#getDtdFilename() */ public String getDtdFilename() { return CONFIGURATION_DTD_NAME; } /** * Returns the site manager.

* * @return the site manager */ public CmsSiteManagerImpl getSiteManager() { return m_siteManager; } /** * @see org.opencms.configuration.I_CmsXmlConfigurationWithUpdateHandler#handleUpdate() */ public synchronized void handleUpdate() throws Exception { CmsLetsEncryptConfiguration config = OpenCms.getLetsEncryptConfig(); if ((config != null) && config.isValidAndEnabled() && (config.getTrigger() == Trigger.siteConfig)) { // the configuration may be written several times in quick succession. We want to update when this // happens for the last time, not the first, so we use a scheduled task. if (m_updateFuture != null) { m_updateFuture.cancel(false); m_updateFuture = null; } m_updateFuture = OpenCms.getExecutor().schedule(new Runnable() { @SuppressWarnings("synthetic-access") public void run() { m_updateFuture = null; CmsLogReport report = new CmsLogReport( Locale.ENGLISH, org.opencms.letsencrypt.CmsSiteConfigToLetsEncryptConfigConverter.class); CmsSiteConfigToLetsEncryptConfigConverter converter = new CmsSiteConfigToLetsEncryptConfigConverter( config); converter.run(report, OpenCms.getSiteManager()); // TODO Auto-generated method stub } }, 5, TimeUnit.SECONDS); } } /** * @see org.opencms.configuration.I_CmsXmlConfigurationWithUpdateHandler#setCmsObject(org.opencms.file.CmsObject) */ public void setCmsObject(CmsObject cms) { m_adminCms = cms; } /** * Sets the site manager.

* * @param siteManager the site manager to set */ public void setSiteManager(CmsSiteManagerImpl siteManager) { m_siteManager = siteManager; if (CmsLog.INIT.isInfoEnabled()) { CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_SITE_CONFIG_FINISHED_0)); } } /** * @see org.opencms.configuration.A_CmsXmlConfiguration#initMembers() */ @Override protected void initMembers() { setXmlFileName(DEFAULT_XML_FILE_NAME); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy