1 package com.atlassian.sal.core.upgrade;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import org.apache.log4j.Logger;
9 import org.springframework.beans.factory.DisposableBean;
10 import org.springframework.beans.factory.InitializingBean;
11
12 import com.atlassian.plugin.Plugin;
13 import com.atlassian.plugin.PluginAccessor;
14 import com.atlassian.plugin.event.PluginEventListener;
15 import com.atlassian.plugin.event.PluginEventManager;
16 import com.atlassian.plugin.event.events.PluginEnabledEvent;
17 import com.atlassian.sal.api.lifecycle.LifecycleAware;
18 import com.atlassian.sal.api.message.Message;
19 import com.atlassian.sal.api.pluginsettings.PluginSettingsFactory;
20 import com.atlassian.sal.api.transaction.TransactionCallback;
21 import com.atlassian.sal.api.transaction.TransactionTemplate;
22 import com.atlassian.sal.api.upgrade.PluginUpgradeManager;
23 import com.atlassian.sal.api.upgrade.PluginUpgradeTask;
24
25
26
27
28
29
30 public class DefaultPluginUpgradeManager implements PluginUpgradeManager, LifecycleAware, InitializingBean, DisposableBean
31 {
32 private static final Logger log = Logger.getLogger(DefaultPluginUpgradeManager.class);
33
34 private volatile boolean started = false;
35
36 private final List<PluginUpgradeTask> upgradeTasks;
37 private final TransactionTemplate transactionTemplate;
38 private final PluginAccessor pluginAccessor;
39 private final PluginSettingsFactory pluginSettingsFactory;
40 private final PluginEventManager pluginEventManager;
41
42 public DefaultPluginUpgradeManager(final List<PluginUpgradeTask> upgradeTasks, final TransactionTemplate transactionTemplate,
43 final PluginAccessor pluginAccessor, final PluginSettingsFactory pluginSettingsFactory, final PluginEventManager pluginEventManager)
44 {
45 this.upgradeTasks = upgradeTasks;
46 this.transactionTemplate = transactionTemplate;
47 this.pluginAccessor = pluginAccessor;
48 this.pluginSettingsFactory = pluginSettingsFactory;
49 this.pluginEventManager = pluginEventManager;
50 }
51
52
53
54
55
56
57
58
59
60
61
62 @SuppressWarnings("unchecked")
63 @Deprecated
64 public void onBind(final PluginUpgradeTask task, final Map props)
65 {
66
67 log.debug("onbind task = [" + task.getPluginKey() + ", " + task.getBuildNumber() + "] ");
68 }
69
70 public void onStart()
71 {
72 log.debug("onStart");
73 final List<Message> messages = upgrade();
74
75
76
77 if (messages != null)
78 {
79 for(final Message msg : messages)
80 {
81 log.error("Upgrade error: "+msg);
82 }
83 }
84
85 started = true;
86 }
87
88 @PluginEventListener
89 public void onPluginEnabled(PluginEnabledEvent event)
90 {
91
92 if (started)
93 {
94
95 final List<Message> messages = upgradeInTransaction(event.getPlugin());
96 if (messages != null && messages.size() > 0)
97 {
98 log.error("Error(s) encountered while upgrading plugin '" + event.getPlugin().getName() + "' on enable.");
99 for(final Message msg : messages)
100 {
101 log.error("Upgrade error: " + msg);
102 }
103 }
104 }
105
106 }
107
108
109
110
111 protected Map<String, List<PluginUpgradeTask>> getUpgradeTasks()
112 {
113 final Map<String, List<PluginUpgradeTask>> pluginUpgrades = new HashMap<String, List<PluginUpgradeTask>>();
114
115
116 for (final PluginUpgradeTask upgradeTask : upgradeTasks)
117 {
118 List<PluginUpgradeTask> upgrades = pluginUpgrades.get(upgradeTask.getPluginKey());
119 if (upgrades==null)
120 {
121 upgrades=new ArrayList<PluginUpgradeTask>();
122 pluginUpgrades.put(upgradeTask.getPluginKey(), upgrades);
123 }
124 upgrades.add(upgradeTask);
125 }
126
127 return pluginUpgrades;
128 }
129
130
131 @SuppressWarnings("unchecked")
132 public List<Message> upgrade()
133 {
134
135
136 final List<Message> messages = (List<Message>) transactionTemplate.execute(new TransactionCallback()
137 {
138 public Object doInTransaction()
139 {
140 return upgradeInternal();
141 }
142 });
143 return messages;
144 }
145
146 public List<Message> upgradeInternal()
147 {
148 log.info("Running plugin upgrade tasks...");
149
150
151 final Map<String, List<PluginUpgradeTask>> pluginUpgrades = getUpgradeTasks();
152
153
154 final ArrayList<Message> messages = new ArrayList<Message>();
155
156
157 for (final String pluginKey : pluginUpgrades.keySet())
158 {
159 final List<PluginUpgradeTask> upgrades = pluginUpgrades.get(pluginKey);
160
161 final List<Message> upgradeMessages = upgradePlugin(pluginKey, upgrades);
162 if (upgradeMessages != null)
163 {
164 messages.addAll(upgradeMessages);
165 }
166 }
167
168 return messages;
169 }
170
171 private List<Message> upgradeInTransaction(final Plugin plugin)
172 {
173
174 final List<Message> messages = (List<Message>) transactionTemplate.execute(new TransactionCallback()
175 {
176 public Object doInTransaction()
177 {
178 return upgradeInternal(plugin);
179 }
180 });
181 return messages;
182 }
183
184 public List<Message> upgradeInternal(Plugin plugin)
185 {
186 final Map<String, List<PluginUpgradeTask>> pluginUpgrades = getUpgradeTasks();
187 final String pluginKey = plugin.getKey();
188 final List<PluginUpgradeTask> upgrades = pluginUpgrades.get(pluginKey);
189 if (upgrades == null)
190 {
191
192 return null;
193 }
194 return upgradePlugin(pluginKey, upgrades);
195 }
196
197 private List<Message> upgradePlugin(String pluginKey, List<PluginUpgradeTask> upgrades)
198 {
199 final Plugin plugin = pluginAccessor.getPlugin(pluginKey);
200 if (plugin == null)
201 throw new IllegalArgumentException("Invalid plugin key: " + pluginKey);
202
203 final PluginUpgrader pluginUpgrader = new PluginUpgrader(plugin, pluginSettingsFactory.createGlobalSettings(), upgrades);
204 final List<Message> upgradeMessages = pluginUpgrader.upgrade();
205 return upgradeMessages;
206 }
207
208 public void afterPropertiesSet() throws Exception
209 {
210 pluginEventManager.register(this);
211 }
212
213 public void destroy() throws Exception
214 {
215 pluginEventManager.unregister(this);
216 }
217 }