Java tutorial
/******************************************************************************* * Copyright (c) 2013 Cloud Bees, Inc. * All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Cloud Bees, Inc. - initial API and implementation *******************************************************************************/ package com.cloudbees.eclipse.dev.ui.views.build; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.CellLabelProvider; import org.eclipse.jface.viewers.IOpenListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.OpenEvent; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IViewSite; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; import com.cloudbees.eclipse.core.CBRemoteChangeAdapter; import com.cloudbees.eclipse.core.CBRemoteChangeListener; import com.cloudbees.eclipse.core.CloudBeesException; import com.cloudbees.eclipse.core.jenkins.api.JenkinsBuild; import com.cloudbees.eclipse.core.jenkins.api.JenkinsJobAndBuildsResponse; import com.cloudbees.eclipse.core.util.Utils; import com.cloudbees.eclipse.dev.ui.CBDEVImages; import com.cloudbees.eclipse.dev.ui.CloudBeesDevUiPlugin; import com.cloudbees.eclipse.dev.ui.actions.InvokeBuildAction; import com.cloudbees.eclipse.dev.ui.actions.OpenBuildAction; import com.cloudbees.eclipse.dev.ui.actions.OpenLogAction; import com.cloudbees.eclipse.dev.ui.actions.ReloadBuildHistoryAction; import com.cloudbees.eclipse.ui.CloudBeesUIPlugin; import com.cloudbees.eclipse.ui.PreferenceConstants; public class BuildHistoryView extends ViewPart implements IPropertyChangeListener { public static final String ID = "com.cloudbees.eclipse.dev.ui.views.build.BuildHistoryView"; private TableViewer table; protected OpenBuildAction actionOpenBuild; protected OpenLogAction actionOpenLog; protected ReloadBuildHistoryAction actionReloadJobs; private InvokeBuildAction actionInvokeBuild; private Action actionOpenBuildInBrowser; private final Map<String, Image> stateIcons = new HashMap<String, Image>(); private CBRemoteChangeListener jenkinsChangeListener; private BuildHistoryContentProvider contentProvider; private String jobUrl; protected Object selectedBuild; public BuildHistoryView() { super(); } public Object getSelectedBuild() { return this.selectedBuild; } protected void setInput(final JenkinsJobAndBuildsResponse newView) { if (newView != null && newView.viewUrl != null) { IViewSite site = getViewSite(); String secId = site.getSecondaryId(); String servUrl = CloudBeesUIPlugin.getDefault().getJenkinsServiceForUrl(newView.viewUrl).getUrl(); if (secId != null && servUrl != null && !secId.equals(Long.toString(servUrl.hashCode()))) { return; // another view } } if (newView == null || newView.builds == null) { setContentDescription("No builds available."); this.contentProvider.inputChanged(this.table, null, null); } else { String label = newView.name; // CloudBeesUIPlugin.getDefault().getJenkinsServiceForUrl(newView.viewUrl).getLabel(); setContentDescription(label + " (" + new Date() + ")"); setPartName("Build History [" + label + "]"); this.contentProvider.inputChanged(this.table, null, newView); } if (newView != null) { this.jobUrl = newView.viewUrl; } else { this.jobUrl = null; } this.actionReloadJobs.setViewUrl(this.jobUrl); this.table.refresh(); } @Override public void createPartControl(final Composite parent) { initImages(); this.table = new TableViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION /*SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL*/); //Tree tree = viewer.getTree(); //tree.setHeaderVisible(true); //table.getTable().setLinesVisible(true); this.table.getTable().setHeaderVisible(true); TableViewerColumn statusCol = createColumn("S", 22, BuildSorter.STATE, new CellLabelProvider() { @Override public void update(final ViewerCell cell) { JenkinsBuild build = (JenkinsBuild) cell.getViewerRow().getElement(); String key = build.result; /* ImageData[] imageDatas = new ImageLoader().load(new FileInputStream("myAnimated.gif")); Image[] images = new Image[imageDatas.length]; for (int n = 0; n < imageDatas.length; n++) { // images[n] = new Image(myTable.getDislay(), imageDatas[n]); } */ // if (job.color != null && job.color.contains("_")) { // key = job.color.substring(0, job.color.indexOf("_")); // } Image img = BuildHistoryView.this.stateIcons.get(key); if (img != null) { cell.setText(""); cell.setImage(img); } else { cell.setImage(null); cell.setText(build.result); } } }); statusCol.getColumn().setToolTipText("Status"); //TODO i18n TableViewerColumn namecol = createColumn("Build", 50, BuildSorter.BUILD, new CellLabelProvider() { @Override public void update(final ViewerCell cell) { JenkinsBuild build = (JenkinsBuild) cell.getViewerRow().getElement(); String val; try { if (build.building) { val = "building"; } else { val = build.number.toString(); } } catch (Exception e) { val = ""; } cell.setText(val); } }); createColumn("When", 100, BuildSorter.TIME, new CellLabelProvider() { @Override public void update(final ViewerCell cell) { JenkinsBuild build = (JenkinsBuild) cell.getViewerRow().getElement(); if (build.timestamp != null) { try { cell.setText( Utils.humanReadableTime(System.currentTimeMillis() - build.timestamp) + " ago"); } catch (Exception e) { cell.setText(""); } } else { cell.setText(""); } cell.setImage(null); } }); createColumn("Build Duration", 100, BuildSorter.DURATION, new CellLabelProvider() { @Override public void update(final ViewerCell cell) { JenkinsBuild build = (JenkinsBuild) cell.getViewerRow().getElement(); if (build.duration != null) { try { cell.setText(Utils.humanReadableTime(build.duration)); } catch (Throwable t) { cell.setText(""); } } else { cell.setText(""); } } }); createColumn("Tests", 200, BuildSorter.TESTS, new CellLabelProvider() { @Override public void update(final ViewerCell cell) { JenkinsBuild build = (JenkinsBuild) cell.getViewerRow().getElement(); try { long total = 0; long failed = 0; long skipped = 0; for (com.cloudbees.eclipse.core.jenkins.api.JenkinsBuild.Action action : build.actions) { if ("testReport".equalsIgnoreCase(action.urlName)) { total += action.totalCount; failed += action.failCount; skipped += action.skipCount; } } if (total > 0 || failed > 0 || skipped > 0) { String val = "Passed: " + (total - failed - skipped); if (failed > 0) { val += ", failed: " + failed; } if (skipped > 0) { val += ", skipped: " + skipped; } cell.setText(val); } else { cell.setText(""); } } catch (Throwable t) { cell.setText(""); } } }); createColumn("Cause", 250, BuildSorter.CAUSE, new CellLabelProvider() { @Override public void update(final ViewerCell cell) { JenkinsBuild build = (JenkinsBuild) cell.getViewerRow().getElement(); String val = null; try { for (com.cloudbees.eclipse.core.jenkins.api.JenkinsBuild.Action action : build.actions) { if (action.causes != null && action.causes.length > 0) { val = action.causes[0].shortDescription; break; } } if (val == null) { val = ""; } cell.setText(val); } catch (Throwable t) { cell.setText(""); } } }); this.contentProvider = new BuildHistoryContentProvider(); this.table.setContentProvider(this.contentProvider); BuildSorter sorter = new BuildSorter(BuildSorter.BUILD); sorter.setDirection(SWT.UP); this.table.setSorter(sorter); this.table.setInput(getViewSite()); /* table.addFilter(new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { return true; } });*/ this.table.addOpenListener(new IOpenListener() { public void open(final OpenEvent event) { ISelection sel = event.getSelection(); if (sel instanceof IStructuredSelection) { Object el = ((IStructuredSelection) sel).getFirstElement(); if (el instanceof JenkinsBuild) { CloudBeesDevUiPlugin.getDefault().showBuild(((JenkinsBuild) el)); } } } }); this.table.getTable().setSortColumn(namecol.getColumn()); this.table.getTable().setSortDirection(SWT.DOWN); makeActions(); contributeToActionBars(); MenuManager popupMenu = new MenuManager(); popupMenu.add(this.actionOpenBuild); popupMenu.add(this.actionOpenLog); popupMenu.add(new Separator("cloudActions")); popupMenu.add(this.actionOpenBuildInBrowser); popupMenu.add(this.actionInvokeBuild); popupMenu.add(new Separator("reloadActions")); popupMenu.add(this.actionReloadJobs); Menu menu = popupMenu.createContextMenu(this.table.getTable()); this.table.getTable().setMenu(menu); this.table.addPostSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(final SelectionChangedEvent event) { StructuredSelection sel = (StructuredSelection) event.getSelection(); BuildHistoryView.this.selectedBuild = sel.getFirstElement(); boolean enable = BuildHistoryView.this.selectedBuild != null; BuildHistoryView.this.actionInvokeBuild.setJob(BuildHistoryView.this.selectedBuild); BuildHistoryView.this.actionOpenBuildInBrowser.setEnabled(enable); BuildHistoryView.this.actionOpenBuild.setBuild(BuildHistoryView.this.selectedBuild); BuildHistoryView.this.actionOpenLog.setBuild(BuildHistoryView.this.selectedBuild); getViewSite().getActionBars().getToolBarManager().update(true); } }); this.jenkinsChangeListener = new CBRemoteChangeAdapter() { public void activeJobHistoryChanged(final JenkinsJobAndBuildsResponse newView) { PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { public void run() { BuildHistoryView.this.setInput(newView); } }); } }; CloudBeesUIPlugin.getDefault().addCBRemoteChangeListener(this.jenkinsChangeListener); } private void initImages() { //TODO Refactor to use CBImages! this.stateIcons.put("", ImageDescriptor.createFromURL( CloudBeesDevUiPlugin.getDefault().getBundle().getResource("/icons/jenkins-icons/16x16/grey.gif")) .createImage()); this.stateIcons.put("SUCCESS", ImageDescriptor.createFromURL( CloudBeesDevUiPlugin.getDefault().getBundle().getResource("/icons/jenkins-icons/16x16/blue.gif")) .createImage()); this.stateIcons.put("FAILURE", ImageDescriptor.createFromURL( CloudBeesDevUiPlugin.getDefault().getBundle().getResource("/icons/jenkins-icons/16x16/red.gif")) .createImage()); this.stateIcons.put("UNSTABLE", ImageDescriptor.createFromURL( CloudBeesDevUiPlugin.getDefault().getBundle().getResource("/icons/jenkins-icons/16x16/yellow.gif")) .createImage()); } private TableViewerColumn createColumn(final String colName, final int width, final CellLabelProvider cellLabelProvider) { return createColumn(colName, width, -1, cellLabelProvider); } private TableViewerColumn createColumn(final String colName, final int width, final int sortCol, final CellLabelProvider cellLabelProvider) { final TableViewerColumn treeViewerColumn = new TableViewerColumn(this.table, SWT.NONE); TableColumn col = treeViewerColumn.getColumn(); if (width > 0) { col.setWidth(width); } col.setText(colName); col.setMoveable(true); treeViewerColumn.setLabelProvider(cellLabelProvider); if (sortCol >= 0) { treeViewerColumn.getColumn().addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { int newOrder = SWT.DOWN; if (BuildHistoryView.this.table.getTable().getSortColumn().equals(treeViewerColumn.getColumn()) && BuildHistoryView.this.table.getTable().getSortDirection() == SWT.DOWN) { newOrder = SWT.UP; } BuildHistoryView.this.table.getTable().setSortColumn(treeViewerColumn.getColumn()); BuildHistoryView.this.table.getTable().setSortDirection(newOrder); BuildSorter newSorter = new BuildSorter(sortCol); newSorter.setDirection(newOrder); BuildHistoryView.this.table.setSorter(newSorter); } }); } return treeViewerColumn; } private void contributeToActionBars() { IActionBars bars = getViewSite().getActionBars(); fillLocalPullDown(bars.getMenuManager()); fillLocalToolBar(bars.getToolBarManager()); } private void fillLocalToolBar(final IToolBarManager manager) { // manager.add(this.actionOpenBuild); // manager.add(this.actionOpenLog); manager.add(this.actionOpenBuildInBrowser); manager.add(this.actionInvokeBuild); manager.add(new Separator("reloadJob")); manager.add(this.actionReloadJobs); } private void fillLocalPullDown(final IMenuManager manager) { manager.add(this.actionOpenBuild); manager.add(this.actionOpenLog); // manager.add(this.actionInvokeBuild); // manager.add(new Separator()); // manager.add(this.actionReloadJobs); } private void makeActions() { CloudBeesUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this); this.actionOpenBuild = new OpenBuildAction(false); this.actionOpenLog = new OpenLogAction(); this.actionReloadJobs = new ReloadBuildHistoryAction(true); // this.actionOpenLastBuildDetails = new OpenBuildAction(this); // this.actionOpenLog = new OpenLogAction(this); // this.actionDeleteJob = new DeleteJobAction(this); this.actionOpenBuildInBrowser = new Action("Open with Browser...", Action.AS_PUSH_BUTTON | SWT.NO_FOCUS) { //$NON-NLS-1$ @Override public void run() { if (BuildHistoryView.this.selectedBuild != null) { JenkinsBuild build = (JenkinsBuild) BuildHistoryView.this.selectedBuild; CloudBeesUIPlugin.getDefault().openWithBrowser(build.url); } } }; this.actionOpenBuildInBrowser.setToolTipText("Open with Browser"); //TODO i18n this.actionOpenBuildInBrowser .setImageDescriptor(CloudBeesDevUiPlugin.getImageDescription(CBDEVImages.IMG_BROWSER)); this.actionOpenBuildInBrowser.setEnabled(false); this.actionInvokeBuild = new InvokeBuildAction(); CloudBeesUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this); } @Override public void setFocus() { this.table.getControl().setFocus(); } public void propertyChange(final PropertyChangeEvent event) { if (PreferenceConstants.P_JENKINS_INSTANCES.equals(event.getProperty()) || PreferenceConstants.P_EMAIL.equals(event.getProperty()) || PreferenceConstants.P_PASSWORD.equals(event.getProperty())) { try { CloudBeesDevUiPlugin.getDefault().showBuildHistory(this.jobUrl, false); } catch (CloudBeesException e) { //TODO i18n CloudBeesUIPlugin.showError("Failed to reload Jenkins jobs!", e); } } if (PreferenceConstants.P_JENKINS_REFRESH_INTERVAL.equals(event.getProperty()) || PreferenceConstants.P_JENKINS_REFRESH_ENABLED.equals(event.getProperty())) { boolean enabled = CloudBeesUIPlugin.getDefault().getPreferenceStore() .getBoolean(PreferenceConstants.P_JENKINS_REFRESH_ENABLED); int secs = CloudBeesUIPlugin.getDefault().getPreferenceStore() .getInt(PreferenceConstants.P_JENKINS_REFRESH_INTERVAL); if (enabled && secs > 0) { // startRefresher(); // start it if it was disabled by 0 value, do nothing if it was already running } else { // stopRefresher(); } } } @Override public void dispose() { CloudBeesUIPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this); CloudBeesUIPlugin.getDefault().removeCBRemoteChangeListener(this.jenkinsChangeListener); this.jenkinsChangeListener = null; // stopRefresher(); disposeImages(); super.dispose(); } private void disposeImages() { Iterator<Image> it = this.stateIcons.values().iterator(); while (it.hasNext()) { Image img = it.next(); img.dispose(); } this.stateIcons.clear(); } }