package hudson.plugins.mantis; import hudson.Extension; import hudson.Util; import hudson.model.AbstractProject; import hudson.model.Hudson; import hudson.model.Job; import hudson.model.JobProperty; import hudson.model.JobPropertyDescriptor; import hudson.plugins.mantis.MantisSite.MantisVersion; import hudson.util.CopyOnWriteList; import hudson.util.FormValidation; import java.io.IOException; import java.net.URL; import java.util.regex.Pattern; import javax.servlet.ServletException; import net.sf.json.JSONObject; import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; /** * Associates {@link AbstractProject} with {@link MantisSite}. * * @author Seiji Sogabe */ public final class MantisProjectProperty extends JobProperty<AbstractProject<?, ?>> { @Extension public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); private static final String ISSUE_ID_STRING = "%ID%"; private static final String DEFAULT_PATTERN = "issue #?" + ISSUE_ID_STRING; private final String siteName; private final String pattern; private final String regex; private Pattern regexpPattern; private final boolean linkEnabled; @DataBoundConstructor public MantisProjectProperty(final String siteName, final String pattern, final String regex, final boolean linkEnabled) { final String name = (siteName != null) ? siteName : defaultSiteName(); this.siteName = Util.fixEmptyAndTrim(name); this.pattern = Util.fixEmptyAndTrim(pattern); this.regex = Util.fixEmptyAndTrim(regex); this.regexpPattern = (this.regex != null) ? Pattern.compile(this.regex) : createRegexp(this.pattern); this.linkEnabled = linkEnabled; } public String getSiteName() { return siteName; } public String getPattern() { return pattern; } public String getRegex() { return regex; } public Pattern getRegexpPattern() { // If project configuration has not saved after upgrading to 0.8.0, // return default issue id pattern. return (regexpPattern != null) ? regexpPattern : createRegexp(pattern); } public boolean isLinkEnabled() { return linkEnabled; } public MantisSite getSite() { final MantisSite[] sites = DESCRIPTOR.getSites(); if (siteName == null && sites.length > 0) { return sites[0]; } for (final MantisSite site : sites) { if (site.getName().equals(siteName)) { return site; } } return null; } private String defaultSiteName() { final MantisSite[] sites = DESCRIPTOR.getSites(); if (sites.length > 0) { return sites[0].getName(); } return null; } private Pattern createRegexp(final String p) { final StringBuffer buf = new StringBuffer(); buf.append("(?<="); if (p != null) { buf.append(Utility.escapeRegexp(p)); } else { buf.append(DEFAULT_PATTERN); } buf.append(')'); final String pt = buf.toString().replace(ISSUE_ID_STRING, ")(\\d+)(?="); return Pattern.compile(pt); } public static final class DescriptorImpl extends JobPropertyDescriptor { private final CopyOnWriteList<MantisSite> sites = new CopyOnWriteList<MantisSite>(); public DescriptorImpl() { super(MantisProjectProperty.class); load(); } @SuppressWarnings("unchecked") @Override public boolean isApplicable(final Class<? extends Job> jobType) { return AbstractProject.class.isAssignableFrom(jobType); } @Override public String getDisplayName() { return Messages.MantisProjectProperty_DisplayName(); } public MantisSite[] getSites() { return sites.toArray(new MantisSite[0]); } public MantisVersion[] getMantisVersions() { return MantisSite.MantisVersion.values(); } @Override public JobProperty<?> newInstance(final StaplerRequest req, final JSONObject formData) throws FormException { MantisProjectProperty mpp = req.bindParameters(MantisProjectProperty.class, "mantis."); if (mpp.siteName == null) { mpp = null; } return mpp; } @Override public boolean configure(final StaplerRequest req, final JSONObject formData) { sites.replaceBy(req.bindParametersToList(MantisSite.class, "mantis.")); save(); return true; } public FormValidation doCheckLogin(final StaplerRequest req, final StaplerResponse res) throws IOException, ServletException { // only administrator allowed Hudson.getInstance().checkPermission(Hudson.ADMINISTER); final String url = Util.fixEmptyAndTrim(req.getParameter("url")); if (url == null) { return FormValidation.error(Messages.MantisProjectProperty_MantisUrlMandatory()); } final String user = Util.fixEmptyAndTrim(req.getParameter("user")); final String pass = Util.fixEmptyAndTrim(req.getParameter("pass")); final String bUser = Util.fixEmptyAndTrim(req.getParameter("buser")); final String bPass = Util.fixEmptyAndTrim(req.getParameter("bpass")); final String ver = Util.fixEmptyAndTrim(req.getParameter("version")); MantisVersion version = MantisVersion.getVersionSafely(ver, MantisVersion.V110); final MantisSite site = new MantisSite(new URL(url), version.name(), user, pass, bUser, bPass); if (!site.isConnect()) { return FormValidation.error(Messages.MantisProjectProperty_UnableToLogin()); } return FormValidation.ok(); } public FormValidation doCheckPattern(@AncestorInPath final AbstractProject<?, ?> project, @QueryParameter final String pattern) throws IOException, ServletException { project.checkPermission(Job.CONFIGURE); final String p = Util.fixEmptyAndTrim(pattern); if (p != null && p.indexOf(ISSUE_ID_STRING) == -1) { return FormValidation.error(Messages.MantisProjectProperty_InvalidPattern(ISSUE_ID_STRING)); } return FormValidation.ok(); } } }