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.jcr.util.NodeTypes;
37 import info.magnolia.jcr.util.PropertyUtil;
38 import info.magnolia.module.delta.AbstractRepositoryTask;
39 import info.magnolia.module.delta.Condition;
40 import info.magnolia.module.delta.Delta;
41 import info.magnolia.module.delta.DeltaBuilder;
42 import info.magnolia.module.delta.ModuleFilesExtraction;
43 import info.magnolia.module.delta.Task;
44 import info.magnolia.module.delta.TaskExecutionException;
45 import info.magnolia.module.model.ModuleDefinition;
46 import info.magnolia.module.model.Version;
47 import info.magnolia.module.model.VersionComparator;
48
49 import java.util.ArrayList;
50 import java.util.Collections;
51 import java.util.LinkedList;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.TreeMap;
55
56 import javax.jcr.Node;
57 import javax.jcr.Property;
58 import javax.jcr.RepositoryException;
59 import javax.jcr.Session;
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<>(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 Node moduleNode = ctx.getOrCreateCurrentModuleNode();
106 if (!moduleNode.hasProperty("version")) {
107 return null;
108 }
109
110 final Property versionProp = moduleNode.getProperty("version");
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<>();
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<>(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 protected Delta getInstall(InstallContext installContext) {
176 final List<Task> installTasks = new ArrayList<>();
177 installTasks.addAll(getBasicInstallTasks(installContext));
178 installTasks.addAll(getExtraInstallTasks(installContext));
179 installTasks.add(new ModuleVersionToLatestTask());
180 final List<Condition> conditions = getInstallConditions();
181 final Version version = installContext.getCurrentModuleDefinition().getVersion();
182 return DeltaBuilder.install(version, "").addTasks(installTasks).addConditions(conditions);
183 }
184
185 protected abstract List<Task> getBasicInstallTasks(InstallContext installContext);
186
187
188
189
190
191 protected List<Task> getExtraInstallTasks(InstallContext installContext) {
192 return Collections.emptyList();
193 }
194
195 protected List<Condition> getInstallConditions() {
196 return Collections.emptyList();
197 }
198
199 @Override
200 public Delta getStartupDelta(InstallContext installContext) {
201 final ModuleDefinition moduleDef = installContext.getCurrentModuleDefinition();
202 final List<Task> tasks = getStartupTasks(installContext);
203 return DeltaBuilder.startup(moduleDef, tasks);
204 }
205
206
207
208
209
210 protected List<Task> getStartupTasks(InstallContext installContext) {
211 return Collections.emptyList();
212 }
213
214
215
216
217
218
219 public class ModuleVersionToLatestTask extends AbstractRepositoryTask {
220 protected ModuleVersionToLatestTask() {
221 super("Version number", "Sets installed module version number.");
222 }
223
224 @Override
225 protected void doExecute(InstallContext ctx) throws RepositoryException, TaskExecutionException {
226
227 if (!ctx.hasModulesNode()) {
228 final Session session = ctx.getConfigJCRSession();
229 session.getRootNode().addNode(ModuleManagerImpl.MODULES_NODE, NodeTypes.Content.NAME);
230 }
231
232 final Node moduleNode = ctx.getOrCreateCurrentModuleNode();
233 PropertyUtil.setProperty(moduleNode, "version", getVersion(ctx).toString());
234 }
235
236 protected Version getVersion(InstallContext ctx) {
237 return ctx.getCurrentModuleDefinition().getVersion();
238 }
239 }
240
241
242
243
244 public class ModuleVersionUpdateTask extends ModuleVersionToLatestTask {
245 private final Version toVersion;
246
247 protected ModuleVersionUpdateTask(Version toVersion) {
248 super();
249 this.toVersion = toVersion;
250 }
251
252 @Override
253 protected Version getVersion(InstallContext ctx) {
254 return toVersion;
255 }
256 }
257
258 }