1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.atlassian.theplugin.idea.config.serverconfig;
18
19 import com.atlassian.theplugin.commons.SubscribedPlan;
20 import com.atlassian.theplugin.commons.bamboo.BambooPlan;
21 import com.atlassian.theplugin.commons.bamboo.BambooPlanData;
22 import com.atlassian.theplugin.commons.bamboo.BambooServerFacade;
23 import com.atlassian.theplugin.commons.cfg.BambooServerCfg;
24 import com.atlassian.theplugin.commons.cfg.ServerId;
25 import com.atlassian.theplugin.commons.exception.ServerPasswordNotProvidedException;
26 import com.atlassian.theplugin.commons.remoteapi.RemoteApiException;
27 import com.atlassian.theplugin.commons.util.MiscUtil;
28 import com.atlassian.theplugin.idea.ProgressAnimationProvider;
29 import com.intellij.uiDesigner.core.GridConstraints;
30 import com.intellij.uiDesigner.core.GridLayoutManager;
31
32 import javax.swing.*;
33 import java.awt.*;
34 import java.awt.event.ActionEvent;
35 import java.awt.event.ActionListener;
36 import java.awt.event.KeyAdapter;
37 import java.awt.event.KeyEvent;
38 import java.awt.event.MouseAdapter;
39 import java.awt.event.MouseEvent;
40 import static java.lang.System.arraycopy;
41 import java.util.ArrayList;
42 import java.util.Collection;
43 import java.util.List;
44 import java.util.Map;
45
46
47 public class BambooPlansForm extends JPanel {
48 private JPanel statusPanel;
49 private JPanel toolbarPanel;
50 private JCheckBox cbUseFavouriteBuilds;
51 private JButton btRefresh;
52 private JList list;
53 private JPanel rootComponent;
54 private JEditorPane statusPane;
55 private JScrollPane scrollList;
56 private JPanel listPanel;
57 private ProgressAnimationProvider progressAnimation = new ProgressAnimationProvider();
58
59 private DefaultListModel model;
60
61 private boolean isListModified;
62 private Boolean isUseFavourite = null;
63 private transient BambooServerCfg bambooServerCfg;
64 private static final int NUM_SERVERS = 10;
65 private Map<ServerId, List<BambooPlanItem>> serverPlans = MiscUtil.buildConcurrentHashMap(NUM_SERVERS);
66 private final transient BambooServerFacade bambooServerFacade;
67 private final BambooServerConfigForm serverPanel;
68
69 public BambooPlansForm(BambooServerFacade bambooServerFacade, BambooServerCfg bambooServerCfg,
70 final BambooServerConfigForm bambooServerConfigForm) {
71 this.bambooServerFacade = bambooServerFacade;
72 this.bambooServerCfg = bambooServerCfg;
73 this.serverPanel = bambooServerConfigForm;
74
75 $$$setupUI$$$();
76
77 final GridConstraints constraint = new GridConstraints(0, 0, 1, 1,
78 GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
79 GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
80 GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false);
81
82 progressAnimation.configure(listPanel, scrollList, constraint);
83
84 list.addMouseListener(new MouseAdapter() {
85 @Override
86 public void mousePressed(MouseEvent e) {
87 int index = list.locationToIndex(e.getPoint());
88 setCheckboxState(index);
89 }
90 });
91
92 list.addKeyListener(new KeyAdapter() {
93 @Override
94 public void keyPressed(KeyEvent e) {
95 if (e.getKeyCode() == KeyEvent.VK_SPACE) {
96 int index = list.getSelectedIndex();
97 setCheckboxState(index);
98 }
99 }
100 });
101
102 cbUseFavouriteBuilds.addActionListener(new ActionListener() {
103 public void actionPerformed(ActionEvent e) {
104 setEnabled(!cbUseFavouriteBuilds.isSelected());
105 }
106 });
107
108 btRefresh.addActionListener(new ActionListener() {
109 public void actionPerformed(ActionEvent e) {
110 refreshServerPlans();
111 }
112 });
113 }
114
115 private void refreshServerPlans() {
116 serverPlans.remove(bambooServerCfg.getServerId());
117 serverPanel.saveData();
118 retrievePlans(bambooServerCfg);
119 }
120
121 private void setCheckboxState(int index) {
122 if (index != -1 && isEnabled()) {
123 BambooPlanItem pi = (BambooPlanItem) list.getModel().getElementAt(index);
124 pi.setSelected(!pi.isSelected());
125 setViewState(index, pi.isSelected());
126 repaint();
127
128 setModifiedState();
129 }
130 }
131
132 private void setViewState(int index, boolean newState) {
133 int[] oldIdx = list.getSelectedIndices();
134 int[] newIdx;
135 if (newState) {
136 newIdx = new int[oldIdx.length + 1];
137 arraycopy(newIdx, 0, oldIdx, 0, oldIdx.length);
138 newIdx[newIdx.length - 1] = index;
139 } else {
140 newIdx = new int[Math.max(0, oldIdx.length - 1)];
141 int i = 0;
142 for (int id : oldIdx) {
143 if (id == index) {
144 continue;
145 }
146 newIdx[i++] = id;
147 }
148 }
149 list.setSelectedIndices(newIdx);
150 }
151
152 private void setModifiedState() {
153 isListModified = false;
154 List<BambooPlanItem> local = serverPlans.get(bambooServerCfg.getServerId());
155 if (local != null) {
156 for (int i = 0; i < model.getSize(); i++) {
157 if (local.get(i) != null) {
158 if (((BambooPlanItem) model.getElementAt(i)).isSelected()
159 != local.get(i).isSelected()) {
160 isListModified = true;
161 break;
162 }
163 }
164 }
165 } else {
166 isListModified = !model.isEmpty();
167 }
168 }
169
170 public void setData(final BambooServerCfg serverCfg) {
171 bambooServerCfg = serverCfg;
172 cbUseFavouriteBuilds.setEnabled(false);
173 if (bambooServerCfg.getUrl().length() > 0) {
174 retrievePlans(bambooServerCfg);
175 } else {
176 model.removeAllElements();
177 }
178 }
179
180 private void retrievePlans(final BambooServerCfg queryServer) {
181 list.setEnabled(false);
182 if (isUseFavourite != null) {
183 cbUseFavouriteBuilds.setSelected(isUseFavourite);
184 isUseFavourite = null;
185 } else {
186 cbUseFavouriteBuilds.setSelected(queryServer.isUseFavourites());
187 }
188 model.removeAllElements();
189 statusPane.setText("Waiting for server plans...");
190
191 new Thread(new Runnable() {
192 public void run() {
193 progressAnimation.startProgressAnimation();
194 StringBuilder msg = new StringBuilder();
195 try {
196 ServerId key = queryServer.getServerId();
197 if (!serverPlans.containsKey(key)) {
198 Collection<BambooPlan> plans;
199 try {
200 plans = bambooServerFacade.getPlanList(queryServer);
201 } catch (ServerPasswordNotProvidedException e) {
202 msg.append("Unable to connect: password for server not provided\n");
203 return;
204 } catch (RemoteApiException e) {
205 msg.append("Unable to connect: ");
206 msg.append(e.getMessage());
207 msg.append("\n");
208 return;
209 }
210 List<BambooPlanItem> plansForServer = new ArrayList<BambooPlanItem>();
211 if (plans != null) {
212 for (BambooPlan plan : plans) {
213 plansForServer.add(new BambooPlanItem(plan, false));
214 }
215 msg.append("Build plans updated from server\n");
216 }
217 for (SubscribedPlan sPlan : queryServer.getSubscribedPlans()) {
218 boolean exists = false;
219 for (BambooPlanItem bambooPlanItem : plansForServer) {
220 if (bambooPlanItem.getPlan().getPlanKey().equals(sPlan.getPlanId())) {
221 exists = true;
222 break;
223 }
224 }
225 if (!exists) {
226 BambooPlanData p = new BambooPlanData(sPlan.getPlanId(), sPlan.getPlanId());
227 p.setEnabled(false);
228 p.setFavourite(false);
229 plansForServer.add(new BambooPlanItem(p, true));
230 }
231 }
232 msg.append("Build plans updated based on stored configuration");
233 serverPlans.put(key, plansForServer);
234 } else {
235 msg.append("Build plans updated based on cached values");
236 }
237 } finally {
238 progressAnimation.stopProgressAnimation();
239 final String message = msg.toString();
240 EventQueue.invokeLater(new Runnable() {
241 public void run() {
242 updatePlanNames(queryServer, message);
243 }
244 });
245 }
246
247 }
248 }, "atlassian-idea-plugin bamboo panel retrieve plans").start();
249 }
250
251 private synchronized void updatePlanNames(BambooServerCfg server, String message) {
252 if (server.equals(bambooServerCfg)) {
253 List<BambooPlanItem> plans = serverPlans.get(server.getServerId());
254 if (plans != null) {
255 model.removeAllElements();
256 for (BambooPlanItem plan : plans) {
257 plan.setSelected(false);
258 for (SubscribedPlan sPlan : server.getSubscribedPlans()) {
259 if (sPlan.getPlanId().equals(plan.getPlan().getPlanKey())) {
260 plan.setSelected(true);
261 break;
262 }
263 }
264 model.addElement(new BambooPlanItem(plan.getPlan(), plan.isSelected()));
265 }
266 }
267 statusPane.setText(message);
268 statusPane.setCaretPosition(0);
269 setVisible(true);
270 cbUseFavouriteBuilds.setEnabled(true);
271 list.setEnabled(!cbUseFavouriteBuilds.isSelected());
272 isListModified = false;
273 }
274 }
275
276 public void saveData() {
277 if (bambooServerCfg == null) {
278 return;
279 }
280
281 if (serverPlans.containsKey(bambooServerCfg.getServerId()) == true) {
282 bambooServerCfg.clearSubscribedPlans();
283 for (int i = 0; i < model.getSize(); ++i) {
284 if (model.getElementAt(i) instanceof BambooPlanItem) {
285 BambooPlanItem p = (BambooPlanItem) model.getElementAt(i);
286
287 if (p.isSelected()) {
288 SubscribedPlan spb = new SubscribedPlan(p.getPlan().getPlanKey());
289 bambooServerCfg.getSubscribedPlans().add(spb);
290 }
291 }
292 }
293 }
294 bambooServerCfg.setUseFavourites(cbUseFavouriteBuilds.isSelected());
295 }
296
297 public boolean isModified() {
298 boolean isFavModified = false;
299 if (bambooServerCfg != null) {
300 if (cbUseFavouriteBuilds.isSelected() != bambooServerCfg.isUseFavourites()) {
301 isFavModified = true;
302 }
303 } else {
304 return false;
305 }
306
307 return isListModified || isFavModified;
308 }
309
310 @Override
311 public void setEnabled(boolean enabled) {
312 super.setEnabled(enabled);
313 list.setEnabled(enabled);
314 }
315
316 private void createUIComponents() {
317 model = new DefaultListModel();
318 list = new JList(model);
319 list.setCellRenderer(new PlanListCellRenderer());
320 list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
321 }
322
323
324
325
326
327
328
329
330 private void $$$setupUI$$$() {
331 createUIComponents();
332 rootComponent = new JPanel();
333 rootComponent.setLayout(new GridBagLayout());
334 rootComponent.setBorder(BorderFactory.createTitledBorder("Build Plans"));
335 toolbarPanel = new JPanel();
336 toolbarPanel.setLayout(new GridBagLayout());
337 GridBagConstraints gbc;
338 gbc = new GridBagConstraints();
339 gbc.gridx = 0;
340 gbc.gridy = 0;
341 gbc.weightx = 1.0;
342 gbc.fill = GridBagConstraints.HORIZONTAL;
343 gbc.insets = new Insets(0, 10, 12, 8);
344 rootComponent.add(toolbarPanel, gbc);
345 cbUseFavouriteBuilds = new JCheckBox();
346 cbUseFavouriteBuilds.setText("Use Favourite Builds For Server");
347 cbUseFavouriteBuilds.setMnemonic('F');
348 cbUseFavouriteBuilds.setDisplayedMnemonicIndex(4);
349 gbc = new GridBagConstraints();
350 gbc.gridx = 0;
351 gbc.gridy = 0;
352 gbc.weightx = 1.0;
353 gbc.weighty = 1.0;
354 gbc.anchor = GridBagConstraints.WEST;
355 toolbarPanel.add(cbUseFavouriteBuilds, gbc);
356 btRefresh = new JButton();
357 btRefresh.setText("Refresh");
358 gbc = new GridBagConstraints();
359 gbc.gridx = 2;
360 gbc.gridy = 0;
361 gbc.weighty = 1.0;
362 gbc.fill = GridBagConstraints.HORIZONTAL;
363 toolbarPanel.add(btRefresh, gbc);
364 statusPanel = new JPanel();
365 statusPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
366 gbc = new GridBagConstraints();
367 gbc.gridx = 0;
368 gbc.gridy = 2;
369 gbc.fill = GridBagConstraints.HORIZONTAL;
370 gbc.insets = new Insets(0, 12, 12, 12);
371 rootComponent.add(statusPanel, gbc);
372 final JScrollPane scrollPane1 = new JScrollPane();
373 scrollPane1.setEnabled(true);
374 scrollPane1.setHorizontalScrollBarPolicy(31);
375 scrollPane1.setVerticalScrollBarPolicy(20);
376 statusPanel.add(scrollPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, 1, 1, new Dimension(-1, 40), null, new Dimension(-1, 40), 0, false));
377 statusPane = new JEditorPane();
378 statusPane.setEditable(false);
379 scrollPane1.setViewportView(statusPane);
380 listPanel = new JPanel();
381 listPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
382 listPanel.setBackground(new Color(-1));
383 gbc = new GridBagConstraints();
384 gbc.gridx = 0;
385 gbc.gridy = 1;
386 gbc.weightx = 1.0;
387 gbc.weighty = 1.0;
388 gbc.fill = GridBagConstraints.BOTH;
389 gbc.insets = new Insets(0, 12, 0, 12);
390 rootComponent.add(listPanel, gbc);
391 scrollList = new JScrollPane();
392 scrollList.setBackground(new Color(-1));
393 listPanel.add(scrollList, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
394 scrollList.setViewportView(list);
395 }
396
397
398
399
400 public JComponent $$$getRootComponent$$$() {
401 return rootComponent;
402 }
403 }