View Javadoc
1   /**
2    * This file Copyright (c) 2003-2015 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.cache.setup;
35  
36  import info.magnolia.context.MgnlContext;
37  import info.magnolia.jcr.util.NodeTypes;
38  import info.magnolia.module.DefaultModuleVersionHandler;
39  import info.magnolia.module.InstallContext;
40  import info.magnolia.module.cache.filter.CacheFilter;
41  import info.magnolia.module.delta.AbstractRepositoryTask;
42  import info.magnolia.module.delta.ArrayDelegateTask;
43  import info.magnolia.module.delta.BootstrapSingleResource;
44  import info.magnolia.module.delta.CheckAndModifyPropertyValueTask;
45  import info.magnolia.module.delta.DeltaBuilder;
46  import info.magnolia.module.delta.FilterOrderingTask;
47  import info.magnolia.module.delta.MoveNodeTask;
48  import info.magnolia.module.delta.NodeExistsDelegateTask;
49  import info.magnolia.module.delta.PartialBootstrapTask;
50  import info.magnolia.module.delta.RemoveNodeTask;
51  import info.magnolia.module.delta.RemoveNodeWoChildren;
52  import info.magnolia.module.delta.RemoveNodesTask;
53  import info.magnolia.module.delta.RemovePropertyTask;
54  import info.magnolia.module.delta.RenameNodeTask;
55  import info.magnolia.module.delta.RenamePropertyTask;
56  import info.magnolia.module.delta.Task;
57  import info.magnolia.module.delta.TaskExecutionException;
58  import info.magnolia.repository.RepositoryConstants;
59  import info.magnolia.voting.voters.URIStartsWithVoter;
60  
61  import java.util.ArrayList;
62  import java.util.Arrays;
63  import java.util.List;
64  
65  import javax.jcr.Node;
66  import javax.jcr.RepositoryException;
67  import javax.jcr.Session;
68  
69  /**
70   * <code>VersionHandler</code> implementation for the cache module.
71   */
72  public class CacheModuleVersionHandler extends DefaultModuleVersionHandler {
73  
74      protected static final String OBSOLETE_COMPRESSIBLE_CONFIGURATION_PATH = "modules/cache/config/configurations/default/executors/store/cacheContent/compressible";
75      public static final String CONFIGURATION_PATH = "modules/cache/config/contentCaching/";
76      protected static final String OBSOLETE_DEFAULT_CONFIGURATION_PATH = "/modules/cache/config/configurations/default/";
77  
78      private final FilterOrderingTask placeGzipFilter = new FilterOrderingTask("gzip", new String[]{"context", "multipartRequest"}, new String[]{"activation"});
79      private final FilterOrderingTask placeCacheFilter = new FilterOrderingTask("cache", new String[]{"gzip", "range", "i18n"});
80  
81      private final Task addUidlCachePolicy = new AbstractRepositoryTask("Add uidl cache policy voter", "") {
82          final String path = "/modules/cache/config/configurations/default/cachePolicy/voters/deny";
83  
84          @Override
85          protected void doExecute(InstallContext installContext) throws RepositoryException, TaskExecutionException {
86              Session session = MgnlContext.getJCRSession(RepositoryConstants.CONFIG);
87              if (session.nodeExists(path) && !session.nodeExists(path + "/uidl")) {
88                  Node uidlNode = session.getNode(path).addNode("uidl", NodeTypes.ContentNode.NAME);
89                  uidlNode.setProperty("class", URIStartsWithVoter.class.getName());
90                  uidlNode.setProperty("enabled", "true");
91                  uidlNode.setProperty("level", "2");
92                  uidlNode.setProperty("pattern", "/.magnolia/admincentral/UIDL");
93              }
94          }
95      };
96  
97      public CacheModuleVersionHandler() {
98          register(DeltaBuilder.checkPrecondition("4.4.6", "4.5"));
99  
100         register(DeltaBuilder.update("4.5", "")
101                 .addTask(placeGzipFilter)
102                 .addTask(placeCacheFilter)
103         );
104 
105         register(DeltaBuilder.update("5.1.1", "")
106                 .addTask(new RemovePropertyTask("Remove hardcoded label", "Remove hardcoded label of Cache tools app", RepositoryConstants.CONFIG, "/modules/ui-admincentral/apps/cacheTools", "label"))
107                 .addTask(new RemovePropertyTask("Remove hardcoded icon", "Remove hardcoded icon of Cache tools app", RepositoryConstants.CONFIG, "/modules/ui-admincentral/apps/cacheTools", "icon")));
108 
109         register(DeltaBuilder.update("5.2", "")
110                 .addTask(addUidlCachePolicy)
111         );
112 
113         register(DeltaBuilder.update("5.4", "")
114 
115                 .addTask(new ArrayDelegateTask("Remove deprecated configuration",
116                         new RemoveNodeTask("Remove obsolete compressible configuration.", "/" + OBSOLETE_COMPRESSIBLE_CONFIGURATION_PATH),
117                         new MoveNodeTask("", OBSOLETE_DEFAULT_CONFIGURATION_PATH + "cachePolicy/voters", OBSOLETE_DEFAULT_CONFIGURATION_PATH + "cachePolicy/shouldBypassVoters", false),
118                         new RemoveNodesTask("Remove deprecated cacheable voters",
119                                 RepositoryConstants.CONFIG, Arrays.asList(OBSOLETE_DEFAULT_CONFIGURATION_PATH + "executors/store/cacheContent/isCacheableVoters"), false)
120                 ))
121 
122                 .addTask(new ArrayDelegateTask("Renaming of 'configurations' to 'contentCaching'",
123                         String.format("Renames the 'configurations' nodes of the cache module to 'contentCaching'. Also renames the 'cacheConfigurationName' property of the cache filter to '%s'.", CacheFilter.DEFAULT_CONTENT_CACHING_CONFIGURATION_NAME),
124                         new RenameNodeTask("", RepositoryConstants.CONFIG, "/modules/cache/config", "configurations", "contentCaching", false),
125                         new RenameNodeTask("", RepositoryConstants.CONFIG, "/modules/cache/config/contentCaching", "default", "defaultPageCache", false),
126                         new RenamePropertyTask("", RepositoryConstants.CONFIG, "/server/filters/cache", "cacheConfigurationName", CacheFilter.DEFAULT_CONTENT_CACHING_CONFIGURATION_NAME, false),
127                         new CheckAndModifyPropertyValueTask("", "", RepositoryConstants.CONFIG, "/server/filters/cache", CacheFilter.DEFAULT_CONTENT_CACHING_CONFIGURATION_NAME, "default", "defaultPageCache")
128                 ))
129 
130                 .addTask(new ArrayDelegateTask("Bootstrap new configuration",
131                         new BootstrapSingleResource("Bootstrap voters for TTL", "Bootstrap voters for Time To Live", "/mgnl-bootstrap/cache/config.modules.cache.config.contentCaching.defaultPageCache.cachePolicy.ttlVoters.xml"),
132                         new PartialBootstrapTask("Rebootstrap new default flush cache policy configuration",
133                                 "/mgnl-bootstrap/cache/config.modules.cache.config.contentCaching.defaultPageCache.xml", "defaultPageCache/flushPolicy/policies/flushAll"),
134                         new PartialBootstrapTask("Rebootstrap new uuid-key-mapping flush cache policy configuration",
135                                 "/mgnl-bootstrap/cache/config.modules.cache.config.contentCaching.uuid-key-mapping.xml", "uuid-key-mapping/flushPolicy/policies/flushAll")
136                 ))
137 
138                 .addTask(new NodeExistsDelegateTask("Remove old cache tools app", "/modules/ui-admincentral/apps/cacheTools",
139                         new RemoveNodeTask("", "/modules/ui-admincentral/apps/cacheTools")))
140                 .addTask(new NodeExistsDelegateTask("Remove cache tools page", "/modules/cache/pages/cachePage",
141                         new RemoveNodeTask("", "/modules/cache/pages/cachePage")))
142                 .addTask(new RemoveNodeWoChildren("Remove pages node if there are no pages registered.", "/modules/cache/pages"))
143                 .addTask(new RemoveVirtualUriMappingTask())
144                 .addTask(new CheckAndModifyPropertyValueTask("Browser cache policy for far-future caching", "Fixes pattern for far-future browser cache policy.", RepositoryConstants.CONFIG, "/modules/cache/config/contentCaching/defaultPageCache/browserCachePolicy/policies/farFuture/voters/dotCacheExtension", "pattern", ".*\\.cache\\.[^\\.]*", ".*[~.]cache\\.[^\\.]*"))
145         );
146     }
147 
148     @Override
149     protected List<Task> getExtraInstallTasks(InstallContext installContext) {
150         final List<Task> tasks = new ArrayList<Task>();
151         tasks.add(placeGzipFilter);
152         tasks.add(placeCacheFilter);
153         tasks.add(addUidlCachePolicy);
154         return tasks;
155     }
156 
157     @Override
158     protected List<Task> getStartupTasks(InstallContext installContext) {
159         final List<Task> tasks = new ArrayList<Task>();
160         tasks.addAll(super.getStartupTasks(installContext));
161 
162         tasks.add(new RemoveCacheTempFilesTask());
163         return tasks;
164     }
165 }