Implement possibility to specify a Single Rule from a Ruleset via http

This commit is contained in:
Andreas Dangel
2014-12-10 21:54:17 +01:00
parent a9e6d921dd
commit dd8c5f2d1a
4 changed files with 124 additions and 7 deletions

View File

@ -101,6 +101,11 @@
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View File

@ -4,16 +4,20 @@
package net.sourceforge.pmd;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import net.sourceforge.pmd.util.ResourceLoader;
import net.sourceforge.pmd.util.StringUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
/**
* This class is used to parse a RuleSet reference value. Most commonly used for specifying a
* RuleSet to process, or in a Rule 'ref' attribute value in the RuleSet XML. The RuleSet reference
@ -119,7 +123,13 @@ public class RuleSetReferenceId {
// Damn this parsing sucks, but my brain is just not working to let me
// write a simpler scheme.
if (isHttpUrl(id) || isFullRuleSetName(id)) {
if (isValidUrl(id)) {
// A full RuleSet name
external = true;
ruleSetFileName = StringUtils.strip(id);
allRules = true;
ruleName = null;
} else if (isFullRuleSetName(id)) {
// A full RuleSet name
external = true;
ruleSetFileName = id;
@ -130,7 +140,20 @@ public class RuleSetReferenceId {
String tempRuleSetFileName = tempRuleName != null && id != null ?
id.substring(0, id.length() - tempRuleName.length() - 1) : id;
if (isFullRuleSetName(tempRuleSetFileName)) {
if (isValidUrl(tempRuleSetFileName)) {
// remaining part is a xml ruleset file, so the tempRuleName is probably a real rule name
external = true;
ruleSetFileName = StringUtils.strip(tempRuleSetFileName);
ruleName = StringUtils.strip(tempRuleName);
allRules = tempRuleName == null;
} else if (isHttpUrl(id)) {
// it's a url, we can't determine whether it's a full ruleset or a single rule - so falling back to
// a full RuleSet name
external = true;
ruleSetFileName = StringUtils.strip(id);
allRules = true;
ruleName = null;
} else if (isFullRuleSetName(tempRuleSetFileName)) {
// remaining part is a xml ruleset file, so the tempRuleName is probably a real rule name
external = true;
ruleSetFileName = tempRuleSetFileName;
@ -256,6 +279,25 @@ public class RuleSetReferenceId {
return false;
}
private static boolean isValidUrl(String name) {
if (isHttpUrl(name)) {
String url = StringUtils.strip(name);
try {
HttpURLConnection connection = (HttpURLConnection)new URL(url).openConnection();
connection.setRequestMethod("HEAD");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
int responseCode = connection.getResponseCode();
if (responseCode == 200) {
return true;
}
} catch (IOException e) {
return false;
}
}
return false;
}
private static boolean isFullRuleSetName(String name) {

View File

@ -3,14 +3,28 @@
*/
package net.sourceforge.pmd;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.findAll;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.head;
import static com.github.tomakehurst.wiremock.client.WireMock.headRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.InputStream;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
public class RuleSetReferenceIdTest {
private static void assertRuleSetReferenceId(final boolean expectedExternal, final String expectedRuleSetFileName,
@ -83,12 +97,63 @@ public class RuleSetReferenceIdTest {
public void constructor_GivenHttpUrlId_SucceedsAndProcessesIdCorrectly() {
final String sonarRulesetUrlId =
" http://localhost:9000/profiles/export?format=pmd&language=java&name=Sonar%2520way ";
"http://localhost:54321/profiles/export?format=pmd&language=java&name=Sonar%2520way";
RuleSetReferenceId ruleSetReferenceId = new RuleSetReferenceId(sonarRulesetUrlId);
RuleSetReferenceId ruleSetReferenceId = new RuleSetReferenceId(" " + sonarRulesetUrlId + " ");
assertRuleSetReferenceId(true, sonarRulesetUrlId, true, null, sonarRulesetUrlId, ruleSetReferenceId);
}
@org.junit.Rule
public WireMockRule wireMockRule = new WireMockRule(0);
@Test
public void constructor_GivenHttpUrl_InputStream() throws Exception {
String path = "/profiles/export?format=pmd&language=java&name=Sonar%2520way";
String rulesetUrl = "http://localhost:" + wireMockRule.port() + path;
stubFor(head(urlEqualTo(path)).willReturn(aResponse().withStatus(200)));
stubFor(get(urlEqualTo(path)).willReturn(aResponse().withStatus(200).withHeader("Content-type", "text/xml").withBody("xyz")));
RuleSetReferenceId ruleSetReferenceId = new RuleSetReferenceId(" " + rulesetUrl + " ");
assertRuleSetReferenceId(true, rulesetUrl, true, null, rulesetUrl, ruleSetReferenceId);
InputStream inputStream = ruleSetReferenceId.getInputStream(RuleSetReferenceIdTest.class.getClassLoader());
String loaded = IOUtils.toString(inputStream, "UTF-8");
assertEquals("xyz", loaded);
verify(1, headRequestedFor(urlEqualTo(path)));
verify(0, headRequestedFor(urlEqualTo("/profiles")));
verify(1, getRequestedFor(urlEqualTo(path)));
assertEquals(1, findAll(headRequestedFor(urlMatching(".*"))).size());
assertEquals(1, findAll(getRequestedFor(urlMatching(".*"))).size());
}
@Test
public void constructor_GivenHttpUrl_SingleRule_InputStream() throws Exception {
String path = "/profiles/export?format=pmd&language=java&name=Sonar%2520way";
String completePath = path + "/DummyBasicMockRule";
String hostpart = "http://localhost:" + wireMockRule.port();
String basicRuleSet = IOUtils.toString(RuleSetReferenceId.class.getResourceAsStream("/rulesets/dummy/basic.xml"));
stubFor(head(urlEqualTo(completePath)).willReturn(aResponse().withStatus(404)));
stubFor(head(urlEqualTo(path)).willReturn(aResponse().withStatus(200).withHeader("Content-type", "text/xml")));
stubFor(get(urlEqualTo(path)).willReturn(aResponse().withStatus(200).withHeader("Content-type", "text/xml").withBody(basicRuleSet)));
RuleSetReferenceId ruleSetReferenceId = new RuleSetReferenceId(" " + hostpart + completePath + " ");
assertRuleSetReferenceId(true, hostpart + path, false, "DummyBasicMockRule", hostpart + completePath, ruleSetReferenceId);
InputStream inputStream = ruleSetReferenceId.getInputStream(RuleSetReferenceIdTest.class.getClassLoader());
String loaded = IOUtils.toString(inputStream, "UTF-8");
assertEquals(basicRuleSet, loaded);
verify(1, headRequestedFor(urlEqualTo(completePath)));
verify(1, headRequestedFor(urlEqualTo(path)));
verify(1, getRequestedFor(urlEqualTo(path)));
verify(0, getRequestedFor(urlEqualTo(completePath)));
assertEquals(2, findAll(headRequestedFor(urlMatching(".*"))).size());
assertEquals(1, findAll(getRequestedFor(urlMatching(".*"))).size());
}
@Test
public void testOneSimpleRuleSet() {

View File

@ -714,6 +714,11 @@
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>1.52</version>
</dependency>
</dependencies>
</dependencyManagement>