1
2
3
4
5
6
7
8
9
10
11 package com.atlassian.jira.upgrade;
12
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Comparator;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23 import java.util.SortedMap;
24 import java.util.SortedSet;
25 import java.util.TreeMap;
26 import java.util.TreeSet;
27
28 import org.apache.commons.lang.exception.ExceptionUtils;
29 import org.apache.log4j.Category;
30 import org.ofbiz.core.entity.GenericEntityException;
31 import org.ofbiz.core.entity.GenericValue;
32
33 import com.atlassian.core.ofbiz.CoreFactory;
34 import com.atlassian.core.util.ClassLoaderUtils;
35 import com.atlassian.jira.ComponentManager;
36 import com.atlassian.jira.ManagerFactory;
37 import com.atlassian.jira.config.properties.ApplicationProperties;
38 import com.atlassian.jira.upgrade.BuildNumComparator;
39 import com.atlassian.jira.upgrade.UpgradeManager;
40 import com.atlassian.jira.upgrade.UpgradeTask;
41 import com.atlassian.jira.util.JiraUtils;
42
43 import electric.xml.Document;
44 import electric.xml.Element;
45 import electric.xml.Elements;
46 import electric.xml.ParseException;
47
48
49
50
51
52
53
54
55
56
57
58 public abstract class AAddOnUpgradeManager implements IAddOnUpgradeManager {
59
60 private static Category log = Category.getInstance(AAddOnUpgradeManager.class);
61 private Comparator buildNumberComp = new BuildNumComparator();
62
63
64 private SortedMap allAddOnUpgrades = new TreeMap(buildNumberComp);
65
66
67 private HashMap upgradeHistoryMap;
68
69
70
71
72
73
74
75
76 protected AAddOnUpgradeManager() {
77 addAllUpgrades(getAllAddOnUpgrades(), getAddOnFileName());
78 }
79
80
81
82 protected AAddOnUpgradeManager(Collection addOnUpgrades) {
83
84 for (Iterator iterator = addOnUpgrades.iterator(); iterator.hasNext();)
85 {
86 UpgradeTask upgradeTask = (UpgradeTask) iterator.next();
87 allAddOnUpgrades.put(upgradeTask.getBuildNumber(), upgradeTask);
88 }
89 }
90
91 public AAddOnUpgradeManager(String addOnFileName)
92 {
93
94 addAllUpgrades(allAddOnUpgrades, addOnFileName);
95
96 }
97
98
99
100
101
102
103
104
105 protected void addAllUpgrades(Map upgradeSet, String fileName)
106 {
107 InputStream is = ClassLoaderUtils.getResourceAsStream(fileName, this.getClass());
108 try
109 {
110 Document doc = new Document(is);
111 Element root = doc.getRoot();
112 Elements actions = root.getElements("upgrade");
113
114 while (actions.hasMoreElements())
115 {
116 Element action = (Element) actions.nextElement();
117 String className = action.getElement("class").getTextString();
118 try
119 {
120 UpgradeTask task = (UpgradeTask) JiraUtils.loadComponent(className, this.getClass());
121
122 upgradeSet.put(action.getAttribute("build"), task);
123
124
125 if ("true".equals(action.getAttribute("setup")))
126 {
127 log.warn("Setup is not supported for AddOn ..." + className);
128 }
129 }
130 catch (Exception e)
131 {
132 log.error("Exception loading type: " + className, e);
133 }
134 }
135 }
136 catch (ParseException e)
137 {
138 log.error("Exception: ", e);
139 }
140
141 try
142 {
143 is.close();
144 }
145 catch (IOException e)
146 {
147 log.warn("Could not close " + fileName + " inputStream");
148 }
149 }
150
151
152
153
154
155
156
157
158
159 private SortedSet getAllRelevantUpgradeBuildNumbers()
160 {
161 SortedSet numbers = new TreeSet(buildNumberComp);
162
163 Map addOnUpgardes = getRelevantUpgradesFromList(allAddOnUpgrades);
164
165 addUpgradeNumbersFromMap(numbers, addOnUpgardes);
166
167 return numbers;
168 }
169
170
171
172
173
174
175
176
177 private void addUpgradeNumbersFromMap(SortedSet numbers, Map upgradeMap)
178 {
179 Collection upgrades = upgradeMap.entrySet();
180
181 for (Iterator iterator = upgrades.iterator(); iterator.hasNext();)
182 {
183 Map.Entry entry = (Map.Entry) iterator.next();
184
185 numbers.add(entry.getKey());
186 }
187 return;
188 }
189
190
191
192
193
194
195
196 public SortedMap getRelevantUpgradesFromList(Map upgradeMap)
197 {
198 try
199 {
200 SortedMap unAppliedUpgrades = new TreeMap(buildNumberComp);
201
202 for (Iterator iterator = upgradeMap.entrySet().iterator(); iterator.hasNext();)
203 {
204 Map.Entry entry = (Map.Entry) iterator.next();
205
206 if (needUpgrade((String) entry.getKey()))
207 {
208 UpgradeTask upgradeTask = (UpgradeTask) entry.getValue();
209 unAppliedUpgrades.put(upgradeTask.getBuildNumber(), upgradeTask);
210 }
211 }
212 return unAppliedUpgrades;
213 }
214 catch (Throwable e)
215 {
216 log.error("Exception getting upgrades " + e.getMessage(), e);
217 return new TreeMap();
218 }
219 }
220
221
222
223 public Collection doUpgradeIfNeeded() {
224 String msg;
225 Collection errors = new ArrayList();
226 if (needUpgrade()) {
227 if (isUpgradable()) {
228 log.info("Detected that an upgrade is needed; existing data at build " + getAddOnBuildNumber());
229 errors = doUpgrade();
230 } else {
231 msg = "Detected that an upgrade is needed, but upgradable due to insufficient Jira Build";
232 log.debug(msg);
233 errors.add(msg);
234 }
235 } else {
236 msg = "Detected that no upgrade is neccessary";
237 log.debug(msg);
238 errors.add(msg);
239 }
240
241 return errors;
242 }
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265 private Collection doUpgrade()
266 {
267 log.info("Doing Upgrade...");
268
269 Collection errors = new ArrayList();
270
271 try
272 {
273 Set upgradeNumbers = getAllRelevantUpgradeBuildNumbers();
274
275
276 Map addOnUpgrades = getRelevantUpgradesFromList(allAddOnUpgrades);
277
278 errors = runUpgradeTasks(upgradeNumbers, addOnUpgrades);
279
280
281 if (errors.isEmpty())
282 {
283
284 log.info("Upgrade succeeded! Setting data build number to " + getCurrentAddOnBuildNumber());
285 setAddOnBuildNumber(getCurrentAddOnBuildNumber());
286 }
287 else
288 {
289 log.error("Errors occurred during upgrade:");
290 printErrors(errors);
291 }
292 }
293 catch (Throwable e)
294 {
295 log.error("Exception thrown during upgrade: " + e.getMessage(), e);
296 errors.add("Exception thrown during upgrade: " + e.getMessage() + "\n" + ExceptionUtils.getStackTrace(e));
297 }
298
299 ManagerFactory.globalRefresh();
300
301
302 return errors;
303 }
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318 private Collection runUpgradeTasks(Collection upgradeNumbers, Map addOnUpgrades) throws Exception
319 {
320 Collection errors = new ArrayList();
321
322
323 Map upgradeHistoryMap = getPreviouslyRunUpgrades();
324
325 for (Iterator iterator = upgradeNumbers.iterator(); iterator.hasNext();)
326 {
327
328 String number = (String) iterator.next();
329
330
331 UpgradeTask addOnUpgradeTask = (UpgradeTask) addOnUpgrades.get(number);
332
333 if (!doUpgradeTaskSucess(upgradeHistoryMap, addOnUpgradeTask, errors))
334 {
335 break;
336 }
337
338
339 if (buildNumberComp.compare(number, getAddOnBuildNumber()) > 0)
340 {
341 log.info("Setting current build number on to " + number);
342 setAddOnBuildNumber(number);
343 }
344
345
346 }
347
348 return errors;
349 }
350
351
352
353
354
355
356
357 private boolean doUpgradeTaskSucess(Map upgradeHistoryMap, UpgradeTask upgradeTask, Collection errors) throws Exception
358 {
359 if (upgradeTask != null)
360 {
361
362 if (upgradeHistoryMap.get(upgradeTask.getClass().getName()) == null)
363 {
364 log.info("Performing Upgrade Task: " + upgradeTask.getShortDescription());
365 upgradeTask.doUpgrade();
366
367 try
368 {
369 addToUpgradeHistory(upgradeTask.getClass());
370 }
371 catch (GenericEntityException e)
372 {
373 errors.add("There was a problem adding Upgrade Task " + upgradeTask.getShortDescription() + " to the Upgrade History");
374 }
375
376 if (!upgradeTask.getErrors().isEmpty())
377 {
378 log.error("Errors during Upgrade Task: " + upgradeTask.getShortDescription());
379 errors.addAll(upgradeTask.getErrors());
380 return false;
381 }
382
383 log.info("Upgrade Task: '" + upgradeTask.getShortDescription() + "' succeeded");
384 }
385 else
386 log.info("Upgrade Task: '" + upgradeTask.getShortDescription() + "' has already been run before");
387 }
388 return true;
389 }
390
391
392 public void addToUpgradeHistory(Class upgradeClass) throws GenericEntityException
393 {
394
395 }
396
397
398
399
400 public SortedMap getAllAddOnUpgrades()
401 {
402 return allAddOnUpgrades;
403 }
404
405
406
407
408
409
410 public boolean isUpgradable()
411 {
412 UpgradeManager manager = (UpgradeManager) ComponentManager.getInstance().getContainer().getComponentInstanceOfType(UpgradeManager.class);
413 return patchBuildGreaterOrEqualThanCurrent(getRequiredJiraBuildNumber(),manager.getJiraBuildNumber());
414 }
415
416
417
418
419
420
421 public boolean needUpgrade()
422 {
423 return !getCurrentAddOnBuildNumber().equals(getAddOnBuildNumber());
424 }
425
426
427
428
429
430
431
432 private boolean needUpgrade(String buildNumber)
433 {
434 return patchBuildGreaterThanCurrent(getAddOnBuildNumber(), buildNumber);
435 }
436
437
438
439
440
441
442
443
444 private boolean patchBuildGreaterThanCurrent(String currentBuild, String patchBuild)
445 {
446 return (buildNumberComp.compare(currentBuild, patchBuild) < 0);
447 }
448
449
450
451
452
453
454
455
456 private boolean patchBuildGreaterOrEqualThanCurrent(String currentBuild, String patchBuild)
457 {
458 return (buildNumberComp.compare(currentBuild, patchBuild) <= 0);
459 }
460
461
462
463
464
465
466
467
468 public String getAddOnBuildNumber()
469 {
470
471
472 if (ManagerFactory.getApplicationProperties().getString(getKeyParameter()) == null)
473 setAddOnBuildNumber("0");
474 return ManagerFactory.getApplicationProperties().getString(getKeyParameter());
475 }
476
477 public void setAddOnBuildNumber(String version)
478 {
479 ApplicationProperties ap = ManagerFactory.getApplicationProperties();
480 ap.setString(getKeyParameter(), version);
481 }
482
483
484 public abstract String getCurrentAddOnBuildNumber();
485
486
487 public abstract String getRequiredJiraBuildNumber();
488
489
490
491
492 private Map getPreviouslyRunUpgrades() throws GenericEntityException
493 {
494
495 if (upgradeHistoryMap == null)
496 {
497 List upgradeHistoryList = CoreFactory.getGenericDelegator().findAll("UpgradeHistory");
498
499 upgradeHistoryMap = new HashMap();
500
501 for (Iterator it = upgradeHistoryList.iterator(); it.hasNext();)
502 {
503 GenericValue upgradeHist = (GenericValue) it.next();
504 upgradeHistoryMap.put(upgradeHist.getString("upgradeclass"), upgradeHist);
505 }
506 }
507 return upgradeHistoryMap;
508 }
509
510
511
512
513
514
515 public void printErrors(Collection errors)
516 {
517 for (Iterator iterator = errors.iterator(); iterator.hasNext();)
518 {
519 String s = (String) iterator.next();
520 log.error("Upgrade Error: " + s);
521 }
522 }
523
524
525 public abstract String getKeyParameter();
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551 }