diff --git a/.checkstyle b/.checkstyle index a18c2f7..cb63279 100644 --- a/.checkstyle +++ b/.checkstyle @@ -6,5 +6,6 @@ + diff --git a/.springBeans b/.springBeans new file mode 100644 index 0000000..345f3c0 --- /dev/null +++ b/.springBeans @@ -0,0 +1,15 @@ + + + 1 + + + + + + + + + + + + diff --git a/src/main/java/uk/org/iay/incommon/validator/api/ApiException.java b/src/main/java/uk/org/iay/incommon/validator/api/ApiException.java new file mode 100644 index 0000000..9dd1415 --- /dev/null +++ b/src/main/java/uk/org/iay/incommon/validator/api/ApiException.java @@ -0,0 +1,73 @@ +/* + * 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.validator.api; + +import java.util.HashMap; +import java.util.Map; + +import org.joda.time.DateTime; +import org.springframework.http.HttpStatus; + +/** + * Exception class for use within the API. + */ +public class ApiException extends Exception { + + /** Serial version UID. */ + private static final long serialVersionUID = -5046975083822313941L; + + /** HTTP Status to be reported by this exception. */ + private final HttpStatus status; + + /** When the exception was created. */ + private final DateTime when; + + /** + * Constructor. + * + * @param stat HTTP status + * @param msg message + */ + public ApiException(final HttpStatus stat, final String msg) { + super(msg); + status = stat; + when = DateTime.now(); + } + + /** + * Reuturns the wrapped {@link HttpStatus} value. + * + * @return an {@link HttpStatus} + */ + public HttpStatus getStatus() { + return status; + } + + /** + * Convert to a {@link Map} so that the data can be turned into + * a JSON response. + * + * @return a new {@link Map} containing the exception information + */ + public Map toMap() { + final Map m = new HashMap<>(); + m.put("status", Integer.valueOf(getStatus().value())); + m.put("error", getStatus().getReasonPhrase()); + m.put("message", getMessage()); + m.put("exception", getClass().getName()); + m.put("timestamp", when); + return m; + } +} diff --git a/src/main/java/uk/org/iay/incommon/validator/api/NotFoundException.java b/src/main/java/uk/org/iay/incommon/validator/api/NotFoundException.java new file mode 100644 index 0000000..5721300 --- /dev/null +++ b/src/main/java/uk/org/iay/incommon/validator/api/NotFoundException.java @@ -0,0 +1,36 @@ +/* + * 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.validator.api; + +import org.springframework.http.HttpStatus; + +/** + * {@link ApiException} representing a "not found" condition. + */ +public class NotFoundException extends ApiException { + + /** Serial version UID. */ + private static final long serialVersionUID = 424520235843161978L; + + /** + * Constructor. + * + * @param msg message to be included in the exception + */ + public NotFoundException(final String msg) { + super(HttpStatus.NOT_FOUND, msg); + } + +} diff --git a/src/main/java/uk/org/iay/incommon/validator/api/ValidatorsApi.java b/src/main/java/uk/org/iay/incommon/validator/api/ValidatorsApi.java new file mode 100644 index 0000000..c6c9f8c --- /dev/null +++ b/src/main/java/uk/org/iay/incommon/validator/api/ValidatorsApi.java @@ -0,0 +1,52 @@ +/** + * NOTE: This class is auto generated by the swagger code generator program (2.3.1). + * https://github.com/swagger-api/swagger-codegen + * Do not edit the class manually. + * + * **IAY**: The only changes here from the generated file have been to clean up the imports + * list and to add "throws ApiException" to the validate method. + */ +package uk.org.iay.incommon.validator.api; + +import java.util.List; + +import javax.validation.Valid; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import uk.org.iay.incommon.validator.models.Status; +import uk.org.iay.incommon.validator.models.Validator; +@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-05-12T13:33:10.546+01:00") + +@Api(value = "validators", description = "the validators API") +public interface ValidatorsApi { + + @ApiOperation(value = "lists available validators", nickname = "getValidators", notes = "Lists all of the available validator pipelines. ", response = Validator.class, responseContainer = "List", tags={ "validation", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "list of validator identifiers and descriptions", response = Validator.class, responseContainer = "List") }) + @RequestMapping(value = "/validators", + produces = { "application/json" }, + method = RequestMethod.GET) + ResponseEntity> getValidators(); + + + @ApiOperation(value = "performs a validation", nickname = "validate", notes = "", response = Status.class, responseContainer = "List", tags={ "validation", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "The result of a validation operation is a (possibly empty) array of `Status` objects derived from the `StatusMetadata` instances attached to the item being validated. These may include errors, and it is up to the client to determine what constitues a \"pass\" or \"fail\". ", response = Status.class, responseContainer = "List") }) + @RequestMapping(value = "/validators/{validator_id}/validate", + produces = { "application/json" }, + consumes = { "application/xml+samlmetadata" }, + method = RequestMethod.POST) + ResponseEntity> validate(@ApiParam(value = "An identifier for the validation to be performed. ",required=true) @PathVariable("validator_id") String validatorId,@ApiParam(value = "The metadata to be validated." ,required=true ) @Valid @RequestBody String metadata) + throws ApiException; + +} diff --git a/src/main/java/uk/org/iay/incommon/validator/api/ValidatorsApiController.java b/src/main/java/uk/org/iay/incommon/validator/api/ValidatorsApiController.java index 7dc604b..8d93967 100644 --- a/src/main/java/uk/org/iay/incommon/validator/api/ValidatorsApiController.java +++ b/src/main/java/uk/org/iay/incommon/validator/api/ValidatorsApiController.java @@ -16,7 +16,9 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import org.slf4j.Logger; @@ -25,6 +27,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -88,10 +91,26 @@ public ResponseEntity> validate( @PathVariable("validator_id") final String validatorId, @ApiParam(value = "The metadata to be validated.", required = true) @Valid @RequestBody - final String metadata) { + final String metadata) throws ApiException { final List statuses = new ArrayList<>(); statuses.add(makeStatus(StatusEnum.ERROR, "component", "message")); statuses.add(makeStatus(StatusEnum.WARNING, "component/sub", "another message")); - return new ResponseEntity>(statuses, HttpStatus.NOT_IMPLEMENTED); + //return new ResponseEntity>(statuses, HttpStatus.NOT_IMPLEMENTED); + throw new NotFoundException("bad validator identifier '" + validatorId + "'"); + } + + /** + * Handle an {@link ApiException} by converting it to a {@link Map}, which will + * in turn be converted to a JSON object. + * + * @param req the {@link HttpServletRequest} being handled + * @param ex the {@link ApiException} being handled + * @return a {@link ResponseEntity} equivalent to the {@link ApiException} + */ + @ExceptionHandler(ApiException.class) + public ResponseEntity> handleApiException(final HttpServletRequest req, final ApiException ex) { + final Map m = ex.toMap(); + m.put("path", req.getRequestURI()); + return new ResponseEntity<>(m, ex.getStatus()); } } diff --git a/swagger/.swagger-codegen-ignore b/swagger/.swagger-codegen-ignore index eb01be8..3b97bfc 100644 --- a/swagger/.swagger-codegen-ignore +++ b/swagger/.swagger-codegen-ignore @@ -15,3 +15,14 @@ README.md # Don't generate dummy controllers once we have implemented them. # **/ValidatorsApiController.java + +# +# Turns out we need to make changes to the API classes as well, to +# allow for exceptions. +# +**/ValidatorsApi.java + +# +# In turn, that means we don't need to generate the exception classes. +# +**/*Exception.java