Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
3 changed files
with
170 additions
and
0 deletions.
There are no files selected for viewing
100 changes: 100 additions & 0 deletions
100
src/main/java/uk/org/iay/incommon/mda/validate/string/AsLiteralTailStringValidator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package uk.org.iay.incommon.mda.validate.string; | ||
|
||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
import javax.annotation.Nonnull; | ||
|
||
import net.shibboleth.metadata.validate.Validator; | ||
import uk.org.iay.incommon.mda.validate.BaseAsValidator; | ||
|
||
/** | ||
* A <code>Validator</code> that assists in the validation of regular-expression <shibmd:Scope> | ||
* values that include a literal tail. | ||
* | ||
* A literal tail is: | ||
* | ||
* <ul> | ||
* <li>a sequence of at least two domain labels</li> | ||
* <li>separated by literal <code>'.'</code> characters (encoded | ||
* in the regular expression as <code>'\.'</code></li> | ||
* <li>explicitly anchored at the end of the regular expression</li> | ||
* <li>preceded by anything terminating with an encoded literal <code>'.'</code> | ||
* </ul> | ||
* | ||
* <p>For example, the literal tail in the regular expression | ||
* <code>'^([a-zA-Z0-9-]{1,63}\.){0,2}ddd\.ccc\.bbb\.aa$'</code> is <code>'ccc.bbb.aa'</code>.</p> | ||
* | ||
* <p>The literal tail is extracted from the regular expression, has its encoded <code>'.'</code> | ||
* characters converted to normal ones, and then validated as a {@link String} by a new sequence of | ||
* validators.</p> | ||
* | ||
* <p>This validator fails (and returns {@link net.shibboleth.metadata.validate.Validator.Action#DONE}) if the | ||
* value does not possess a literal tail.</p> | ||
* | ||
* <p>Otherwise, the validator applies the sequence of validators to the new value and returns | ||
* the value of that sequence.</p> | ||
*/ | ||
public class AsLiteralTailStringValidator extends BaseAsValidator<String, String> | ||
implements Validator<String> { | ||
|
||
/** | ||
* Regular expression to match and extract the literal tail. | ||
* | ||
* The component parts of this expression are: | ||
* | ||
* <ul> | ||
* <li>implicitly, anchored at the start of the string being matched</li> | ||
* <li><code>.*?</code> matches non-greedily any text at the start of the regular expression, | ||
* maximising the size of the later parts of the match</li> | ||
* <li><code>\\\\.</code> matches <code>\.</code> in the regular expression, which in turn | ||
* matches a literal <code>.</code> in the scope</li> | ||
* <li>A group containing: | ||
* <ul> | ||
* <li>At least one DNS label terminated by a literal '.'</li> | ||
* <li>A final DNS label</li> | ||
* </ul> | ||
* </li> | ||
* <li><code>\\$</code> matches an end-string marker in the regular expression being matched</li> | ||
* <li>implicitly, anchored at the end of the string being matched</li> | ||
* </ul> | ||
* | ||
* <p>The matching of DNS labels is not exact. For example, labels starting or ending with hyphens | ||
* are accepted as part of a literal tail. This will normally be detected by the nested validator | ||
* sequence applied to the result.</p> | ||
* | ||
* <p>Similarly, upper-case characters are permitted in the literal tail although these would | ||
* not normally be permitted in scopes. Again, these characters are permitted so that a more | ||
* specific error can be reported, rather than just a generic failure to convert.</p> | ||
*/ | ||
private final Pattern pattern = Pattern.compile(".*?\\\\.(([a-zA-Z0-9-]+\\\\.)+[a-zA-Z0-9-]+)\\$"); | ||
|
||
@Override | ||
protected String convert(@Nonnull final String regex) throws IllegalArgumentException { | ||
// Match against the regular expression | ||
final Matcher matcher = pattern.matcher(regex); | ||
|
||
// If the pattern does not match, signal that the string does not have a literal tail | ||
if (!matcher.matches()) { | ||
throw new IllegalArgumentException(); | ||
} | ||
|
||
// Remove all '\' characters from the result. | ||
return matcher.group(1).replaceAll("\\\\", ""); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
src/test/java/uk/org/iay/incommon/mda/validate/string/AsLiteralTailStringValidatorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
|
||
package uk.org.iay.incommon.mda.validate.string; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
import org.testng.Assert; | ||
import org.testng.annotations.Test; | ||
|
||
import net.shibboleth.metadata.Item; | ||
import net.shibboleth.metadata.pipeline.StageProcessingException; | ||
import net.shibboleth.metadata.validate.Validator; | ||
import net.shibboleth.metadata.validate.Validator.Action; | ||
import uk.org.iay.incommon.mda.validate.BaseLocalValidator; | ||
import uk.org.ukfederation.mda.MockItem; | ||
|
||
public class AsLiteralTailStringValidatorTest { | ||
|
||
private static class CountingCapturingValidator extends BaseLocalValidator implements Validator<String> { | ||
public int count; | ||
public String value; | ||
private final Action action; | ||
|
||
@Override | ||
public Action validate(String e, Item<?> item, String stageId) throws StageProcessingException { | ||
count++; | ||
value = e; | ||
return action; | ||
} | ||
|
||
/** Constructor. */ | ||
public CountingCapturingValidator(final Action a) { | ||
action = a; | ||
} | ||
} | ||
|
||
@Test | ||
public void testAssumptions() throws Exception { | ||
final Pattern pattern = Pattern.compile(".*?\\\\.(([a-zA-Z0-9-]+\\\\.)+[a-zA-Z0-9-]+)\\$"); | ||
final String value = "^([a-zA-Z0-9-]{1,63}\\.){0,2}vho\\.aaf\\.edu\\.au$"; | ||
final Matcher matcher = pattern.matcher(value); | ||
Assert.assertTrue(matcher.matches()); | ||
} | ||
|
||
@Test | ||
public void testExample() throws Exception { | ||
final CountingCapturingValidator ccv = new CountingCapturingValidator(Action.CONTINUE); | ||
ccv.setId("ccv"); | ||
ccv.initialize(); | ||
|
||
final List<Validator<String>> nvs = new ArrayList<>(); | ||
nvs.add(ccv); | ||
|
||
final AsLiteralTailStringValidator val = new AsLiteralTailStringValidator(); | ||
val.setId("val"); | ||
val.setValidators(nvs); | ||
val.initialize(); | ||
|
||
final Item<String> item = new MockItem("content"); | ||
Assert.assertEquals(val.validate("^([a-zA-Z0-9-]{1,63}\\.){0,2}vho\\.aaf\\.edu\\.au$", item, "stage"), Action.CONTINUE); | ||
Assert.assertEquals(ccv.count, 1); | ||
Assert.assertEquals(ccv.value, "aaf.edu.au"); | ||
} | ||
|
||
} |