package hudson.plugins.view.dashboard; import hudson.DescriptorExtensionList; import hudson.Extension; import hudson.Util; import hudson.model.AbstractProject; import hudson.model.Descriptor; import hudson.model.Hudson; import hudson.model.Item; import hudson.model.Job; import hudson.model.TopLevelItem; import hudson.model.View; import hudson.model.ViewDescriptor; import hudson.model.Descriptor.FormException; import hudson.util.CaseInsensitiveComparator; import hudson.util.FormValidation; import java.io.IOException; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import java.util.*; import javax.servlet.ServletException; import net.sf.json.JSONObject; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; /** * View that can be customized with portlets to show the selected jobs information * in various ways. * * @author Peter Hayes */ public class Dashboard extends View { /* * List of job names to be included in this view */ final SortedSet<String> jobNames = new TreeSet<String>(CaseInsensitiveComparator.INSTANCE); /* * Include regex string. */ private String includeRegex; /* * Compiled include pattern from the includeRegex string. */ private transient Pattern includePattern; /* * If using regex, prevent disabled jobs from appearing in the list */ private boolean excludeDisabledJobs = false; /* * Show standard hudson jobs list at the top of the page */ private boolean includeStdJobList = false; /* * The configured summarized reports for this summary view */ private List<DashboardPortlet> leftPortlets = new ArrayList<DashboardPortlet>(); private List<DashboardPortlet> rightPortlets = new ArrayList<DashboardPortlet>(); private List<DashboardPortlet> topPortlets = new ArrayList<DashboardPortlet>(); private List<DashboardPortlet> bottomPortlets = new ArrayList<DashboardPortlet>(); @DataBoundConstructor public Dashboard(String name) { super(name); } private Object readResolve() { if(includeRegex != null) includePattern = Pattern.compile(includeRegex); return this; } public String getIncludeRegex() { return includeRegex; } public boolean isExcludeDisabledJobs() { return excludeDisabledJobs; } public boolean isIncludeStdJobList() { return includeStdJobList; } public List<DashboardPortlet> getLeftPortlets() { return leftPortlets; } public List<DashboardPortlet> getRightPortlets() { return rightPortlets; } public List<DashboardPortlet> getTopPortlets() { return topPortlets; } public List<DashboardPortlet> getBottomPortlets() { return bottomPortlets; } public DashboardPortlet getPortlet(String name) { ArrayList<DashboardPortlet> allPortlets = new ArrayList<DashboardPortlet>(topPortlets); allPortlets.addAll(leftPortlets); allPortlets.addAll(rightPortlets); allPortlets.addAll(bottomPortlets); for (DashboardPortlet portlet : allPortlets) { if (name.equals(portlet.getId())) { return portlet; } } return null; } public DescriptorExtensionList<DashboardPortlet, Descriptor<DashboardPortlet>> getDashboardPortletDescriptors() { DescriptorExtensionList<DashboardPortlet, Descriptor<DashboardPortlet>> list = DashboardPortlet.all(); // Collections.sort(list); // Collections.sort(list, new Comparator<Descriptor<DashboardPortlet>>() { // public int compare(Descriptor<DashboardPortlet> p1, Descriptor<DashboardPortlet> p2) { // return p1.getDisplayName().compareTo(p2.getDisplayName()); // } // }); return list; } @Override public synchronized boolean contains(TopLevelItem item) { return jobNames.contains(item.getName()); } @Override public Item doCreateItem(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { Item item = Hudson.getInstance().doCreateItem(req, rsp); if (item != null) { synchronized (this) { jobNames.add(item.getName()); } owner.save(); } return item; } /** * Returns a read-only view of all {@link Job}s in this view. * * <p> * This method returns a separate copy each time to avoid * concurrent modification issue. */ public synchronized List<TopLevelItem> getItems() { List<TopLevelItem> items = new ArrayList<TopLevelItem>(); List<TopLevelItem> allItems = Hudson.getInstance().getItems(); for (TopLevelItem item : allItems) { if (item != null && item instanceof Job) { if (HasItem(item)) { items.add(item); } } } return items; } public synchronized boolean HasItem(TopLevelItem item) { if (!(item instanceof Job)) { return false; } boolean res = false; if (includePattern != null) { if (includePattern.matcher(item.getName()).matches()) { res = true; } } res |= contains(item); if (res && isExcludeDisabledJobs() && item instanceof AbstractProject) { AbstractProject project = (AbstractProject) item; res &= !project.isDisabled(); } return res; } public synchronized List<Job> getJobs() { List<Job> jobs = new ArrayList<Job>(); for (TopLevelItem item : getItems()) { if (item instanceof Job) { jobs.add((Job) item); } } return jobs; } @Override public synchronized void onJobRenamed(Item item, String oldName, String newName) { if (jobNames.remove(oldName) && newName != null) { jobNames.add(newName); } } @Override protected synchronized void submit(StaplerRequest req) throws IOException, ServletException, FormException { req.setCharacterEncoding("UTF-8"); JSONObject json = req.getSubmittedForm(); jobNames.clear(); for (TopLevelItem item : Hudson.getInstance().getItems()) { if(req.getParameter(item.getName())!=null) jobNames.add(item.getName()); } if (req.getParameter("useincluderegex") != null) { includeRegex = Util.nullify(req.getParameter("includeRegex")); includePattern = Pattern.compile(includeRegex); } else { includeRegex = null; includePattern = null; // excludeDisabledJobs = false; } String sExcludeDisabledJobs = Util.nullify(req.getParameter("excludeDisabledJobs")); excludeDisabledJobs = sExcludeDisabledJobs != null && "on".equals(sExcludeDisabledJobs); String sIncludeStdJobList = Util.nullify(req.getParameter("includeStdJobList")); includeStdJobList = sIncludeStdJobList != null && "on".equals(sIncludeStdJobList); topPortlets = Descriptor.newInstancesFromHeteroList(req, json, "topPortlet", DashboardPortlet.all()); leftPortlets = Descriptor.newInstancesFromHeteroList(req, json, "leftPortlet", DashboardPortlet.all()); rightPortlets = Descriptor.newInstancesFromHeteroList(req, json, "rightPortlet", DashboardPortlet.all()); bottomPortlets = Descriptor.newInstancesFromHeteroList(req, json, "bottomPortlet", DashboardPortlet.all()); } @Extension public static final class DescriptorImpl extends ViewDescriptor { @Override public String getDisplayName() { return "Dashboard"; } /** * Checks if the include regular expression is valid. */ public FormValidation doCheckIncludeRegex( @QueryParameter String value ) throws IOException, ServletException, InterruptedException { String v = Util.fixEmpty(value); if (v != null) { try { Pattern.compile(v); } catch (PatternSyntaxException pse) { return FormValidation.error(pse.getMessage()); } } return FormValidation.ok(); } } }