package com.baloise.jenkins.plugin; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import hudson.model.Job; import hudson.model.Result; import hudson.model.Run; import hudson.model.TopLevelItem; import hudson.model.View; import jenkins.model.Jenkins; public class ViewTracker { Logger LOG = Logger.getLogger(getClass().getName()); Map<String, Result> results = new HashMap<>(); List<ViewListener> listeners = new ArrayList<>(); private Collection<View> getViewsAffectedBy(Run<?, ?> run) { Collection<View> views = Jenkins.getInstance().getViews(); List<View> affected = new ArrayList<>(views.size()); TopLevelItem parent = getTopLevelParent(run); if (parent != null) { for (View view : views) { if (view.contains(parent)) { affected.add(view); } } } else { LOG.log(Level.WARNING, run.getParent().getClass() + " not instanceof TopLevelItem"); } return affected; } private TopLevelItem getTopLevelParent(Object o) { if(o == null) return null; if(o instanceof TopLevelItem) return (TopLevelItem) o; Object parent = null; try { Method getParent = o.getClass().getMethod("getParent", null); parent = getParent.invoke(o, null); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { LOG.log(Level.WARNING,e.getMessage()); } return getTopLevelParent(parent); } public ViewTracker addViewListener(ViewListener listener) { listeners.add(listener); return this; } public void trackViews(Run<?, ?> run) { Collection<View> affectedViews = getViewsAffectedBy(run); if (run.isBuilding()) { ensureInitialState(affectedViews); } else { fireDifference(affectedViews); } } private void fireDifference(Collection<View> affectedViews) { for (View view : affectedViews) { String key = key(view); Result newResult = getResult(view); Result oldResult = results.get(key); if(oldResult != null && !oldResult.equals(newResult)) { results.put(key, newResult); fireViewChanged(view, oldResult, newResult); } } } private void fireViewChanged(View view, Result oldResult, Result newResult) { for (ViewListener viewListener : listeners) { viewListener.fireViewChanged(view, oldResult, newResult); } } private Result getResult(View view) { Result ret = Result.SUCCESS; for (TopLevelItem item : view.getAllItems()) { for (Job<?,?> job : item.getAllJobs()) { Run<?, ?> build = job.getLastCompletedBuild(); if(build != null) { Result result = build.getResult(); if(result.isBetterOrEqualTo(Result.FAILURE)) ret = ret.combine(result); } } } return ret; } private String key(View view) { return view.getDisplayName(); } private void ensureInitialState(Collection<View> affectedViews) { for (View view : affectedViews) { String key = key(view); if (!results.containsKey(key)) { results.put(key, getResult(view)); } } } public void disable() { results.clear(); } }