/** * This file Copyright (c) 2003-2012 Magnolia International * Ltd. (http://www.magnolia-cms.com). All rights reserved. * * * This file is dual-licensed under both the Magnolia * Network Agreement and the GNU General Public License. * You may elect to use one or the other of these licenses. * * This file is distributed in the hope that it will be * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. * Redistribution, except as permitted by whichever of the GPL * or MNA you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or * modify this file under the terms of the GNU General * Public License, Version 3, as published by the Free Software * Foundation. You should have received a copy of the GNU * General Public License, Version 3 along with this program; * if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * 2. For the Magnolia Network Agreement (MNA), this file * and the accompanying materials are made available under the * terms of the MNA which accompanies this distribution, and * is available at http://www.magnolia-cms.com/mna.html * * Any modifications to this file must keep this entire header * intact. * */ package info.magnolia.setup; import static info.magnolia.nodebuilder.Ops.*; import info.magnolia.cms.filters.FilterManager; import info.magnolia.jcr.util.NodeTypes; import info.magnolia.module.AbstractModuleVersionHandler; import info.magnolia.module.InstallContext; import info.magnolia.module.delta.ArrayDelegateTask; import info.magnolia.module.delta.BootstrapConditionally; import info.magnolia.module.delta.BootstrapSingleModuleResource; import info.magnolia.module.delta.BootstrapSingleResource; import info.magnolia.module.delta.CheckOrCreatePropertyTask; import info.magnolia.module.delta.ChildrenExistsDelegateTask; import info.magnolia.module.delta.Condition; import info.magnolia.module.delta.CreateNodeTask; import info.magnolia.module.delta.DeltaBuilder; import info.magnolia.module.delta.MoveAndRenamePropertyTask; import info.magnolia.module.delta.NodeExistsDelegateTask; import info.magnolia.module.delta.OrderFilterBeforeTask; import info.magnolia.module.delta.OrderNodeBeforeTask; import info.magnolia.module.delta.PropertyExistsDelegateTask; import info.magnolia.module.delta.PropertyValueDelegateTask; import info.magnolia.module.delta.RemoveDuplicatePermissionTask; import info.magnolia.module.delta.RemoveNodeTask; import info.magnolia.module.delta.RenameNodesTask; import info.magnolia.module.delta.Task; import info.magnolia.module.delta.TextFileConditionsUtil; import info.magnolia.module.delta.WebXmlConditionsUtil; import info.magnolia.module.delta.WorkspaceXmlConditionsUtil; import info.magnolia.nodebuilder.task.ErrorHandling; import info.magnolia.nodebuilder.task.NodeBuilderTask; import info.magnolia.repository.RepositoryConstants; import info.magnolia.setup.for4_5.RenameACLNodesTask; import info.magnolia.setup.for4_5.UpdateSecurityFilterClientCallbacksConfiguration; import info.magnolia.setup.for4_5.UpdateUserManagers; import info.magnolia.setup.for5_0.ConvertMetaDataUpdateTask; import info.magnolia.setup.initial.GenericTasks; import java.util.ArrayList; import java.util.List; /** * Special VersionHandler for the core module. As it does not extend {@link info.magnolia.module.DefaultModuleVersionHandler} it has a special getBasicInstallTasks(InstallContext) that * e.g. will not automatically bootstrap xml-files placed in mgnl-bootstrap/core. */ public class CoreModuleVersionHandler extends AbstractModuleVersionHandler { public static final String BOOTSTRAP_AUTHOR_INSTANCE_PROPERTY = "magnolia.bootstrap.authorInstance"; // TODO : why is this a BootstrapConditionally and not a BootstrapSingleResource ? private final BootstrapConditionally auditTrailManagerTask = new BootstrapConditionally("New auditory log configuration", "Install new configuration for auditory log manager.", "/mgnl-bootstrap/core/config.server.auditLogging.xml"); private final BootstrapSingleResource bootstrapFreemarker = new BootstrapSingleResource("Freemarker configuration", "Freemarker template loaders can now be configured in Magnolia. Adds default configuration", "/mgnl-bootstrap/core/config.server.rendering.freemarker.xml"); private final CreateNodeTask addFreemarkerSharedVariables = new CreateNodeTask("Freemarker configuration", "Adds sharedVariables node to the Freemarker configuration", RepositoryConstants.CONFIG, "/server/rendering/freemarker", "sharedVariables", NodeTypes.ContentNode.NAME); private final BootstrapSingleResource bootstrapWebContainerResources = new BootstrapSingleResource("Web container resources configuration", "Global configuration which resources are not meant to be handled by Magnolia. For instance JSP files.", "/mgnl-bootstrap/core/config.server.webContainerResources.xml"); private final BootstrapSingleModuleResource bootstrapChannelManagement = new BootstrapSingleModuleResource("ChannelManagement configuration", "", "config.server.rendering.channelManagement.xml"); private final BootstrapSingleModuleResource bootstrapChannelFilter = new BootstrapSingleModuleResource("ChannelFilter configuration", "", "config.server.filters.channel.xml"); private final Task placeChannelBeforeLogout = new OrderFilterBeforeTask("channel", new String[] {"logout"}); public CoreModuleVersionHandler() { super(); register(DeltaBuilder.update("5.0", "") .addTask(new ConvertMetaDataUpdateTask("", ""))); register(DeltaBuilder.checkPrecondition("4.4.6", "4.5")); register(DeltaBuilder.update("4.5", "") .addCondition(new SystemTmpDirCondition()) .addConditions(get45ConfigFileConditions()) .addTask(new RenameACLNodesTask()) .addTask(new ArrayDelegateTask("New security filter", "Adds the securityCallback filter.", new NodeBuilderTask("New security filter", "Adds the securityCallback filter.", ErrorHandling.strict, RepositoryConstants.CONFIG, FilterManager.SERVER_FILTERS, addNode("securityCallback", NodeTypes.Content.NAME).then( addProperty("class", "info.magnolia.cms.security.SecurityCallbackFilter"), addNode("bypasses", NodeTypes.ContentNode.NAME) ) ), new OrderNodeBeforeTask("", "Puts the securityCallback just before the uriSecurity filter.", RepositoryConstants.CONFIG, FilterManager.SERVER_FILTERS + "/securityCallback", "uriSecurity") )) .addTask(new UpdateSecurityFilterClientCallbacksConfiguration("uriSecurity", "securityCallback")) .addTask(new UpdateUserManagers()) .addTask(new HashUsersPasswords()) .addTask(bootstrapChannelManagement) .addTask(bootstrapChannelFilter) .addTask(placeChannelBeforeLogout) .addTask(new RemoveDuplicatePermissionTask("Remove duplicate permission", "Remove duplicate permission in workspace Expression for role superuser", "superuser", "acl_Expressions")) .addTask(new RemoveDuplicatePermissionTask("Remove duplicate permission", "Remove duplicate permission in workspace Store for role superuser", "superuser", "acl_Store")) .addTask(new RemoveDuplicatePermissionTask("Remove duplicate permission", "Remove duplicate permission in workspace forum for role superuser", "superuser", "acl_forum")) .addTask(new CheckOrCreatePropertyTask("Update system userManager ", "Add the realName property.", RepositoryConstants.CONFIG, "/server/security/userManagers/system", "realName", "system")) .addTask(new CheckOrCreatePropertyTask("Update system userManager ", "Add the realName property.", RepositoryConstants.CONFIG, "/server/security/userManagers/admin", "realName", "admin")) .addTask(new RenameNodesTask("Update servlet mapping names", "Update '--resources--' servlet mapping names to use '.'.", RepositoryConstants.CONFIG, "/server/filters/servlets", "--resources--", "-.resources--", NodeTypes.ContentNode.NAME)) .addTask(new ChildrenExistsDelegateTask("name", "description", RepositoryConstants.CONFIG, "/server/filters/securityCallback/bypasses", NodeTypes.ContentNode.NAME, null, new RemoveNodeTask("Update securityCallback", "Remove empty bypasses node from securityCallback.", RepositoryConstants.CONFIG, "/server/filters/securityCallback/bypasses"))) .addTask(new PropertyValueDelegateTask("Remove urlPattern", "Remove urlPattern from 'magnolia' clientCallback if previously set to '*'", RepositoryConstants.CONFIG, "/server/filters/securityCallback/clientCallbacks/magnolia/urlPattern", "patternString", "*", true, new RemoveNodeTask("Update form clientCallback", "Remove 'urlPattern' from new 'magnolia' clientCallback", RepositoryConstants.CONFIG, "/server/filters/securityCallback/clientCallbacks/magnolia/urlPattern"))) .addTask(new RenameNodesTask("Rename clientCallback", "Rename 'magnolia' clientCallback to 'form'.", RepositoryConstants.CONFIG, "/server/filters/securityCallback/clientCallbacks", "magnolia", "form", NodeTypes.ContentNode.NAME)) .addTask(new NodeExistsDelegateTask("Server node", "Update uriSecurity if needed.", RepositoryConstants.CONFIG, "/server/filters/securityCallback/public", new OrderNodeBeforeTask("Order clientCallbacks", "Order 'form' clientCallback before 'public'.", RepositoryConstants.CONFIG, "/server/filters/securityCallback/clientCallbacks/form", "public"),null)) .addTask(new RemoveNodeTask("Update contentSecurity", "Remove clientCallback from cms/contentSecurity as they're now under 'securityCallback'.", RepositoryConstants.CONFIG, "/server/filters/cms/contentSecurity/clientCallback")) .addTask(new OrderNodeBeforeTask("Order i18n", "Put i18n subnodes in proper order.", RepositoryConstants.CONFIG, "/server/i18n/content", "system")) ); register(DeltaBuilder.update("4.5.2", "") .addTask(new PropertyExistsDelegateTask("Fix property name", "", RepositoryConstants.CONFIG, "/server/security/userManagers/system", "realName", new MoveAndRenamePropertyTask("Fix propertyName", "/server/security/userManagers/system", "realName", "/server/security/userManagers/system", "realmName"))) .addTask(new PropertyExistsDelegateTask("Fix property name", "", RepositoryConstants.CONFIG, "/server/security/userManagers/admin", "realName", new MoveAndRenamePropertyTask("Fix propertyName", "/server/security/userManagers/admin", "realName", "/server/security/userManagers/admin", "realmName"))) ); } @Override protected List<Task> getBasicInstallTasks(InstallContext ctx) { final List<Task> tasks = new ArrayList<Task>(); tasks.addAll(GenericTasks.genericTasksForNewInstallation()); tasks.add(auditTrailManagerTask); tasks.add(bootstrapFreemarker); tasks.add(addFreemarkerSharedVariables); tasks.add(bootstrapWebContainerResources); tasks.add(new BootstrapConditionally("Security", "Bootstraps security-base role.", "/mgnl-bootstrap/core/userroles.security-base.xml")); // always hash passwords. Task will not re-hash so it is safe to run this op at any time, multiple times. tasks.add(new HashUsersPasswords()); tasks.add(bootstrapChannelManagement); tasks.add(bootstrapChannelFilter); tasks.add(placeChannelBeforeLogout); return tasks; } @Override protected List<Condition> getInstallConditions() { final ArrayList<Condition> conditions = new ArrayList<Condition>(); final WebXmlConditionsUtil u = new WebXmlConditionsUtil(conditions); u.servletIsNowWrapped("ActivationHandler"); u.servletIsNowWrapped("AdminTreeServlet"); u.servletIsNowWrapped("classpathspool"); u.servletIsNowWrapped("DialogServlet"); u.servletIsNowWrapped("PageServlet"); u.servletIsNowWrapped("log4j"); u.servletIsNowWrapped("FCKEditorSimpleUploadServlet"); u.servletIsDeprecated("uuidRequestDispatcher"); u.filterIsDeprecated("info.magnolia.cms.filters.MagnoliaManagedFilter", "info.magnolia.cms.filters.MgnlMainFilter"); u.filterMustBeRegisteredWithCorrectDispatchers("info.magnolia.cms.filters.MgnlMainFilter"); u.listenerIsDeprecated("info.magnolia.cms.servlets.PropertyInitializer", "info.magnolia.cms.servlets.MgnlServletContextListener"); u.listenerIsDeprecated("info.magnolia.cms.beans.config.ShutdownManager", "info.magnolia.cms.servlets.MgnlServletContextListener"); final WorkspaceXmlConditionsUtil u2 = new WorkspaceXmlConditionsUtil(conditions); u2.textFilterClassesAreNotSet(); conditions.add(new SystemTmpDirCondition()); return conditions; } private List<Condition> get45ConfigFileConditions() { List<Condition> conditions = new ArrayList<Condition>(); final TextFileConditionsUtil u = new TextFileConditionsUtil(conditions); u.addFalseConditionIfExpressionIsContained(System.getProperty("java.security.auth.login.config"), "^Jackrabbit.*"); final WorkspaceXmlConditionsUtil u2 = new WorkspaceXmlConditionsUtil(conditions); u2.textFilterClassesAreNotSet(); u2.paramAnalyzerIsNotSet(); u2.accessControlProviderIsSet(); return conditions; } }