1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.module;
35
36 import info.magnolia.cms.core.Content;
37 import info.magnolia.cms.core.HierarchyManager;
38 import info.magnolia.cms.core.ItemType;
39 import info.magnolia.cms.core.NodeData;
40 import info.magnolia.cms.util.NodeDataUtil;
41 import info.magnolia.module.delta.AbstractRepositoryTask;
42 import info.magnolia.module.delta.Condition;
43 import info.magnolia.module.delta.Delta;
44 import info.magnolia.module.delta.DeltaBuilder;
45 import info.magnolia.module.delta.ModuleFilesExtraction;
46 import info.magnolia.module.delta.Task;
47 import info.magnolia.module.delta.TaskExecutionException;
48 import info.magnolia.module.model.ModuleDefinition;
49 import info.magnolia.module.model.Version;
50 import info.magnolia.module.model.VersionComparator;
51
52 import java.util.ArrayList;
53 import java.util.Collections;
54 import java.util.LinkedList;
55 import java.util.List;
56 import java.util.Map;
57 import java.util.TreeMap;
58
59 import javax.jcr.RepositoryException;
60
61 import org.apache.commons.lang3.StringUtils;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65
66
67
68
69
70
71
72 public abstract class AbstractModuleVersionHandler implements ModuleVersionHandler {
73
74 protected Logger log = LoggerFactory.getLogger(getClass());
75
76 private final Map<Version, Delta> allDeltas;
77
78 public AbstractModuleVersionHandler() {
79 allDeltas = new TreeMap<Version, Delta>(new VersionComparator());
80 }
81
82
83
84
85
86 protected void register(Delta delta) {
87 final Version v = delta.getVersion();
88 if (allDeltas.containsKey(v)) {
89 throw new IllegalStateException("Version " + v + " was already registered in this ModuleVersionHandler.");
90 }
91 delta.getTasks().addAll(getDefaultUpdateTasks(v));
92 delta.getConditions().addAll(getDefaultUpdateConditions(v));
93 allDeltas.put(v, delta);
94 }
95
96 @Override
97 public Version getCurrentlyInstalled(InstallContext ctx) {
98 try {
99 log.debug("checking currently installed version of module [{}]", ctx.getCurrentModuleDefinition());
100
101
102 if (!ctx.hasModulesNode()) {
103 return null;
104 }
105 final Content moduleNode = ctx.getOrCreateCurrentModuleNode();
106 final NodeData versionProp = moduleNode.getNodeData("version");
107 if (!versionProp.isExist()) {
108 return null;
109 }
110
111 return Version.parseVersion(versionProp.getString());
112 } catch (RepositoryException e) {
113 throw new RuntimeException(e);
114 }
115 }
116
117 @Override
118 public List<Delta> getDeltas(InstallContext installContext, Version from) {
119 if (from == null) {
120 return Collections.singletonList(getInstall(installContext));
121 }
122
123 return getUpdateDeltas(installContext, from);
124 }
125
126 protected List<Delta> getUpdateDeltas(InstallContext installContext, Version from) {
127 final Version toVersion = installContext.getCurrentModuleDefinition().getVersion();
128 final List<Delta> deltas = new LinkedList<Delta>();
129 for (Version v : allDeltas.keySet()) {
130 if (v.isStrictlyAfter(toVersion)) {
131 throw new IllegalArgumentException("Cannot handle delta for version '" + v.toString() + "' while only installing version '" + toVersion.toString() + "' of module '" + installContext.getCurrentModuleDefinition().getName() + "'.");
132 }
133 if (v.isStrictlyAfter(from)) {
134 final Delta delta = allDeltas.get(v);
135 if (v.isEquivalent(toVersion) && !StringUtils.equals(v.getClassifier(), toVersion.getClassifier())) {
136 delta.getTasks().add(new ModuleVersionUpdateTask(toVersion));
137 }
138 deltas.add(delta);
139 }
140 }
141
142
143 if (toVersion.isStrictlyAfter(from) && !allDeltas.containsKey(toVersion)) {
144 deltas.add(getDefaultUpdate(installContext));
145 }
146 return deltas;
147 }
148
149
150
151
152
153 protected Delta getDefaultUpdate(InstallContext installContext) {
154 final Version toVersion = installContext.getCurrentModuleDefinition().getVersion();
155 final List<Task> defaultUpdateTasks = getDefaultUpdateTasks(toVersion);
156 final List<Condition> defaultUpdateConditions = getDefaultUpdateConditions(toVersion);
157 return DeltaBuilder.update(toVersion, "").addTasks(defaultUpdateTasks).addConditions(defaultUpdateConditions);
158 }
159
160 protected List<Task> getDefaultUpdateTasks(Version forVersion) {
161 final List<Task> defaultUpdates = new ArrayList<Task>(2);
162 defaultUpdates.add(new ModuleFilesExtraction());
163 defaultUpdates.add(new ModuleVersionUpdateTask(forVersion));
164 return defaultUpdates;
165 }
166
167 protected List<Condition> getDefaultUpdateConditions(Version forVersion) {
168 return Collections.emptyList();
169 }
170
171
172
173
174
175
176 protected Delta getInstall(InstallContext installContext) {
177 final List<Task> installTasks = new ArrayList<Task>();
178 installTasks.addAll(getBasicInstallTasks(installContext));
179 installTasks.addAll(getExtraInstallTasks(installContext));
180 installTasks.add(new ModuleVersionToLatestTask());
181 final List<Condition> conditions = getInstallConditions();
182 final Version version = installContext.getCurrentModuleDefinition().getVersion();
183 return DeltaBuilder.install(version, "").addTasks(installTasks).addConditions(conditions);
184 }
185
186 protected abstract List<Task> getBasicInstallTasks(InstallContext installContext);
187
188
189
190
191
192 protected List<Task> getExtraInstallTasks(InstallContext installContext) {
193 return Collections.emptyList();
194 }
195
196 protected List<Condition> getInstallConditions() {
197 return Collections.emptyList();
198 }
199
200 @Override
201 public Delta getStartupDelta(InstallContext installContext) {
202 final ModuleDefinition moduleDef = installContext.getCurrentModuleDefinition();
203 final List<Task> tasks = getStartupTasks(installContext);
204 return DeltaBuilder.startup(moduleDef, tasks);
205 }
206
207
208
209
210
211 protected List<Task> getStartupTasks(InstallContext installContext) {
212 return Collections.emptyList();
213 }
214
215
216
217
218
219
220 public class ModuleVersionToLatestTask extends AbstractRepositoryTask {
221 protected ModuleVersionToLatestTask() {
222 super("Version number", "Sets installed module version number.");
223 }
224
225 @Override
226 protected void doExecute(InstallContext ctx) throws RepositoryException, TaskExecutionException {
227
228 if (!ctx.hasModulesNode()) {
229 final HierarchyManager hm = ctx.getConfigHierarchyManager();
230 hm.createContent("/", ModuleManagerImpl.MODULES_NODE, ItemType.CONTENT.getSystemName());
231 }
232
233 final Content moduleNode = ctx.getOrCreateCurrentModuleNode();
234 final NodeData nodeData = NodeDataUtil.getOrCreate(moduleNode, "version");
235 nodeData.setValue(getVersion(ctx).toString());
236 }
237
238 protected Version getVersion(InstallContext ctx) {
239 return ctx.getCurrentModuleDefinition().getVersion();
240 }
241 }
242
243
244
245
246 public class ModuleVersionUpdateTask extends ModuleVersionToLatestTask {
247 private final Version toVersion;
248
249 protected ModuleVersionUpdateTask(Version toVersion) {
250 super();
251 this.toVersion = toVersion;
252 }
253
254 @Override
255 protected Version getVersion(InstallContext ctx) {
256 return toVersion;
257 }
258 }
259
260 }