View Javadoc

1   /**
2    * Copyright (C) 2008 Atlassian
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.atlassian.theplugin.idea.bamboo;
18  
19  import com.atlassian.theplugin.commons.bamboo.*;
20  import com.atlassian.theplugin.commons.exception.ServerPasswordNotProvidedException;
21  import com.atlassian.theplugin.commons.remoteapi.RemoteApiException;
22  import com.atlassian.theplugin.configuration.ProjectConfigurationBean;
23  import com.atlassian.theplugin.configuration.ProjectToolWindowTableConfiguration;
24  import com.atlassian.theplugin.idea.ui.AbstractTableToolWindowPanel;
25  import com.atlassian.theplugin.idea.ui.TableColumnProvider;
26  import com.atlassian.theplugin.idea.util.memoryvfs.PlainTextMemoryVirtualFile;
27  import com.atlassian.theplugin.util.PluginUtil;
28  import com.intellij.ide.BrowserUtil;
29  import com.intellij.openapi.fileEditor.FileEditorManager;
30  import com.intellij.openapi.project.Project;
31  import com.intellij.util.ui.UIUtil;
32  import org.joda.time.format.DateTimeFormat;
33  import org.joda.time.format.DateTimeFormatter;
34  
35  import javax.swing.*;
36  import java.util.ArrayList;
37  import java.util.Collection;
38  import java.util.Date;
39  import java.util.List;
40  
41  public class BambooTableToolWindowPanel extends AbstractTableToolWindowPanel<BambooBuildAdapterIdea>
42  		implements BambooStatusListener {
43      private final transient BambooServerFacade bambooFacade;
44      private static final DateTimeFormatter TIME_DF = DateTimeFormat.forPattern("hh:mm a");
45      private TableColumnProvider columnProvider;    
46  	private final TestResultsToolWindow testResultsToolWindow;
47  	private final BuildChangesToolWindow buildChangesToolWindow;
48  	public static final String BAMBOO_ATLASSIAN_TOOLWINDOW_SERVER_TOOL_BAR = "atlassian.bamboo.toolwindow";
49  
50  	@Override
51      protected String getInitialMessage() {
52          return "Waiting for Bamboo statuses.";
53      }
54  
55      @Override
56      protected String getToolbarActionGroup() {
57          return "ThePlugin.BambooToolWindowToolBar";
58      }
59  
60      @Override
61      protected String getPopupActionGroup() {
62          return "ThePlugin.Bamboo.BuildPopupMenu";
63      }
64  
65      @Override
66      protected TableColumnProvider getTableColumnProvider() {
67          if (columnProvider == null) {
68              columnProvider = new BambooTableColumnProviderImpl();
69          }
70          return columnProvider;
71      }
72  
73      @Override
74      protected ProjectToolWindowTableConfiguration getTableConfiguration() {
75          return projectConfiguration.getBambooConfiguration().getTableConfiguration();
76      }
77  
78      @Override
79      public void applyAdvancedFilter() {
80      }
81  
82      @Override
83      public void cancelAdvancedFilter() {
84      }
85  
86      @Override
87      public void clearAdvancedFilter() {
88      }
89  
90  	@Override
91  	public String getActionPlace() {
92  		return BAMBOO_ATLASSIAN_TOOLWINDOW_SERVER_TOOL_BAR + project.getName();
93  	}
94  
95  	public BambooTableToolWindowPanel(Project project, ProjectConfigurationBean projectConfigurationBean,
96  			final TestResultsToolWindow testResultsToolWindow, final BuildChangesToolWindow buildChangesToolWindow) {
97          super(project, projectConfigurationBean);        
98  		this.testResultsToolWindow = testResultsToolWindow;
99  		this.buildChangesToolWindow = buildChangesToolWindow;
100 		bambooFacade = BambooServerFacadeImpl.getInstance(PluginUtil.getLogger());
101 //		testResultsToolWindow = project.getComponent(TestResultsToolWindow.class);
102 		assert this.testResultsToolWindow != null;
103 //		buildChangesToolWindow = project.getComponent(BuildChangesToolWindow.class);
104 		assert this.buildChangesToolWindow != null;
105 	}
106 
107 
108     @Override
109     protected void handlePopupClick(Object selectedObject) {
110     }
111 
112     @Override
113     protected void handleDoubleClick(Object selectedObject) {
114         BambooBuildAdapter build = (BambooBuildAdapter) selectedObject;
115         if (build != null) {
116             BrowserUtil.launchBrowser(build.getBuildResultUrl());
117         }
118     }
119 
120 
121 //    public static BambooTableToolWindowPanel getInstance(Project project, ProjectConfigurationBean projectConfigurationBean) {
122 //
123 //        BambooTableToolWindowPanel window = project.getUserData(WINDOW_PROJECT_KEY);
124 //
125 //        if (window == null) {
126 //            window = new BambooTableToolWindowPanel(project, projectConfigurationBean);
127 //            project.putUserData(WINDOW_PROJECT_KEY, window);
128 //        }
129 //        return window;
130 //    }
131 
132 
133     private void openLabelDialog(BambooBuildAdapterIdea build) {
134         BuildLabelForm buildLabelForm = new BuildLabelForm(build);
135         buildLabelForm.show();
136         if (buildLabelForm.getExitCode() == 0) {
137             labelBuild(build, buildLabelForm.getLabel());
138         }
139     }
140 
141     private void labelBuild(final BambooBuildAdapterIdea build, final String label) {
142         new Thread(new Runnable() {
143             public void run() {
144                 setStatusMessage("Applying label on build...");
145                 try {
146                     bambooFacade.addLabelToBuild(build.getServer(),
147                             build.getBuildKey(), build.getBuildNumber(), label);
148                     setStatusMessage("Label applied on build");
149                 } catch (ServerPasswordNotProvidedException e) {
150                     setStatusMessage("Label not applied: Password on provided for server");
151                 } catch (RemoteApiException e) {
152                     setStatusMessage("Label not applied: " + e.getMessage());
153                 }
154             }
155         }, "atlassian-idea-plugin label build").start();
156     }
157 
158     public void addLabelToBuild() {
159         BambooBuildAdapterIdea build = table.getSelectedObject();
160         openLabelDialog(build);
161     }
162 
163     private void openCommentDialog(BambooBuildAdapterIdea build) {
164         BuildCommentForm buildCommentForm = new BuildCommentForm(build);
165         buildCommentForm.show();
166         if (buildCommentForm.getExitCode() == 0) {
167             commentBuild(build, buildCommentForm.getCommentText());
168         }
169     }
170 
171     private void commentBuild(final BambooBuildAdapterIdea build, final String commentText) {
172         new Thread(new Runnable() {
173             public void run() {
174                 setStatusMessage("Adding comment label on build...");
175                 try {
176                     bambooFacade.addCommentToBuild(build.getServer(),
177                             build.getBuildKey(), build.getBuildNumber(), commentText);
178                     setStatusMessage("Comment added to build");
179                 } catch (ServerPasswordNotProvidedException e) {
180                     setStatusMessage("Comment not added: Password not provided for server");
181                 } catch (RemoteApiException e) {
182                     setStatusMessage("Comment not added: " + e.getMessage());
183                 }
184 
185             }
186         }, "atlassian-idea-plugin comment build").start();
187     }
188 
189     public void addCommentToBuild() {
190         BambooBuildAdapterIdea build = table.getSelectedObject();
191         openCommentDialog(build);
192     }
193 
194     private void executeBuild(final BambooBuildAdapterIdea build) {
195         new Thread(new Runnable() {
196             public void run() {
197                 setStatusMessage("Executing build on plan " + build.getBuildKey());
198                 try {
199                     bambooFacade.executeBuild(build.getServer(), build.getBuildKey());
200                     setStatusMessage("Build executed on plan: " + build.getBuildKey());
201                 } catch (ServerPasswordNotProvidedException e) {
202                     setStatusMessage("Build not executed: Password not provided for server");
203                 } catch (RemoteApiException e) {
204                     setStatusMessage("Build not executed: " + e.getMessage());
205                 }
206 
207             }
208         }, "atlassian-idea-plugin execute build").start();
209     }
210 
211     public void runBuild() {
212         BambooBuildAdapterIdea build = table.getSelectedObject();
213         executeBuild(build);
214     }
215 
216     private void setBuilds(Collection<BambooBuild> builds) {
217         boolean haveErrors = false;
218         List<BambooBuildAdapterIdea> buildAdapters = new ArrayList<BambooBuildAdapterIdea>();
219         Date lastPollingTime = null;
220         for (BambooBuild build : builds) {
221             if (!haveErrors) {
222                 if (build.getStatus() == BuildStatus.UNKNOWN) {
223                     setStatusMessage(build.getMessage(), true);
224                     haveErrors = true;
225                 }
226             }
227             if (build.getPollingTime() != null) {
228                 lastPollingTime = build.getPollingTime();
229             }
230             buildAdapters.add(new BambooBuildAdapterIdea(build));
231         }
232 
233         // remember selection
234         int selectedItem = table.getSelectedRow();
235 
236         listTableModel.setItems(buildAdapters);
237         listTableModel.fireTableDataChanged();
238         table.setEnabled(true);
239         table.setForeground(UIUtil.getActiveTextColor());
240 
241         // restore selection
242         table.getSelectionModel().setSelectionInterval(selectedItem, selectedItem);
243 
244         if (!haveErrors) {
245             StringBuffer sb = new StringBuffer();
246             sb.append("Loaded <b>");
247             sb.append(builds.size());
248             sb.append("</b> builds");
249             if (lastPollingTime != null) {
250                 sb.append(" at  <b>");
251                 sb.append(TIME_DF.print(lastPollingTime.getTime()));
252                 sb.append("</b>");
253             }
254             sb.append(".");
255             setStatusMessage((sb.toString()));
256         }
257     }
258 
259     @SuppressWarnings("unchecked")
260     public List<BambooBuildAdapterIdea> getBuilds() {
261         return listTableModel.getItems();
262     }
263 
264     public void updateBuildStatuses(Collection<BambooBuild> buildStatuses) {
265         setBuilds(buildStatuses);
266     }
267 
268     public void resetState() {
269         updateBuildStatuses(new ArrayList<BambooBuild>());
270     }
271 
272     public boolean getExecuteBuildEnabled() {
273         BambooBuildAdapterIdea build = table.getSelectedObject();
274         return build != null && build.getEnabled();
275     }
276 
277     private boolean getBamboo2ActionsEnabled() {
278         BambooBuildAdapterIdea build = table.getSelectedObject();
279         if (build != null) {
280             return build.isBamboo2() && build.getEnabled();
281         } else {
282             return false;
283         }
284     }
285 
286     public boolean getLabelBuildEnabled() {
287         return getBamboo2ActionsEnabled();
288     }
289 
290     public boolean getCommentBuildEnabled() {
291         return getBamboo2ActionsEnabled();
292     }
293 
294     public void viewBuild() {
295         BambooBuildAdapterIdea build = table.getSelectedObject();
296         if (build != null) {
297             BrowserUtil.launchBrowser(build.getBuildResultUrl());
298         }
299     }
300 
301     public boolean canShowFailedTests() {
302         BambooBuildAdapterIdea build = table.getSelectedObject();
303         if (build == null) {
304             return false;
305         }
306         return (build.isBamboo2() && (build.getTestsFailed() > 0));
307     }
308 
309     public void showBuildStackTrace() {
310         final BambooBuildAdapterIdea build = table.getSelectedObject();
311 
312         new Thread(new Runnable() {
313             public void run() {
314                 setStatusMessage("Getting test results for build " + build.getBuildKey() + "...");
315                 try {
316                     BuildDetails details = bambooFacade.getBuildDetails(
317                             build.getServer(), build.getBuildKey(), build.getBuildNumber());
318                     final List<TestDetails> failedTests = details.getFailedTestDetails();
319                     final List<TestDetails> succeededTests = details.getSuccessfulTestDetails();
320                     SwingUtilities.invokeLater(new Runnable() {
321                         public void run() {
322                             testResultsToolWindow.showTestResults(
323                                     build.getBuildKey(), build.getBuildNumber(), failedTests, succeededTests);
324                         }
325                     });
326                     setStatusMessage("Test results for build " + build.getBuildKey() + " received");
327                 } catch (ServerPasswordNotProvidedException e) {
328                     setStatusMessage("Failed to get test results: Password not provided for server");
329                 } catch (RemoteApiException e) {
330                     setStatusMessage("Failed to get test results: " + e.getMessage());
331                 }
332 
333             }
334         }, "atlassian-idea-plugin get stack traces").start();
335     }
336 
337     public boolean canShowChanges() {
338         BambooBuildAdapterIdea build = table.getSelectedObject();
339         if (build == null) {
340             return false;
341         }
342         return build.isBamboo2();
343     }
344 
345     public void showChanges() {
346         final BambooBuildAdapterIdea build = table.getSelectedObject();
347 
348         new Thread(new Runnable() {
349             public void run() {
350                 setStatusMessage("Getting changes for build " + build.getBuildKey() + "...");
351                 try {
352                     BuildDetails details = bambooFacade.getBuildDetails(
353                             build.getServer(), build.getBuildKey(), build.getBuildNumber());
354                     final List<BambooChangeSet> commits = details.getCommitInfo();
355                     SwingUtilities.invokeLater(new Runnable() {
356                         public void run() {
357                             buildChangesToolWindow.showBuildChanges(
358                                     build.getBuildKey(), build.getBuildNumber(), commits);
359                         }
360                     });
361                     setStatusMessage("Changes for build " + build.getBuildKey() + " received");
362                 } catch (ServerPasswordNotProvidedException e) {
363                     setStatusMessage("Failed to get changes: Password not provided for server");
364                 } catch (RemoteApiException e) {
365                     setStatusMessage("Failed to get changes: " + e.getMessage());
366                 }
367 
368             }
369         }, "atlassian-idea-plugin get changes").start();
370     }
371 
372 	
373 	public void showBuildLog() {
374         final BambooBuildAdapterIdea build = table.getSelectedObject();
375 
376         new Thread(new Runnable() {
377             public void run() {
378                 setStatusMessage("Getting build log: " + build.getBuildKey() + "...");
379                 try {
380                     final byte[] log = bambooFacade.getBuildLogs(
381                             build.getServer(), build.getBuildKey(), build.getBuildNumber());
382                     final String title = "Bamboo build: "
383                             + build.getServer().getName() + ": "
384                             + build.getBuildKey() + "-" + build.getBuildNumber();
385                     SwingUtilities.invokeLater(new Runnable() {
386                         public void run() {
387                             PlainTextMemoryVirtualFile vf = new PlainTextMemoryVirtualFile(title, new String(log));
388                             FileEditorManager.getInstance(project).openFile(vf, true);
389                         }
390                     });
391                     setStatusMessage("Changes for build " + build.getBuildKey() + " received");
392                 } catch (ServerPasswordNotProvidedException e) {
393                     setStatusMessage("Failed to get changes: Password not provided for server");
394                 } catch (RemoteApiException e) {
395                     setStatusMessage("Failed to get changes: " + e.getMessage());
396                 }
397 
398             }
399         }, "atlassian-idea-plugin get changes").start();
400     }
401 }