package de.fspengler.hudson.pview; import hudson.model.AbstractProject; import hudson.model.Action; import hudson.model.Hudson; import hudson.model.RSS; import hudson.model.Run; import hudson.model.TopLevelItem; import hudson.model.User; import hudson.security.ACL; import hudson.security.AccessControlled; import hudson.security.Permission; import hudson.util.RunList; import hudson.views.BuildButtonColumn; import hudson.views.JobColumn; import hudson.views.LastDurationColumn; import hudson.views.LastFailureColumn; import hudson.views.LastStableColumn; import hudson.views.LastSuccessColumn; import hudson.views.ListViewColumn; import hudson.views.StatusColumn; import hudson.views.WeatherColumn; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.SortedMap; import java.util.TreeMap; import java.util.regex.Pattern; import javax.servlet.ServletException; import org.kohsuke.stapler.Stapler; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.export.ExportedBean; /** * Link for call the personal view * * @author Tom Spengler */ @ExportedBean public class PViewLinkAction implements Action, AccessControlled { private static final String URL_PART_SI_VIEW = "siView"; private static final String URL_PART_ROOT_SI_VIEW = "rootSiView"; private static final String P_URL_PVIEW_ROOT_SI_VIEW = "/pview/" + URL_PART_ROOT_SI_VIEW ; private static final String P_URL_PVIEW_SI_VIEW = "/pview/" + URL_PART_SI_VIEW; private static final long serialVersionUID = 1L; public String getDisplayName() { StaplerRequest req = Stapler.getCurrentRequest(); if(req!=null && req.getOriginalRequestURI().contains("/view")){ return null; } if (req.getAttribute("rootisSet") != null){ if (req.getAttribute("rootProject") != null){ return "Tree View: " + req.getAttribute("rootProject") ; } return "Tree View"; } if (User.current() != null) { req.setAttribute("rootisSet",Boolean.TRUE); return "Personal View"; } else { return "Anonymous View"; } } public String getUrlName() { StaplerRequest req = Stapler.getCurrentRequest(); if(req!=null && req.getOriginalRequestURI().contains("/view")){ return null; } return "pview"; } public String getIconFileName() { StaplerRequest req = Stapler.getCurrentRequest(); if(req!=null && req.getOriginalRequestURI().contains("/view")){ return null; } return "up.gif"; } private boolean isIsTreePosition (int position, boolean pDefault){ if (!isIsTree()){ return false; } if (getUser() && getUserProp() != null ) return ((getUserProp().getTreePosition() == position)); else return pDefault; } public boolean isIsTreeNE() { return isIsTreePosition(0, true); } public boolean isIsTreeSE() { return isIsTreePosition(1, false); } public boolean isIsTreeNW() { return isIsTreePosition(2, false); } public boolean isIsTreeSW() { return isIsTreePosition(3, false); } public boolean isIsTree() { StaplerRequest req = Stapler.getCurrentRequest(); if(req!=null && (req.getOriginalRequestURI().startsWith(getStepInViewUrl(req)) || req.getOriginalRequestURI().startsWith(getStepInViewRoot(req)) )){ return true; } return false; } private String getStepInViewRoot(StaplerRequest req) { return req.getContextPath() + P_URL_PVIEW_ROOT_SI_VIEW; } private String getStepInViewUrl(StaplerRequest req) { return req.getContextPath() + P_URL_PVIEW_SI_VIEW; } public boolean isIsList() { return !isIsTree(); } public String getUserLogin(){ if (getUser() ) return User.current().getUrl(); else return ""; } public boolean isHasUp () { if (isIsTree()){ return getProjectMatcher().length() > 0; } return false; } public String getTreeParent(){ String result; if (isIsTree()){ String matcher = getProjectMatcher(); String splitChar = "-"; if (getUserProp() != null ) { splitChar = getUserProp().getTreeSplitChar(); } if (matcher.indexOf(splitChar) > -1){ result = URL_PART_SI_VIEW + "/" + matcher.substring(0, matcher.lastIndexOf(splitChar)) + "/"; } else { result = URL_PART_ROOT_SI_VIEW; } } else { result = ""; } return result; } @SuppressWarnings("unchecked") public Collection<DirEntry> getSubDirs(){ String splitChar = "-"; if (getUserProp() != null ) { splitChar = getUserProp().getTreeSplitChar(); } List<AbstractProject> iList = Hudson.getInstance().getItems(AbstractProject.class); SortedMap<String,DirEntry> dirSet = new TreeMap<String,DirEntry>(); String startMatcher = getProjectMatcher(); int lenMatcher = startMatcher.length(); Pattern pat=getFreePattern(Stapler.getCurrentRequest()); if (lenMatcher > 0) { for (AbstractProject abstractProject : iList) { if ((pat == null || pat.matcher(abstractProject.getName()).matches() ) && abstractProject.getName().startsWith(startMatcher)) { int posOfMatcher = abstractProject.getName().indexOf(splitChar, lenMatcher + 1); if (posOfMatcher > -1) { String abString = abstractProject.getName().substring(lenMatcher+1, posOfMatcher); if (dirSet.containsKey(abString)){ dirSet.get(abString).addOne(); } else { DirEntry de =new DirEntry(abString, startMatcher + splitChar + abString ); dirSet.put(abString, de); } } } } } else { for (AbstractProject abstractProject : iList) { if ((pat == null || pat.matcher(abstractProject.getName()).matches() ) && abstractProject.getName().startsWith(startMatcher)) { int posOfMatcher = abstractProject.getName().indexOf(splitChar); if (posOfMatcher > -1) { String abString = abstractProject.getName().substring(0, posOfMatcher); if (dirSet.containsKey(abString)){ dirSet.get(abString).addOne(); } else { DirEntry de =new DirEntry(abString, abString ); dirSet.put(abString, de); } } } } } return dirSet.values(); } @SuppressWarnings("unchecked") public List<AbstractProject> getJobs() { return getJobs(null,null); } @SuppressWarnings("unchecked") public List<AbstractProject> getJobs(StaplerRequest req, StaplerResponse rsp) { StaplerRequest mReq = (req == null ? Stapler.getCurrentRequest() : req); List<AbstractProject> jobList = new ArrayList<AbstractProject>(); List<AbstractProject> iList = Hudson.getInstance().getItems(AbstractProject.class); String splitChar = "-"; if (getUserProp() != null) { splitChar = getUserProp().getTreeSplitChar(); } //Step in if (isIsTree()){ // RootStep in if (mReq.getOriginalRequestURI().startsWith(getStepInViewRoot(mReq))){ Pattern pat = getFreePattern(mReq); if (pat != null && !pat.pattern().equals(".*")) { for (AbstractProject<?, ?> abstractProject : iList) { if (pat.matcher(abstractProject.getName()).matches()){ jobList.add(abstractProject); } } } else { for (AbstractProject<?, ?> abstractProject : iList) { if (!abstractProject.getName().contains(splitChar)){ jobList.add(abstractProject); } } } } else { String startMatcher = getProjectMatcher(mReq); Pattern pat = getFreePattern(mReq); for (AbstractProject<?, ?> abstractProject : iList) { if (abstractProject.getName().startsWith(startMatcher)){ if (pat != null){ if (pat.matcher(abstractProject.getName()).matches()){ jobList.add(abstractProject); } } else { jobList.add(abstractProject); } int stepInNumberJobs = 30; if (getUserProp() != null) { stepInNumberJobs = getUserProp().getStepInNumberJobs(); } if (jobList.size() > stepInNumberJobs){ jobList.clear(); break; } } } } } else { // ListView Pattern pat = getUserPattern(mReq); for (AbstractProject abstractProject : iList) { if (pat.matcher(abstractProject.getName()).matches()){ jobList.add(abstractProject); } } } return jobList; } private Pattern getFreePattern(StaplerRequest req) { Pattern pat = null; if (req.hasParameter("match") && req.getParameter("match").length() > 0){ pat = Pattern.compile(req.getParameter("match")); } return pat; } public String getNicePattern(){ Pattern pat =getFreePattern(Stapler.getCurrentRequest()); if (pat != null){ return pat.pattern(); } else { return ".*"; } } public String getNiceUserPattern(){ Pattern pat =getUserPattern(Stapler.getCurrentRequest()); if (pat != null){ return pat.pattern(); } else { return ".*"; } } public String getProjectMatcher() { return getProjectMatcher(Stapler.getCurrentRequest()); } public String getProjectMatcher(StaplerRequest req) { String orgUri= req.getOriginalRequestURI(); if (orgUri.substring(orgUri.lastIndexOf("/")).startsWith("/rss")) { orgUri = orgUri.substring(0,orgUri.lastIndexOf("/") +1); } if ( ! orgUri.startsWith(getStepInViewUrl(req) + "/")){ return ""; } String matchPoint = orgUri.substring((getStepInViewUrl(req) + "/").length(),orgUri.length() -1); return matchPoint; } private Pattern getUserPattern(StaplerRequest req) { Pattern pat = getFreePattern(req); if (pat != null){ return pat; } UserPersonalViewProperty up = getUserProp(); if (up != null){ pat = Pattern.compile(getUserProp().getPViewExpression()); } else { pat = Pattern.compile(PViewProjectProperty.DESCRIPTOR.getRegex()); } return pat; } public boolean getShowQueue(){ if (getUserProp() == null){ return true; } else { return !getUserProp().isPViewBuildNoQueue(); } } public boolean getShowExecutor(){ if (getUserProp() == null){ return true; } else { return !getUserProp().isPViewBuildNoExecutor(); } } private UserPersonalViewProperty getUserProp(){ if (User.current() != null) return User.current().getProperty(UserPersonalViewProperty.class); else return null; } public boolean getUser(){ return (User.current() != null); } public ACL getACL() { return Hudson.getInstance().getACL(); } public void checkPermission(Permission p) { getACL().checkPermission(p); } public boolean hasPermission(Permission p) { return (User.current() != null); } public void doRssAll( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { rss(req, rsp, " all builds", getBuilds(req, rsp)); } public void doRssFailed( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { rss(req, rsp, " failed builds", getBuilds(req, rsp).failureOnly()); } public RunList getBuilds() { return getBuilds(null,null); } private RunList getBuilds(StaplerRequest req, StaplerResponse rsp){ return new RunList(getJobs(req, rsp)); } private void rss(StaplerRequest req, StaplerResponse rsp, String suffix, RunList runs) throws IOException, ServletException { RSS.forwardToRss(getDisplayName()+ suffix, getUrlName(), runs.newBuilds(), Run.FEED_ADAPTER, req, rsp ); } @SuppressWarnings("unchecked") public void doRssLatest( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { List<Run<?,?>> lastBuilds = new ArrayList<Run<?,?>>(); List<AbstractProject> list = getJobs(req, rsp); for (AbstractProject project: list){ Run<?,?> lb = project.getLastBuild(); if(lb!=null) lastBuilds.add(lb); } RSS.forwardToRss(getDisplayName()+" last builds only", getUrlName(), lastBuilds, Run.FEED_ADAPTER_LATEST, req, rsp ); } /** * Alias for {@link #getItem(String)}. This is the one used in the URL binding. */ public final TopLevelItem getJob(String name) { return Hudson.getInstance().getItem(name); } public List<ListViewColumn> getColumns (){ ArrayList<ListViewColumn> rlist = new ArrayList<ListViewColumn>(); UserPersonalViewProperty up = getUserProp() ; if (up == null) { rlist.add(new StatusColumn()); rlist.add(new WeatherColumn()); rlist.add(new JobColumn()); rlist.add(new LastSuccessColumn()); rlist.add(new LastFailureColumn()); rlist.add(new LastStableColumn()); rlist.add(new LastDurationColumn()); rlist.add(new ConsoleViewColumn()); rlist.add(new BuildButtonColumn()); } else { if (up.isPcStatus()) rlist.add(new StatusColumn()); if (up.isPcWeather()) rlist.add(new WeatherColumn()); if (up.isPcJob()) rlist.add(new JobColumn()); if (up.isPcLastSuccess()) rlist.add(new LastSuccessColumn()); if (up.isPcLastFailure()) rlist.add(new LastFailureColumn()); if (up.isPcLastStable()) rlist.add(new LastStableColumn()); if (up.isPcLastDuration()) rlist.add(new LastDurationColumn()); if (up.isPcConsoleView()) rlist.add(new ConsoleViewColumn()); if (up.isPcBuildButton()) rlist.add(new BuildButtonColumn()); } return rlist; } /** * Alias for {@link #getItem(String)}. This is the one used in the URL binding. */ public final PViewLinkAction getSiView(String rootProject) throws CloneNotSupportedException { StaplerRequest req = Stapler.getCurrentRequest(); req.setAttribute("rootProject",rootProject); return this; } /** * Alias for {@link #getItem(String)}. This is the one used in the URL binding. * @throws CloneNotSupportedException */ public final PViewLinkAction getRootSiView() throws CloneNotSupportedException { StaplerRequest req = Stapler.getCurrentRequest(); req.removeAttribute("rootProject"); return this; } }