From 0da3881226d344bbb81ca9bfe2a3c1bff0014027 Mon Sep 17 00:00:00 2001 From: jacobrobertson <jacob.robertson.work@gmail.com> Date: Sun, 13 Nov 2011 08:23:50 -0600 Subject: [PATCH] adding regex support --- pom.xml | 7 ++ .../sitemonitor/SiteMonitorDescriptor.java | 41 ++++++++-- .../sitemonitor/SiteMonitorRecorder.java | 48 +++++++++++- .../sitemonitor/SiteMonitorValidator.java | 19 +++++ .../plugins/sitemonitor/model/Site.java | 76 +++++++++++++++++++ .../plugins/sitemonitor/Messages.properties | 3 + .../SiteMonitorRecorder/config.jelly | 16 +++- src/main/webapp/url.html | 7 +- .../plugins/sitemonitor/model/SiteTest.java | 12 +++ 9 files changed, 218 insertions(+), 11 deletions(-) mode change 100755 => 100644 src/main/resources/hudson/plugins/sitemonitor/Messages.properties diff --git a/pom.xml b/pom.xml index 4c871f5..59a44e7 100644 --- a/pom.xml +++ b/pom.xml @@ -69,6 +69,13 @@ </systemPropertyVariables> </configuration> </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.6</source> + <target>1.6</target> + </configuration> + </plugin> </plugins> </build> diff --git a/src/main/java/hudson/plugins/sitemonitor/SiteMonitorDescriptor.java b/src/main/java/hudson/plugins/sitemonitor/SiteMonitorDescriptor.java index 8d5b9ce..f938c93 100644 --- a/src/main/java/hudson/plugins/sitemonitor/SiteMonitorDescriptor.java +++ b/src/main/java/hudson/plugins/sitemonitor/SiteMonitorDescriptor.java @@ -152,15 +152,13 @@ public final Publisher newInstance(final StaplerRequest request, Object sitesObject = json.get("sites"); if (sitesObject instanceof JSONObject) { - for (Object siteObject : json.getJSONObject("sites").values()) { - String url = String.valueOf(siteObject); - sites.add(new Site(url)); - } + Site site = toSite((JSONObject) sitesObject); + sites.add(site); } else if (sitesObject instanceof JSONArray) { for (Object siteObject : (JSONArray) sitesObject) { if (siteObject instanceof JSONObject) { - String url = ((JSONObject) siteObject).getString("url"); - sites.add(new Site(url)); + Site site = toSite((JSONObject) siteObject); + sites.add(site); } } } else { @@ -170,6 +168,19 @@ public final Publisher newInstance(final StaplerRequest request, return new SiteMonitorRecorder(sites); } + /** + * Converts the json object to the Site. + * @param siteObject + * the siteObject submitted + * @return the new Site + */ + private Site toSite(JSONObject siteObject) { + String url = siteObject.getString("url"); + String regex = siteObject.getString("regularExpression"); + boolean regexFlag = siteObject.getBoolean("failWhenRegexNotFound"); + return new Site(url, regex, regexFlag); + } + /** * Handles SiteMonitor global configuration per Jenkins instance. * @param request @@ -205,6 +216,15 @@ public final FormValidation doCheckUrl(@QueryParameter final String value) { return mValidator.validateUrl(value); } + /** + * @param value + * the value to validate + * @return true if value is a valid Regex, false otherwise + */ + public final FormValidation doCheckRegex(@QueryParameter final String value) { + return mValidator.validateRegex(value); + } + /** * @param value * the value to validate @@ -225,4 +245,13 @@ public final FormValidation doCheckTimeout( @QueryParameter final String value) { return mValidator.validateTimeout(value); } + + /** + * @return the url to the help fule + */ + @Override + public String getHelpFile() { + return "/plugin/sitemonitor/url.html"; + } + } diff --git a/src/main/java/hudson/plugins/sitemonitor/SiteMonitorRecorder.java b/src/main/java/hudson/plugins/sitemonitor/SiteMonitorRecorder.java index 946a669..3497674 100644 --- a/src/main/java/hudson/plugins/sitemonitor/SiteMonitorRecorder.java +++ b/src/main/java/hudson/plugins/sitemonitor/SiteMonitorRecorder.java @@ -35,7 +35,6 @@ import java.net.MalformedURLException; import java.net.SocketTimeoutException; import java.net.URL; -import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; @@ -48,8 +47,12 @@ import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; + +import org.apache.commons.io.IOUtils; + import java.util.ArrayList; import java.util.List; +import java.util.regex.Matcher; /** * Performs the web site monitoring process. @@ -161,6 +164,13 @@ public final boolean perform(final AbstractBuild<?, ?> build, } else { status = Status.ERROR; } + + if (status == Status.UP && site.getRegularExpressionPattern() != null) { + Result regexResult = validateWithRegularExpression(site, connection); + note = regexResult.getNote(); + status = regexResult.getStatus(); + } + } catch (SocketTimeoutException ste) { listener.getLogger().println(ste + " - " + ste.getMessage()); status = Status.DOWN; @@ -203,6 +213,42 @@ public final boolean perform(final AbstractBuild<?, ?> build, return !hasFailure; } + /** + * @param site + * the Site configuration object + * @param connection + * the connection to the site + * @return the Result with the status and note + * @throws IOException + * When any IO fails + */ + private Result validateWithRegularExpression(Site site, HttpURLConnection connection) throws IOException { + String page = IOUtils.toString(connection.getInputStream()); + Matcher matcher = site.getRegularExpressionPattern().matcher(page); + boolean found = matcher.find(); + String foundString = null; + boolean exact = false; + if (found) { + foundString = matcher.group(); + if (site.getRegularExpression().equals(foundString)) { + exact = true; + } + } + Status status = Status.UP; + if (site.isFailWhenRegexNotFound() != found) { + status = Status.DOWN; + } + String note; + if (exact) { + note = Messages.SiteMonitor_Status_RegularExpressionExactMatch(foundString); + } else if (found) { + note = Messages.SiteMonitor_Status_RegularExpressionFound(site.getRegularExpression(), foundString); + } else { + note = Messages.SiteMonitor_Status_RegularExpressionNotFound(site.getRegularExpression()); + } + return new Result(null, 0, status, note); + } + /** * Gets the required monitor service. * @return the BuildStepMonitor diff --git a/src/main/java/hudson/plugins/sitemonitor/SiteMonitorValidator.java b/src/main/java/hudson/plugins/sitemonitor/SiteMonitorValidator.java index b4dbc04..1108aa8 100644 --- a/src/main/java/hudson/plugins/sitemonitor/SiteMonitorValidator.java +++ b/src/main/java/hudson/plugins/sitemonitor/SiteMonitorValidator.java @@ -27,6 +27,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; @@ -60,6 +61,24 @@ public final FormValidation validateUrl(final String url) { return validation; } + /** + * Validates a regex. + * @param regex + * the regex + * @return false when regex is malformed, true otherwise + */ + public final FormValidation validateRegex(final String regex) { + FormValidation validation = FormValidation.ok(); + if (StringUtils.isNotBlank(regex)) { + try { + Pattern.compile(regex); + } catch (Exception e) { + validation = FormValidation.error(e, e.getLocalizedMessage()); + } + } + return validation; + } + /** * Validates HTTP connection timeout value. * @param timeout diff --git a/src/main/java/hudson/plugins/sitemonitor/model/Site.java b/src/main/java/hudson/plugins/sitemonitor/model/Site.java index 4fbd16e..f158b2f 100644 --- a/src/main/java/hudson/plugins/sitemonitor/model/Site.java +++ b/src/main/java/hudson/plugins/sitemonitor/model/Site.java @@ -21,6 +21,10 @@ */ package hudson.plugins.sitemonitor.model; +import java.util.regex.Pattern; + +import org.apache.commons.lang.StringUtils; + /** * This class keeps the details of the web site to be monitored. * @author cliffano @@ -32,6 +36,37 @@ public class Site { */ private String mUrl; + /** + * The regular expression to check. + */ + private String mRegularExpression; + + /** + * The pattern for the expression to check. + */ + transient private Pattern mRegularExpressionPattern; + + /** + * The flag for checking the regex. + */ + private boolean mFailWhenRegexNotFound = true; + + /** + * Constructs a Site with specified details. + * @param url + * the web site URL + * @param regularExpression + * the regular expression to check + * @param failWhenRegexNotFound + * the flag for checking the regex + */ + public Site(final String url, final String regularExpression, final boolean failWhenRegexNotFound) { + mUrl = url; + mRegularExpression = regularExpression; + mFailWhenRegexNotFound = failWhenRegexNotFound; + setRegexPattern(); + } + /** * Constructs a Site with specified details. * @param url @@ -41,10 +76,51 @@ public Site(final String url) { mUrl = url; } + /** + * Sets the regex pattern based on the regex. + */ + private void setRegexPattern() { + if (!StringUtils.isEmpty(mRegularExpression)) { + mRegularExpressionPattern = Pattern.compile(mRegularExpression); + } else { + mRegularExpressionPattern = null; + } + } + + /** + * Part of the serialization strategy. + * @return this + */ + Object readResolve() { + setRegexPattern(); + return this; + } + /** * @return the web site URL */ public final String getUrl() { return mUrl; } + + /** + * @return the regular expression to check + */ + public final String getRegularExpression() { + return mRegularExpression; + } + + /** + * @return the Pattern for the regular expression to check + */ + public final Pattern getRegularExpressionPattern() { + return mRegularExpressionPattern; + } + + /** + * @return the flag for checking the regex + */ + public final boolean isFailWhenRegexNotFound() { + return mFailWhenRegexNotFound; + } } diff --git a/src/main/resources/hudson/plugins/sitemonitor/Messages.properties b/src/main/resources/hudson/plugins/sitemonitor/Messages.properties old mode 100755 new mode 100644 index 7bde220..50dc075 --- a/src/main/resources/hudson/plugins/sitemonitor/Messages.properties +++ b/src/main/resources/hudson/plugins/sitemonitor/Messages.properties @@ -5,6 +5,9 @@ SiteMonitor.Error.PrefixOfURL=URL must start with http:// or https:// SiteMonitor.Error.TimeoutIsBlank=Timeout value must be provided SiteMonitor.Error.TimeoutIsNotDigit=Timeout value must be a number SiteMonitor.Error.InvalidResponseCode=Invalid response code(s): +SiteMonitor.Status.RegularExpressionNotFound=Regular expression "{0}" was not found. +SiteMonitor.Status.RegularExpressionExactMatch=Exact text "{0}" was found. +SiteMonitor.Status.RegularExpressionFound=Regular expression "{0}" was found.<br/>Matching text was "{1}". SiteMonitor.Console.URL=URL: SiteMonitor.Console.ResponseCode=response code: SiteMonitor.Console.Status=status: diff --git a/src/main/resources/hudson/plugins/sitemonitor/SiteMonitorRecorder/config.jelly b/src/main/resources/hudson/plugins/sitemonitor/SiteMonitorRecorder/config.jelly index 7312c89..16710e1 100644 --- a/src/main/resources/hudson/plugins/sitemonitor/SiteMonitorRecorder/config.jelly +++ b/src/main/resources/hudson/plugins/sitemonitor/SiteMonitorRecorder/config.jelly @@ -2,10 +2,20 @@ <f:entry title=""> <f:repeatable var="site" name="sites" items="${instance.sites}" noAddButton="true" minimum="1"> <table style="width: 100%;"> - <f:entry title="${%URL}" help="/plugin/sitemonitor/url.html"> + <f:entry title="${%URL}"> <f:textbox name="url" value="${site.url}" checkUrl="'${rootURL}/publisher/SiteMonitorRecorder/checkUrl?value='+encode(this.value)"/> - <div style="text-align: right;"> - <input type="button" value="${%Delete}" class="repeatable-delete show-if-not-only"/> + </f:entry> + <f:advanced> + <f:entry title="${%Validate with regular expression}"> + <f:textbox name="regularExpression" value="${site.regularExpression}" checkUrl="'${rootURL}/publisher/SiteMonitorRecorder/checkRegex?value='+encode(this.value)"/> + </f:entry> + <f:entry title="${%Fail when Regular Expression is NOT found}"> + <f:checkbox name="failWhenRegexNotFound" field="failWhenRegexNotFound" default="true" /> + </f:entry> + </f:advanced> + <f:entry title=""> + <div align="right"> + <f:repeatableDeleteButton /> </div> </f:entry> <f:entry> diff --git a/src/main/webapp/url.html b/src/main/webapp/url.html index 52a2717..97bbc7c 100644 --- a/src/main/webapp/url.html +++ b/src/main/webapp/url.html @@ -1 +1,6 @@ -The URL address of the web site to be monitored. URL should start with http:// or https:// . \ No newline at end of file +Provides monitoring of one or more sites. Each site can be configured with +<ul> +<li>The URL address of the web site to be monitored. URL should start with http:// or https:// .</li> +<li>An optional Regular Expression to check for on the website's page.</li> +<li>A flag indicating whether to fail/succeed when the regular expression is found.</li> +</ul> \ No newline at end of file diff --git a/src/test/java/hudson/plugins/sitemonitor/model/SiteTest.java b/src/test/java/hudson/plugins/sitemonitor/model/SiteTest.java index ee9788d..d198e15 100644 --- a/src/test/java/hudson/plugins/sitemonitor/model/SiteTest.java +++ b/src/test/java/hudson/plugins/sitemonitor/model/SiteTest.java @@ -11,4 +11,16 @@ public void testGetUrlShouldGiveExpectedUrlValue() { site = new Site("http://hudson-ci.org"); assertEquals("http://hudson-ci.org", site.getUrl()); } + + public void testGetRegularExpressionShouldGiveExpectedUrlValue() { + site = new Site(null, "regex1", false); + assertEquals("regex1", site.getRegularExpression()); + assertEquals("regex1", site.getRegularExpressionPattern().pattern()); + } + + public void testGetRegularExpressionFlagShouldGiveExpectedUrlValue() { + site = new Site(null, null, false); + assertEquals(false, site.isFailWhenRegexNotFound()); + } + }