@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Thrown when one or more parameters fail bean validation constraints.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
public class ParameterValidationException extends RuntimeException {
|
||||
private final Set<ConstraintViolation<Object>> constraintViolations;
|
||||
private final MethodTarget methodTarget;
|
||||
|
||||
public ParameterValidationException(Set<ConstraintViolation<Object>> constraintViolations, MethodTarget methodTarget) {
|
||||
this.constraintViolations = constraintViolations;
|
||||
this.methodTarget = methodTarget;
|
||||
}
|
||||
|
||||
public Set<ConstraintViolation<Object>> getConstraintViolations() {
|
||||
return constraintViolations;
|
||||
}
|
||||
|
||||
public MethodTarget getMethodTarget() {
|
||||
return methodTarget;
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,9 @@ public class Shell implements CommandRegistry {
|
||||
*/
|
||||
protected static final Object UNRESOLVED = new Object();
|
||||
|
||||
private final ExecutableValidator executableValidator = Validation
|
||||
.buildDefaultValidatorFactory().getValidator().forExecutables();
|
||||
|
||||
public Shell(ResultHandler resultHandler) {
|
||||
this.resultHandler = resultHandler;
|
||||
}
|
||||
@@ -229,13 +232,13 @@ public class Shell implements CommandRegistry {
|
||||
throw new IllegalStateException("Could not resolve " + methodParameter);
|
||||
}
|
||||
}
|
||||
ExecutableValidator executableValidator = Validation
|
||||
.buildDefaultValidatorFactory().getValidator().forExecutables();
|
||||
Set<ConstraintViolation<Object>> constraintViolations = executableValidator.validateParameters(methodTarget.getBean(),
|
||||
Set<ConstraintViolation<Object>> constraintViolations = executableValidator.validateParameters(
|
||||
methodTarget.getBean(),
|
||||
methodTarget.getMethod(),
|
||||
args);
|
||||
args
|
||||
);
|
||||
if (constraintViolations.size() > 0) {
|
||||
System.out.println(constraintViolations);
|
||||
throw new ParameterValidationException(constraintViolations, methodTarget);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.result;
|
||||
|
||||
import org.jline.utils.AttributedString;
|
||||
import org.jline.utils.AttributedStringBuilder;
|
||||
import org.jline.utils.AttributedStyle;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.shell.ParameterDescription;
|
||||
import org.springframework.shell.ParameterResolver;
|
||||
import org.springframework.shell.ParameterValidationException;
|
||||
import org.springframework.shell.Utils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.validation.ElementKind;
|
||||
import javax.validation.Path;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
* Displays validation errors on the terminal.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
@Component
|
||||
public class ParameterValidationExceptionResultHandler
|
||||
extends TerminalAwareResultHandler<ParameterValidationException> {
|
||||
|
||||
@Autowired
|
||||
private List<ParameterResolver> parameterResolvers;
|
||||
|
||||
@Override
|
||||
protected void doHandleResult(ParameterValidationException result) {
|
||||
terminal.writer().println(new AttributedString("The following constraints were not met:",
|
||||
AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)).toAnsi());
|
||||
result.getConstraintViolations().stream()
|
||||
.forEach(v -> {
|
||||
Optional<Integer> parameterIndex = StreamSupport.stream(v.getPropertyPath().spliterator(), false)
|
||||
.filter(n -> n.getKind() == ElementKind.PARAMETER)
|
||||
.map(n -> ((Path.ParameterNode) n).getParameterIndex())
|
||||
.findFirst();
|
||||
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(result.getMethodTarget().getMethod(),
|
||||
parameterIndex.get());
|
||||
List<ParameterDescription> descriptions = findParameterResolver(methodParameter)
|
||||
.describe(methodParameter).collect(Collectors.toList());
|
||||
if (descriptions.size() == 1) {
|
||||
ParameterDescription description = descriptions.get(0);
|
||||
AttributedStringBuilder ansi = new AttributedStringBuilder(100);
|
||||
ansi.append("\t").append(description.keys().get(0), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED).bold());
|
||||
ansi.append(" ").append(description.formal(), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED).underline());
|
||||
String msg = String.format(" : %s (You passed '%s')",
|
||||
v.getMessage(),
|
||||
String.valueOf(v.getInvalidValue())
|
||||
);
|
||||
ansi.append(msg, AttributedStyle.DEFAULT.foreground(AttributedStyle.RED));
|
||||
|
||||
terminal.writer().println(ansi.toAnsi(terminal));
|
||||
}
|
||||
// Several formals for one method param, must be framework like JCommander, etc
|
||||
else {
|
||||
// Output toString() for now...
|
||||
terminal.writer().println(new AttributedString(v.toString(),
|
||||
AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)).toAnsi(terminal));
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private ParameterResolver findParameterResolver(MethodParameter methodParameter) {
|
||||
return parameterResolvers.stream().filter(pr -> pr.supports(methodParameter)).findFirst().get();
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@ import java.util.List;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
|
||||
/**
|
||||
* An example straight from the JCommander documentation.
|
||||
*
|
||||
@@ -31,6 +33,7 @@ public class Args {
|
||||
@Parameter
|
||||
private List<String> parameters = new ArrayList<>();
|
||||
|
||||
@Min(3)
|
||||
@Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity")
|
||||
private Integer verbose = 1;
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ import org.springframework.shell.standard.ShellComponent;
|
||||
import org.springframework.shell.standard.ShellMethod;
|
||||
import org.springframework.shell.standard.ShellOption;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* A class with JCommander commands.
|
||||
*
|
||||
@@ -29,7 +31,7 @@ import org.springframework.shell.standard.ShellOption;
|
||||
public class JCommanderCommands {
|
||||
|
||||
@ShellMethod("Bind parameters to JCommander POJO.")
|
||||
public String jcommander(@ShellOption(optOut = true) Args args) {
|
||||
public String jcommander(@ShellOption(optOut = true) @Valid Args args) {
|
||||
return "You said " + args;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import org.springframework.shell.standard.ShellOption;
|
||||
import org.springframework.shell.standard.ValueProviderSupport;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* Example commands for the Shell 2 Standard resolver.
|
||||
*
|
||||
@@ -44,7 +46,7 @@ public class Commands {
|
||||
}
|
||||
|
||||
@ShellMethod("It's cool.")
|
||||
public String foo(String bar) {
|
||||
public String foo(@Size(min = 2) String bar) {
|
||||
return bar;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user