Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add AsDomainNameStringValidator and BaseAsValidator
iay committed Oct 10, 2017
1 parent b2824d7 commit 8525aa8
Showing 5 changed files with 307 additions and 0 deletions.
4 changes: 4 additions & 0 deletions pom.xml
@@ -35,6 +35,10 @@
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>net.shibboleth.metadata</groupId>
<artifactId>aggregator-pipeline</artifactId>
150 changes: 150 additions & 0 deletions src/main/java/uk/org/iay/incommon/mda/validate/BaseAsValidator.java
@@ -0,0 +1,150 @@
/*
* 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;

import java.util.List;

import javax.annotation.Nonnull;

import net.shibboleth.metadata.Item;
import net.shibboleth.metadata.pipeline.StageProcessingException;
import net.shibboleth.metadata.validate.Validator;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;

/**
* An abstract base class for {@link Validator} implementations which validate a value of
* one type "as" another type.
*
* <p>The implementation calls a template method in the implementation subclass to perform the
* conversion. If the conversion succeeds, a sequence of {@link Validator}s are applied to
* that new value.</p>
*
* <p>If the value cannot be converted to the new type, the template method is expected to
* throw {@link IllegalArgumentException}. In this case, behaviour depends on the
* {@link #conversionRequired} property.</p>
*
* <p>If {@link #conversionRequired} is <code>true</code> (the default) then an error
* status will be applied to the {@link Item}, and the validator will return
* {@link net.shibboleth.metadata.validate.Validator.Action#DONE}.</p>
*
* <p>If {@link #conversionRequired} is <code>false</code> then the validator
* will simply return {@link net.shibboleth.metadata.validate.Validator.Action#CONTINUE}
* so that subsequent validators may still be applied. This allows several "as" validators
* to be applied in sequence, each taking a different approach.</p>
*
* @param <V> type of the original value
* @param <A> type of the new value to which validators should be applied
*/
public abstract class BaseAsValidator<V, A> extends BaseLocalValidator implements Validator<V> {

/** The validator sequence to apply. */
@Nonnull
private ValidatorSequence<A> validators = new ValidatorSequence<>();

/** Whether conversion to the new type must succeed. Default: <code>true</code> */
private boolean conversionRequired = true;

/**
* Set the list of validators to apply to each item.
*
* @param newValidators the list of validators to set
*/
public void setValidators(@Nonnull final List<Validator<A>> newValidators) {
validators.setValidators(newValidators);
}

/**
* Gets the list of validators being applied to each item.
*
* @return list of validators
*/
@Nonnull
public List<Validator<A>> getValidators() {
return validators.getValidators();
}

/**
* Set whether conversion to the new type is required to succeed.
*
* @param required <code>true</code> if the conversion is required to succeed
*/
public void setConversionRequired(final boolean required) {
conversionRequired = required;
}

/**
* Returns whether conversion to the new type is required to succeed.
*
* @return <code>true</code> if the conversion is required to succeed
*/
public boolean isConversionRequired() {
return conversionRequired;
}

/**
* Apply each of the configured validators in turn to the provided object.
*
* @param value object to be validated
* @param item the {@link Item} context for the validation
*
* @return the result of applying the validators to the value
*
* @throws StageProcessingException if errors occur during processing
*/
protected Action applyValidators(@Nonnull final A value, @Nonnull final Item<?> item)
throws StageProcessingException {
return validators.validate(value, item, getId());
}

/**
* Convert from the old value type to the new.
*
* @param from a value of the old type
* @return a value of the new type
* @throws IllegalArgumentException if a conversion can not be performed
*/
protected abstract A convert(@Nonnull final V from) throws IllegalArgumentException;

@Override
public Action validate(@Nonnull final V t, @Nonnull final Item<?> item, @Nonnull final String stageId)
throws StageProcessingException {
try {
final A v = convert(t);
return applyValidators(v, item);
} catch (final IllegalArgumentException e) {
if (isConversionRequired()) {
addErrorMessage(t, item, stageId);
return Action.DONE;
} else {
return Action.CONTINUE;
}
}
}

@Override
protected void doDestroy() {
validators.destroy();
validators = null;
super.doDestroy();
}

@Override
protected void doInitialize() throws ComponentInitializationException {
super.doInitialize();
validators.setId(getId());
validators.initialize();
}

}
@@ -0,0 +1,42 @@
/*
* 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 javax.annotation.Nonnull;

import com.google.common.net.InternetDomainName;

import net.shibboleth.metadata.validate.Validator;
import uk.org.iay.incommon.mda.validate.BaseAsValidator;

/**
* A <code>Validator</code> that checks {@link String} values as domain names by converting the
* value to an {@link InternetDomainName} and applying a sequence of validators to that value.
*
* This validator fails (and returns {@link net.shibboleth.metadata.validate.Validator.Action#DONE}) if the
* value can not be converted to an {@link InternetDomainName}.
*
* Otherwise, the validator applies the sequence of validators to the {@link InternetDomainName} and returns
* the value of that sequence.
*/
public class AsDomainNameStringValidator extends BaseAsValidator<String, InternetDomainName>
implements Validator<String> {

@Override
protected InternetDomainName convert(@Nonnull final String domain) throws IllegalArgumentException {
return InternetDomainName.from(domain);
}

}
3 changes: 3 additions & 0 deletions src/main/resources/uk/org/iay/incommon/mda/beans.xml
@@ -44,6 +44,9 @@
<bean id="inc.AcceptStringValueValidator" abstract="true" parent="inc.component_parent"
class="uk.org.iay.incommon.mda.validate.string.AcceptStringValueValidator"/>

<bean id="inc.AsDomainNameStringValidator" abstract="true" parent="inc.component_parent"
class="uk.org.iay.incommon.mda.validate.string.AsDomainNameStringValidator"/>

<bean id="inc.RejectAllValidator" abstract="true" parent="inc.component_parent"
class="uk.org.iay.incommon.mda.validate.RejectAllValidator"/>

@@ -0,0 +1,108 @@

package uk.org.iay.incommon.mda.validate.string;

import java.util.ArrayList;
import java.util.List;

import org.testng.Assert;
import org.testng.annotations.Test;

import com.google.common.net.InternetDomainName;

import net.shibboleth.metadata.ErrorStatus;
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 AsDomainNameStringValidatorTest {

private static class CountingValidator extends BaseLocalValidator implements Validator<InternetDomainName> {
public int count;
private final Action action;

@Override
public Action validate(InternetDomainName e, Item<?> item, String stageId) throws StageProcessingException {
count++;
return action;
}

/** Constructor. */
public CountingValidator(final Action a) {
action = a;
}
}

@Test
public void testOK() throws Exception {
final CountingValidator counter = new CountingValidator(Action.CONTINUE);
counter.setId("counter");
counter.initialize();

final List<Validator<InternetDomainName>> nestedSequence = new ArrayList<>();
nestedSequence.add(counter);

final Item<String> item = new MockItem("content");

final AsDomainNameStringValidator val = new AsDomainNameStringValidator();
val.setId("id");
val.setValidators(nestedSequence);
val.initialize();

final Action res = val.validate("example.org", item, "stage");
Assert.assertEquals(res, Action.CONTINUE);
Assert.assertEquals(item.getItemMetadata().get(ErrorStatus.class).size(), 0);
Assert.assertEquals(counter.count, 1);
}

@Test
public void testNoConvertDefault() throws Exception {
final CountingValidator counter = new CountingValidator(Action.CONTINUE);
counter.setId("counter");
counter.initialize();

final List<Validator<InternetDomainName>> nestedSequence = new ArrayList<>();
nestedSequence.add(counter);

final Item<String> item = new MockItem("content");

final AsDomainNameStringValidator val = new AsDomainNameStringValidator();
val.setId("id");
val.setValidators(nestedSequence);
val.setMessage("quick brown %s");
val.initialize();

final Action res = val.validate("example**.org", item, "stage");
Assert.assertEquals(res, Action.DONE);
Assert.assertEquals(item.getItemMetadata().get(ErrorStatus.class).size(), 1);
final ErrorStatus err = item.getItemMetadata().get(ErrorStatus.class).get(0);
Assert.assertTrue(err.getStatusMessage().contains("quick brown example**.org"));
Assert.assertEquals(counter.count, 0);
}

@Test
public void testNoConvertFalse() throws Exception {
final CountingValidator counter = new CountingValidator(Action.CONTINUE);
counter.setId("counter");
counter.initialize();

final List<Validator<InternetDomainName>> nestedSequence = new ArrayList<>();
nestedSequence.add(counter);

final Item<String> item = new MockItem("content");

final AsDomainNameStringValidator val = new AsDomainNameStringValidator();
val.setId("id");
val.setConversionRequired(false);
val.setValidators(nestedSequence);
val.initialize();

final Action res = val.validate("example**.org", item, "stage");
Assert.assertEquals(res, Action.CONTINUE);
Assert.assertEquals(item.getItemMetadata().get(ErrorStatus.class).size(), 0);
Assert.assertEquals(counter.count, 0);
}

}

0 comments on commit 8525aa8

Please sign in to comment.