1 package com.atlassian.sal.core.upgrade;
2
3 import java.io.PrintWriter;
4 import java.io.StringWriter;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.Collection;
8 import java.util.Collections;
9 import java.util.Comparator;
10 import java.util.List;
11
12 import org.apache.log4j.Logger;
13
14 import com.atlassian.plugin.Plugin;
15 import com.atlassian.sal.api.message.Message;
16 import com.atlassian.sal.api.pluginsettings.PluginSettings;
17 import com.atlassian.sal.api.upgrade.PluginUpgradeTask;
18 import com.atlassian.sal.core.message.DefaultMessage;
19
20
21
22
23 public class PluginUpgrader
24 {
25
26 public static final String BUILD = ":build";
27 protected List<PluginUpgradeTask> upgradeTasks = new ArrayList<PluginUpgradeTask>();
28 private static final Logger log = Logger.getLogger(PluginUpgrader.class);
29 protected Plugin plugin;
30 protected PluginSettings pluginSettings;
31 protected List<Message> errors = new ArrayList<Message>();
32
33 private static final Comparator<PluginUpgradeTask> UPGRADE_TASK_COMPARATOR = new Comparator<PluginUpgradeTask>()
34 {
35 public int compare(final PluginUpgradeTask t1, final PluginUpgradeTask t2)
36 {
37 if (t1 == null)
38 {
39 return -1;
40 }
41 if (t2 == null)
42 {
43 return 1;
44 }
45 if (t1.getBuildNumber() > t2.getBuildNumber())
46 {
47 return 1;
48 }
49
50 return (t1.getBuildNumber() < t2.getBuildNumber()) ? -1 : 0;
51 }
52 };
53
54 protected PluginUpgrader(final Plugin plugin, final PluginSettings pluginSettings, final List<PluginUpgradeTask> upgradeTasks)
55 {
56 this.plugin = plugin;
57 this.pluginSettings = pluginSettings;
58 this.upgradeTasks = upgradeTasks;
59 Collections.sort(this.upgradeTasks, UPGRADE_TASK_COMPARATOR);
60 }
61
62 protected List<Message> upgrade()
63 {
64 if (needUpgrade())
65 {
66 doUpgrade();
67 }
68 return errors;
69 }
70
71 protected void doUpgrade()
72 {
73 try
74 {
75 log.info("Upgrading plugin " + plugin.getKey());
76 for (final PluginUpgradeTask upgradeTask : upgradeTasks)
77 {
78
79 if (upgradeTask.getBuildNumber() <= getDataBuildNumber())
80 {
81
82 continue;
83 }
84
85 final Collection<Message> messages = upgradeTask.doUpgrade();
86
87 if (messages == null || messages.isEmpty())
88 {
89 upgradeTaskSucceeded(upgradeTask);
90 }
91 else
92 {
93 upgradeTaskFailed(upgradeTask, messages);
94 }
95 }
96 }
97 catch (final Throwable e)
98 {
99
100 StringWriter sw = new StringWriter();
101 e.printStackTrace(new PrintWriter(sw));
102
103
104 errors.add(new DefaultMessage("Unexpected exception caught during plugin upgrade: " + sw.toString()));
105 log.error("Upgrade failed: " + e.getMessage(), e);
106 }
107 finally
108 {
109 postUpgrade();
110 }
111 }
112
113
114 protected void upgradeTaskSucceeded(final PluginUpgradeTask upgradeTask)
115 {
116 setDataBuildNumber(upgradeTask.getBuildNumber());
117 log.info("Upgraded plugin " + upgradeTask.getPluginKey() + " to version " + upgradeTask.getBuildNumber() + " - " + upgradeTask.getShortDescription());
118 }
119
120 protected void upgradeTaskFailed(final PluginUpgradeTask upgradeTask, final Collection<Message> messages)
121 {
122 errors.addAll(messages);
123 final StringBuilder msg = new StringBuilder();
124 msg.append("Plugin upgrade failed for ").append(upgradeTask.getPluginKey());
125 msg.append(" to version ").append(upgradeTask.getBuildNumber());
126 msg.append(" - ").append(upgradeTask.getShortDescription());
127 msg.append("\n");
128 for (final Message message : messages)
129 {
130 msg.append("\t* ").append(message.getKey()).append(" ").append(Arrays.toString(message.getArguments()));
131 }
132
133 log.warn(msg.toString());
134 }
135
136 protected List<Message> getErrors()
137 {
138 return errors;
139 }
140
141 protected boolean needUpgrade()
142 {
143 final PluginUpgradeTask lastUpgradeTask = this.upgradeTasks.get(this.upgradeTasks.size()-1);
144 final int dataBuildNumber = getDataBuildNumber();
145 log.info("Plugin: " +plugin.getKey() + ", current version: " + dataBuildNumber + ", highest upgrade task found: " + lastUpgradeTask.getBuildNumber() + ".");
146 return lastUpgradeTask.getBuildNumber() > dataBuildNumber;
147 }
148
149
150
151
152
153 protected int getDataBuildNumber()
154 {
155 final String val = (String) pluginSettings.get(plugin.getKey() + BUILD);
156 if (val != null)
157 {
158 return Integer.parseInt(val);
159 }
160 else
161 {
162 return 0;
163 }
164 }
165
166 protected void setDataBuildNumber(final int buildNumber)
167 {
168 pluginSettings.put(plugin.getKey() + BUILD, String.valueOf(buildNumber));
169 }
170
171 protected void postUpgrade()
172 {
173 log.info("Plugin " + plugin.getKey() + " upgrade completed. Current version is: "+ getDataBuildNumber());
174 }
175 }