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.lang.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(from)) {
131 final Delta delta = allDeltas.get(v);
132 if (v.isEquivalent(toVersion) && !StringUtils.equals(v.getClassifier(), toVersion.getClassifier())) {
133 delta.getTasks().add(new ModuleVersionUpdateTask(toVersion));
134 }
135 deltas.add(delta);
136 }
137 }
138
139
140 if (toVersion.isStrictlyAfter(from) && !allDeltas.containsKey(toVersion)) {
141 deltas.add(getDefaultUpdate(installContext));
142 }
143 return deltas;
144 }
145
146
147
148
149
150 protected Delta getDefaultUpdate(InstallContext installContext) {
151 final Version toVersion = installContext.getCurrentModuleDefinition().getVersion();
152 final List<Task> defaultUpdateTasks = getDefaultUpdateTasks(toVersion);
153 final List<Condition> defaultUpdateConditions = getDefaultUpdateConditions(toVersion);
154 return DeltaBuilder.update(toVersion, "").addTasks(defaultUpdateTasks).addConditions(defaultUpdateConditions);
155 }
156
157 protected List<Task> getDefaultUpdateTasks(Version forVersion) {
158 final List<Task> defaultUpdates = new ArrayList<Task>(2);
159 defaultUpdates.add(new ModuleFilesExtraction());
160 defaultUpdates.add(new ModuleVersionUpdateTask(forVersion));
161 return defaultUpdates;
162 }
163
164 protected List<Condition> getDefaultUpdateConditions(Version forVersion) {
165 return Collections.emptyList();
166 }
167
168
169
170
171
172
173 protected Delta getInstall(InstallContext installContext) {
174 final List<Task> installTasks = new ArrayList<Task>();
175 installTasks.addAll(getBasicInstallTasks(installContext));
176 installTasks.addAll(getExtraInstallTasks(installContext));
177 installTasks.add(new ModuleVersionToLatestTask());
178 final List<Condition> conditions = getInstallConditions();
179 final Version version = installContext.getCurrentModuleDefinition().getVersion();
180 return DeltaBuilder.install(version, "").addTasks(installTasks).addConditions(conditions);
181 }
182
183 protected abstract List<Task> getBasicInstallTasks(InstallContext installContext);
184
185
186
187
188
189 protected List<Task> getExtraInstallTasks(InstallContext installContext) {
190 return Collections.emptyList();
191 }
192
193 protected List<Condition> getInstallConditions() {
194 return Collections.emptyList();
195 }
196
197 @Override
198 public Delta getStartupDelta(InstallContext installContext) {
199 final ModuleDefinition moduleDef = installContext.getCurrentModuleDefinition();
200 final List<Task> tasks = getStartupTasks(installContext);
201 return DeltaBuilder.startup(moduleDef, tasks);
202 }
203
204
205
206
207
208 protected List<Task> getStartupTasks(InstallContext installContext) {
209 return Collections.emptyList();
210 }
211
212
213
214
215
216
217 public class ModuleVersionToLatestTask extends AbstractRepositoryTask {
218 protected ModuleVersionToLatestTask() {
219 super("Version number", "Sets installed module version number.");
220 }
221
222 @Override
223 protected void doExecute(InstallContext ctx) throws RepositoryException, TaskExecutionException {
224
225 if (!ctx.hasModulesNode()) {
226 final HierarchyManager hm = ctx.getConfigHierarchyManager();
227 hm.createContent("/", ModuleManagerImpl.MODULES_NODE, ItemType.CONTENT.getSystemName());
228 }
229
230 final Content moduleNode = ctx.getOrCreateCurrentModuleNode();
231 final NodeData nodeData = NodeDataUtil.getOrCreate(moduleNode, "version");
232 nodeData.setValue(getVersion(ctx).toString());
233 }
234
235 protected Version getVersion(InstallContext ctx) {
236 return ctx.getCurrentModuleDefinition().getVersion();
237 }
238 }
239
240
241
242
243 public class ModuleVersionUpdateTask extends ModuleVersionToLatestTask {
244 private final Version toVersion;
245
246 protected ModuleVersionUpdateTask(Version toVersion) {
247 super();
248 this.toVersion = toVersion;
249 }
250
251 @Override
252 protected Version getVersion(InstallContext ctx) {
253 return toVersion;
254 }
255 }
256
257 }