From 381fdf60e33d859e4711f7cdec1530b0591d231a Mon Sep 17 00:00:00 2001 From: Carl Wilson Date: Mon, 29 Jan 2024 09:24:33 +0000 Subject: [PATCH 1/6] DOC: Improve REST method documentation - fixed `@Schema` annotations for correct return types; - improved documentation of methods; and - added return examples where appropriate. TODO: Fix the validation method documentation, which requires some refactoring. --- src/main/java/org/verapdf/rest/resources/ProfileResource.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/verapdf/rest/resources/ProfileResource.java b/src/main/java/org/verapdf/rest/resources/ProfileResource.java index 2437775..bd560ea 100644 --- a/src/main/java/org/verapdf/rest/resources/ProfileResource.java +++ b/src/main/java/org/verapdf/rest/resources/ProfileResource.java @@ -92,7 +92,7 @@ public static Set getFlavours() { /** * @param profileId * the String id of the Validation profile (1b, 1a, 2b, 2a, 2u, - * 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2) + * 3b, 3a, 3u, 4, 4e, 4f or ua1) * @return a validation profile selected by id */ @GET @@ -136,7 +136,7 @@ public static ValidationProfile getProfile( public static Set getProfileRules( @Parameter(description = "The String id of the Validation profile that the rule IDs should be retrieved from, " + - "(1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2") @PathParam("profileId") String profileId) { + "(1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f or ua1") @PathParam("profileId") String profileId) { SortedSet ids = new TreeSet<>(new Profiles.RuleIdComparator()); for (Rule rule : DIRECTORY.getValidationProfileById(profileId).getRules()) { ids.add(rule.getRuleId()); From 2c59902f765946eabae3445f4e1164812f772155 Mon Sep 17 00:00:00 2001 From: Carl Wilson Date: Wed, 31 Jan 2024 07:12:42 +0000 Subject: [PATCH 2/6] FIX: Review comments. --- src/main/java/org/verapdf/rest/resources/ProfileResource.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/verapdf/rest/resources/ProfileResource.java b/src/main/java/org/verapdf/rest/resources/ProfileResource.java index bd560ea..2437775 100644 --- a/src/main/java/org/verapdf/rest/resources/ProfileResource.java +++ b/src/main/java/org/verapdf/rest/resources/ProfileResource.java @@ -92,7 +92,7 @@ public static Set getFlavours() { /** * @param profileId * the String id of the Validation profile (1b, 1a, 2b, 2a, 2u, - * 3b, 3a, 3u, 4, 4e, 4f or ua1) + * 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2) * @return a validation profile selected by id */ @GET @@ -136,7 +136,7 @@ public static ValidationProfile getProfile( public static Set getProfileRules( @Parameter(description = "The String id of the Validation profile that the rule IDs should be retrieved from, " + - "(1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f or ua1") @PathParam("profileId") String profileId) { + "(1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2") @PathParam("profileId") String profileId) { SortedSet ids = new TreeSet<>(new Profiles.RuleIdComparator()); for (Rule rule : DIRECTORY.getValidationProfileById(profileId).getRules()) { ids.add(rule.getRuleId()); From 50dfa31ade37eb80e2c7abbd75912964dc65c3da Mon Sep 17 00:00:00 2001 From: Carl Wilson Date: Wed, 31 Jan 2024 16:29:58 +0000 Subject: [PATCH 3/6] REFACT: Consolidate validation methods - combined all sha/profile validation methods into a single method with appropriate content type negotiation; - `sha1` parameter is now optional to allow for non-sha calling for consolidation; and - added `beforesend` event to allow for custom headers to be added to the request. --- .../rest/resources/ValidateResource.java | 632 +++++++----------- src/main/resources/assets/js/vera.results.js | 6 +- 2 files changed, 250 insertions(+), 388 deletions(-) diff --git a/src/main/java/org/verapdf/rest/resources/ValidateResource.java b/src/main/java/org/verapdf/rest/resources/ValidateResource.java index 6aad3fc..27062eb 100644 --- a/src/main/java/org/verapdf/rest/resources/ValidateResource.java +++ b/src/main/java/org/verapdf/rest/resources/ValidateResource.java @@ -3,13 +3,30 @@ */ package org.verapdf.rest.resources; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.enums.ParameterStyle; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.security.DigestInputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.text.Format; + +import javax.ws.rs.BadRequestException; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + import org.apache.commons.codec.binary.Hex; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; @@ -31,410 +48,251 @@ import org.verapdf.processor.reports.BatchSummary; import org.verapdf.processor.reports.ItemDetails; -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import java.io.*; -import java.net.URL; -import java.security.DigestInputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterStyle; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; /** * @author Carl Wilson */ public class ValidateResource { - // java.security.digest name for the SHA-1 algorithm - private static final String SHA1_NAME = "SHA-1"; //$NON-NLS-1$ - private static final String FILE_SIZE_HEADER = "X-File-Size"; - private static final int CONVERTER_MB_TO_B = 1_048_576; - private static int maxFileSize; - private static final String MAX_ALLOWED_FILE_SIZE = "Maximum allowed file size exceeded: %d MB"; - - private static ConfigManager configManager; - - static { - VeraGreenfieldFoundryProvider.initialise(); - File root = new File(""); - configManager = ConfigManagerImpl.create(new File(root.getAbsolutePath() + "/config")); - } - - @GET - @Path("/details") - @Operation(summary = "Get component details") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", content = { - @Content(mediaType = "application/json", schema = - @Schema(implementation = ComponentDetails.class) - ), @Content(mediaType = "application/xml", schema = - @Schema(implementation = ComponentDetails.class) - )})}) - @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) - public static ComponentDetails getDetails() { - return Foundries.defaultInstance().getDetails(); - } - - /** - * @param profileId - * the String id of the Validation profile - * (auto, 1b, 1a, 2b, 2a, 2u, - * 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2) - * @param uploadedInputStream - * a {@link java.io.InputStream} to the PDF to - * be validated - * @param contentDispositionHeader - * @return the {@link org.verapdf.pdfa.results.ValidationResult} obtained - * when validating the uploaded stream against the selected profile. - */ - @POST - @Path("/{profileId}") - @Operation(summary = "Validate the uploaded stream against the selected profile and return validation result") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", content = { - @Content(mediaType = "application/xml", schema = - @Schema(implementation = InputStream.class)), - @Content(mediaType = "application/json", schema = - @Schema(implementation = InputStream.class)), - @Content(mediaType = "text/html", schema = - @Schema(implementation = InputStream.class) - )})}) - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({MediaType.APPLICATION_XML}) - public static InputStream validateXml(@Parameter(description = "the String id of the Validation profile " + - "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") - @PathParam("profileId") String profileId, - @Parameter(name = "file", schema = @Schema(implementation = File.class), - style = ParameterStyle.FORM, description = "an InputStream of the PDF to be validated") - @FormDataParam("file") InputStream uploadedInputStream, - @Parameter(hidden = true) @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") - @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { - return validateFile(uploadedInputStream, contentDispositionHeader, profileId, null, FormatOption.XML, fileSize); - } - - /** - * @param profileId - * the String id of the Validation profile - * (auto, 1b, 1a, 2b, 2a, 2u, - * 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2) - * @param sha1Hex - * the hex String representation of the file's - * SHA-1 hash - * @param uploadedInputStream - * a {@link java.io.InputStream} to the PDF to - * be validated - * @param contentDispositionHeader - * @return the {@link org.verapdf.pdfa.results.ValidationResult} obtained - * when validating the uploaded stream against the selected profile. - */ - @POST - @Path("/sha/{profileId}") - @Operation(summary = "Validate the uploaded stream against the selected profile and return validation result") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", content = { - @Content(mediaType = "application/xml", schema = - @Schema(implementation = InputStream.class)), - @Content(mediaType = "application/json", schema = - @Schema(implementation = InputStream.class)), - @Content(mediaType = "text/html", schema = - @Schema(implementation = InputStream.class) - )})}) - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({MediaType.APPLICATION_XML}) - public static InputStream validateXml(@Parameter(description = "the String id of the Validation profile " + - "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") - @PathParam("profileId") String profileId, - @Parameter(description = "the hex String representation of the file's SHA-1 hash") - @FormDataParam("sha1Hex") String sha1Hex, - @Parameter(name = "file", schema = @Schema(implementation = File.class), - style = ParameterStyle.FORM, description = "an InputStream of the PDF to be validated") - @FormDataParam("file") InputStream uploadedInputStream, - @Parameter(hidden = true) @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") - @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { - return validateFile(uploadedInputStream, contentDispositionHeader, profileId, sha1Hex, FormatOption.XML, fileSize); - } + // java.security.digest name for the SHA-1 algorithm + private static final String SHA1_NAME = "SHA-1"; //$NON-NLS-1$ + private static final String FILE_SIZE_HEADER = "X-File-Size"; + private static final int CONVERTER_MB_TO_B = 1_048_576; + private static int maxFileSize; + private static final String MAX_ALLOWED_FILE_SIZE = "Maximum allowed file size exceeded: %d MB"; - @POST - @Path("/url/{profileId}") - @Operation(summary = "Validate PDF given by URL against the selected profile and return validation result") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", content = { - @Content(mediaType = "application/xml", schema = - @Schema(implementation = InputStream.class)), - @Content(mediaType = "application/json", schema = - @Schema(implementation = InputStream.class)), - @Content(mediaType = "text/html", schema = - @Schema(implementation = InputStream.class) - )})}) - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({MediaType.APPLICATION_XML}) - public static InputStream validateXml(@Parameter(description = "the String id of the Validation profile " + - "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") - @PathParam("profileId") String profileId, - @Parameter(description = "a URL of PDF to be validated") - @FormDataParam("url") String urlLink, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") - @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { - return validateUrl(urlLink, profileId, FormatOption.XML, fileSize); - } + private static final ConfigManager configManager; - /** - * @param profileId - * the String id of the Validation profile - * (auto, 1b, 1a, 2b, 2a, 2u, - * 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2) - * @param uploadedInputStream - * a {@link java.io.InputStream} to the PDF to - * be validated - * @param contentDispositionHeader - * @return the {@link org.verapdf.pdfa.results.ValidationResult} obtained - * when validating the uploaded stream against the selected profile. - */ - @POST - @Path("/{profileId}") - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({MediaType.APPLICATION_JSON}) - public static InputStream validateJson(@Parameter(description = "the String id of the Validation profile " + - "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") - @PathParam("profileId") String profileId, - @Parameter(name = "file", schema = @Schema(implementation = File.class), - style = ParameterStyle.FORM, description = "an InputStream of the PDF to be validated") - @FormDataParam("file") InputStream uploadedInputStream, - @Parameter(hidden = true) @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") - @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { - return validateFile(uploadedInputStream, contentDispositionHeader, profileId, null, FormatOption.JSON, fileSize); - } + static { + VeraGreenfieldFoundryProvider.initialise(); + File root = new File(""); + configManager = ConfigManagerImpl.create(new File(root.getAbsolutePath() + "/config")); + } - /** - * @param profileId - * the String id of the Validation profile - * (auto, 1b, 1a, 2b, 2a, 2u, - * 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2) - * @param sha1Hex - * the hex String representation of the file's - * SHA-1 hash - * @param uploadedInputStream - * a {@link java.io.InputStream} to the PDF to - * be validated - * @param contentDispositionHeader - * @return the {@link org.verapdf.pdfa.results.ValidationResult} obtained - * when validating the uploaded stream against the selected profile. - */ - @POST - @Path("/sha/{profileId}") - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({MediaType.APPLICATION_JSON}) - public static InputStream validateJson(@Parameter(description = "the String id of the Validation profile " + - "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") - @PathParam("profileId") String profileId, - @Parameter(description = "the hex String representation of the file's SHA-1 hash") - @FormDataParam("sha1Hex") String sha1Hex, - @Parameter(name = "file", schema = @Schema(implementation = File.class), - style = ParameterStyle.FORM, description = "an InputStream of the PDF to be validated") - @FormDataParam("file") InputStream uploadedInputStream, - @Parameter(hidden = true) @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") - @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { + @GET + @Path("/details") + @Operation(summary = "Get component details") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = { + @Content(mediaType = "application/json", schema = @Schema(implementation = ComponentDetails.class)), + @Content(mediaType = "application/xml", schema = @Schema(implementation = ComponentDetails.class)) }) }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public static ComponentDetails getDetails() { + return Foundries.defaultInstance().getDetails(); + } - return validateFile(uploadedInputStream, contentDispositionHeader, profileId, sha1Hex, FormatOption.JSON, fileSize); - } + /** + * @param profileId + * the String id of the Validation profile + * (auto, 1b, 1a, 2b, 2a, 2u, + * 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2) + * @param sha1Hex + * the hex String representation of the file's + * SHA-1 hash + * @param uploadedInputStream + * a {@link java.io.InputStream} to the PDF to + * be validated + * @param contentDispositionHeader + * @return the {@link org.verapdf.pdfa.results.ValidationResult} obtained + * when validating the uploaded stream against the selected profile. + */ + @POST + @Path("/{profileId}") + @Operation(summary = "Validate the uploaded stream against the selected profile and return validation result") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = { + @Content(mediaType = "application/xml", schema = @Schema(implementation = InputStream.class)), + @Content(mediaType = "application/json", schema = @Schema(implementation = InputStream.class)), + @Content(mediaType = "text/html", schema = @Schema(implementation = InputStream.class)) }) }) + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML }) + public static Response validateXml(@Parameter(description = "the String id of the Validation profile " + + "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") @PathParam("profileId") String profileId, + @Parameter(description = "the hex String representation of the file's SHA-1 hash", required = false, allowEmptyValue = true) @FormDataParam("sha1Hex") String sha1Hex, + @Parameter(name = "file", schema = @Schema(implementation = File.class), style = ParameterStyle.FORM, description = "an InputStream of the PDF to be validated") @FormDataParam("file") InputStream uploadedInputStream, + @Parameter(hidden = true) @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader, + @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") @HeaderParam(FILE_SIZE_HEADER) Integer fileSize, + @HeaderParam("Accept") String accepts) { + FormatOption formatOption = formatOptionFromAccepts(accepts); + return Response + .ok(validateFile(uploadedInputStream, contentDispositionHeader, profileId, sha1Hex, formatOption, + fileSize), accepts) + .build(); + } - @POST - @Path("/url/{profileId}") - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({MediaType.APPLICATION_JSON}) - public static InputStream validateJson(@Parameter(description = "the String id of the Validation profile " + - "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") - @PathParam("profileId") String profileId, - @Parameter(description = "a URL of PDF to be validated") - @FormDataParam("url") String urlLink, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") - @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { - return validateUrl(urlLink, profileId, FormatOption.JSON, fileSize); - } + @POST + @Path("/url/{profileId}") + @Operation(summary = "Validate PDF given by URL against the selected profile and return validation result") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = { + @Content(mediaType = "application/xml", schema = @Schema(implementation = InputStream.class)), + @Content(mediaType = "application/json", schema = @Schema(implementation = InputStream.class)), + @Content(mediaType = "text/html", schema = @Schema(implementation = InputStream.class)) }) }) + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces({ MediaType.APPLICATION_XML }) + public static InputStream validateXml(@Parameter(description = "the String id of the Validation profile " + + "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") @PathParam("profileId") String profileId, + @Parameter(description = "a URL of PDF to be validated") @FormDataParam("url") String urlLink, + @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { + return validateUrl(urlLink, profileId, FormatOption.XML, fileSize); + } - /** - * @param profileId - * the String id of the Validation profile - * (auto, 1b, 1a, 2b, 2a, 2u, - * 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2) - * @param uploadedInputStream - * a {@link java.io.InputStream} to the PDF to - * be validated - * @param contentDispositionHeader - * @return - */ - @POST - @Path("/{profileId}") - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({MediaType.TEXT_HTML}) - public static InputStream validateHtml(@PathParam("profileId") String profileId, - @Parameter(name = "file", schema = @Schema(implementation = File.class), - style = ParameterStyle.FORM, description = "an InputStream of the PDF to be validated") - @FormDataParam("file") InputStream uploadedInputStream, - @Parameter(hidden = true) @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") - @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { - return validateFile(uploadedInputStream, contentDispositionHeader, profileId, null, FormatOption.HTML, fileSize); - } + @POST + @Path("/url/{profileId}") + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces({ MediaType.APPLICATION_JSON }) + public static InputStream validateJson(@Parameter(description = "the String id of the Validation profile " + + "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") @PathParam("profileId") String profileId, + @Parameter(description = "a URL of PDF to be validated") @FormDataParam("url") String urlLink, + @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { + return validateUrl(urlLink, profileId, FormatOption.JSON, fileSize); + } - /** - * @param profileId - * the String id of the Validation profile - * (auto, 1b, 1a, 2b, 2a, 2u, - * 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2) - * @param sha1Hex - * the hex String representation of the file's - * SHA-1 hash - * @param uploadedInputStream - * a {@link java.io.InputStream} to the PDF to - * be validated - * @param contentDispositionHeader - * @return - */ - @POST - @Path("/sha/{profileId}") - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({MediaType.TEXT_HTML}) - public static InputStream validateHtml(@PathParam("profileId") String profileId, - @Parameter(description = "the hex String representation of the file's SHA-1 hash") - @FormDataParam("sha1Hex") String sha1Hex, - @Parameter(name = "file", schema = @Schema(implementation = File.class), - style = ParameterStyle.FORM, description = "an InputStream of the PDF to be validated") - @FormDataParam("file") InputStream uploadedInputStream, - @Parameter(hidden = true) @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") - @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { - return validateFile(uploadedInputStream, contentDispositionHeader, profileId, sha1Hex, FormatOption.HTML, fileSize); - } + @POST + @Path("/url/{profileId}") + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces({ MediaType.TEXT_HTML }) + public static InputStream validateHtml(@Parameter(description = "the String id of the Validation profile " + + "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") @PathParam("profileId") String profileId, + @Parameter(description = "a URL of PDF to be validated") @FormDataParam("url") String urlLink, + @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { + return validateUrl(urlLink, profileId, FormatOption.HTML, fileSize); + } - @POST - @Path("/url/{profileId}") - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({MediaType.TEXT_HTML}) - public static InputStream validateHtml(@Parameter(description = "the String id of the Validation profile " + - "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") - @PathParam("profileId") String profileId, - @Parameter(description = "a URL of PDF to be validated") - @FormDataParam("url") String urlLink, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") - @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { - return validateUrl(urlLink, profileId, FormatOption.HTML, fileSize); - } + public static void setMaxFileSize(Integer maxFileSize) { + ValidateResource.maxFileSize = maxFileSize; + } - public static void setMaxFileSize(Integer maxFileSize) { - ValidateResource.maxFileSize = maxFileSize; - } + private static InputStream validateFile(InputStream uploadedInputStream, + FormDataContentDisposition contentDispositionHeader, String profileId, + String sha1Hex, FormatOption formatOption, Integer fileSize) { + if (contentDispositionHeader == null) { + throw new BadRequestException("File is empty"); + } - private static InputStream validateFile(InputStream uploadedInputStream, - FormDataContentDisposition contentDispositionHeader, String profileId, - String sha1Hex, FormatOption formatOption, Integer fileSize) { - if (contentDispositionHeader == null) { - throw new BadRequestException("File is empty"); - } + return validate(uploadedInputStream, contentDispositionHeader.getFileName(), profileId, sha1Hex, formatOption, + fileSize); + } - return validate(uploadedInputStream, contentDispositionHeader.getFileName(), profileId, sha1Hex, formatOption, fileSize); - } + private static InputStream validateUrl(String urlLink, String profileId, FormatOption formatOption, + Integer fileSize) { + InputStream uploadedInputStream = getInputStreamByUrlLink(urlLink); - private static InputStream validateUrl(String urlLink, String profileId, FormatOption formatOption, Integer fileSize) { - InputStream uploadedInputStream = getInputStreamByUrlLink(urlLink); + return validate(uploadedInputStream, urlLink, profileId, null, formatOption, fileSize); + } - return validate(uploadedInputStream, urlLink, profileId, null, formatOption, fileSize); - } + private static InputStream validate(InputStream uploadedInputStream, String fileName, String profileId, + String sha1Hex, FormatOption formatOption, Integer fileSize) { + if (fileName == null) { + throw new BadRequestException("File name is empty"); + } - private static InputStream validate(InputStream uploadedInputStream, String fileName, String profileId, - String sha1Hex, FormatOption formatOption, Integer fileSize) { - if (fileName == null) { - throw new BadRequestException("File name is empty"); - } + SeekableInputStream seekableInputStream = createInputStream(uploadedInputStream, sha1Hex, fileSize); + PDFAFlavour flavour = PDFAFlavour.byFlavourId(profileId); + ValidatorConfig validatorConfig = configManager.getValidatorConfig(); + validatorConfig.setFlavour(flavour); + ProcessorConfig config = createProcessorConfig(validatorConfig); + byte[] outputBytes; + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + VeraAppConfig appConfig = configManager.getApplicationConfig(); + processStream(seekableInputStream, fileName, config, outputStream, appConfig, formatOption); + outputBytes = outputStream.toByteArray(); + } catch (IOException excep) { + throw new InternalServerErrorException("Some Java Exception while validating", excep); + } + return new ByteArrayInputStream(outputBytes); + } - SeekableInputStream seekableInputStream = createInputStream(uploadedInputStream, sha1Hex, fileSize); - PDFAFlavour flavour = PDFAFlavour.byFlavourId(profileId); - ValidatorConfig validatorConfig = configManager.getValidatorConfig(); - validatorConfig.setFlavour(flavour); - ProcessorConfig config = createProcessorConfig(validatorConfig); - byte[] outputBytes; - try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { - VeraAppConfig appConfig = configManager.getApplicationConfig(); - processStream(seekableInputStream, fileName, config, outputStream, appConfig, formatOption); - outputBytes = outputStream.toByteArray(); - } catch (IOException excep) { - throw new InternalServerErrorException("Some Java Exception while validating", excep); - } - return new ByteArrayInputStream(outputBytes); - } + private static SeekableInputStream createInputStream(InputStream uploadedInputStream, String sha1Hex, + Integer fileSize) { + InputStream inputStream = uploadedInputStream; + if (sha1Hex != null) { + MessageDigest sha1 = getDigest(); + inputStream = new DigestInputStream(uploadedInputStream, sha1); + } + if (fileSize != null && fileSize > maxFileSize * CONVERTER_MB_TO_B) { + throw new BadRequestException(String.format(MAX_ALLOWED_FILE_SIZE, maxFileSize)); + } - private static SeekableInputStream createInputStream(InputStream uploadedInputStream, String sha1Hex, Integer fileSize) { - InputStream inputStream = uploadedInputStream; - if (sha1Hex != null) { - MessageDigest sha1 = getDigest(); - inputStream = new DigestInputStream(uploadedInputStream, sha1); - } - if (fileSize != null && fileSize > maxFileSize * CONVERTER_MB_TO_B) { - throw new BadRequestException(String.format(MAX_ALLOWED_FILE_SIZE, maxFileSize)); - } + try { + SeekableInputStream seekableInputStream = SeekableInputStream.getSeekableStream(inputStream, + CONVERTER_MB_TO_B * maxFileSize); + if (sha1Hex != null && !sha1Hex.equalsIgnoreCase( + Hex.encodeHexString(((DigestInputStream) inputStream).getMessageDigest().digest()))) { + throw new BadRequestException("Incorrect sha1 value"); + } + return seekableInputStream; + } catch (VeraPDFParserException e) { + throw new BadRequestException(String.format(MAX_ALLOWED_FILE_SIZE, maxFileSize), e); + } catch (IOException e) { + throw new InternalServerErrorException(e.getMessage(), e); + } + } - try { - SeekableInputStream seekableInputStream = SeekableInputStream.getSeekableStream(inputStream, CONVERTER_MB_TO_B * maxFileSize); - if (sha1Hex != null && !sha1Hex.equalsIgnoreCase(Hex.encodeHexString(((DigestInputStream) inputStream).getMessageDigest().digest()))) { - throw new BadRequestException("Incorrect sha1 value"); - } - return seekableInputStream; - } catch (VeraPDFParserException e) { - throw new BadRequestException(String.format(MAX_ALLOWED_FILE_SIZE, maxFileSize), e); - } catch (IOException e) { - throw new InternalServerErrorException(e.getMessage(), e); - } - } + private static MessageDigest getDigest() { + try { + return MessageDigest.getInstance(SHA1_NAME); + } catch (NoSuchAlgorithmException nsaExcep) { + // If this happens the Java Digest algorithms aren't present, a + // faulty Java install?? + throw new IllegalStateException( + "No digest algorithm implementation for " + + SHA1_NAME + ", check you Java installation.", //$NON-NLS-1$ + nsaExcep); // $NON-NLS-2$ + } + } - private static MessageDigest getDigest() { - try { - return MessageDigest.getInstance(SHA1_NAME); - } catch (NoSuchAlgorithmException nsaExcep) { - // If this happens the Java Digest algorithms aren't present, a - // faulty Java install?? - throw new IllegalStateException( - "No digest algorithm implementation for " + - SHA1_NAME + ", check you Java installation.", //$NON-NLS-1$ - nsaExcep); //$NON-NLS-2$ - } - } + private static ProcessorConfig createProcessorConfig(ValidatorConfig validatorConfig) { + VeraAppConfig veraAppConfig = configManager.getApplicationConfig(); + return ProcessorFactory.fromValues(validatorConfig, configManager.getFeaturesConfig(), + configManager.getPluginsCollectionConfig(), configManager.getFixerConfig(), + veraAppConfig.getProcessType().getTasks()); + } - private static ProcessorConfig createProcessorConfig(ValidatorConfig validatorConfig) { - VeraAppConfig veraAppConfig = configManager.getApplicationConfig(); - return ProcessorFactory.fromValues(validatorConfig, configManager.getFeaturesConfig(), - configManager.getPluginsCollectionConfig(), configManager.getFixerConfig(), - veraAppConfig.getProcessType().getTasks()); - } + private static InputStream getInputStreamByUrlLink(String urlLink) { + try { + return new URL(urlLink).openStream(); + } catch (IOException e) { + if (urlLink.isEmpty()) { + throw new BadRequestException("URL is empty", e); + } else { + throw new BadRequestException("URL is incorrect: " + urlLink, e); + } + } + } - private static InputStream getInputStreamByUrlLink(String urlLink) { - try { - return new URL(urlLink).openStream(); - } catch (IOException e) { - if (urlLink.isEmpty()) { - throw new BadRequestException("URL is empty", e); - } else { - throw new BadRequestException("URL is incorrect: " + urlLink, e); - } - } - } + private static BatchSummary processStream(SeekableInputStream inputStream, String fileName, ProcessorConfig config, + OutputStream stream, + VeraAppConfig appConfig, FormatOption formatOption) + throws IOException { + BatchSummary summary; + try (BatchProcessor processor = ProcessorFactory.fileBatchProcessor(config)) { + summary = processor.process(ItemDetails.fromValues(fileName, inputStream.getStreamLength()), inputStream, + ProcessorFactory.getHandler(formatOption, appConfig.isVerbose(), stream, + config.getValidatorConfig().isRecordPasses(), appConfig.getWikiPath())); + } catch (VeraPDFException e) { + throw new InternalServerErrorException(e.getMessage(), e); + } finally { + if (inputStream != null) { + inputStream.close(); + } + } + return summary; + } - private static BatchSummary processStream(SeekableInputStream inputStream, String fileName, ProcessorConfig config, OutputStream stream, - VeraAppConfig appConfig, FormatOption formatOption) - throws IOException { - BatchSummary summary; - try (BatchProcessor processor = ProcessorFactory.fileBatchProcessor(config)) { - summary = processor.process(ItemDetails.fromValues(fileName, inputStream.getStreamLength()), inputStream, - ProcessorFactory.getHandler(formatOption, appConfig.isVerbose(), stream, - config.getValidatorConfig().isRecordPasses(), appConfig.getWikiPath())); - } catch (VeraPDFException e) { - throw new InternalServerErrorException(e.getMessage(), e); - } finally { - if (inputStream != null) { - inputStream.close(); - } - } - return summary; - } + private static FormatOption formatOptionFromAccepts(final String accepts) { + if (accepts == null) { + return FormatOption.HTML; + } + if (accepts.contains("html")) { + return FormatOption.HTML; + } + return accepts.contains("xml") ? FormatOption.XML : FormatOption.JSON; + } } diff --git a/src/main/resources/assets/js/vera.results.js b/src/main/resources/assets/js/vera.results.js index 12e229b..c4cfec0 100644 --- a/src/main/resources/assets/js/vera.results.js +++ b/src/main/resources/assets/js/vera.results.js @@ -33,7 +33,11 @@ var pdfaValidator = { }, validate: function (formData, flavour, callback, contentType = "json") { $.ajax({ - url: '/api/validate/sha/' + flavour + '/', + beforeSend: function (xhrObj) { + let headerpt1 = (contentType === "html") ? "text/" : "application/" + xhrObj.setRequestHeader("Accept", headerpt1 + contentType); + }, + url: '/api/validate/' + flavour + '/', type: 'POST', data: formData, dataType: contentType, From 35e4b68668d7779199d7349d893502d137f83a83 Mon Sep 17 00:00:00 2001 From: Carl Wilson Date: Wed, 31 Jan 2024 16:41:37 +0000 Subject: [PATCH 4/6] FIX: Static QA issues. --- src/main/resources/assets/js/vera.results.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/assets/js/vera.results.js b/src/main/resources/assets/js/vera.results.js index c4cfec0..2bff7c1 100644 --- a/src/main/resources/assets/js/vera.results.js +++ b/src/main/resources/assets/js/vera.results.js @@ -33,11 +33,11 @@ var pdfaValidator = { }, validate: function (formData, flavour, callback, contentType = "json") { $.ajax({ - beforeSend: function (xhrObj) { - let headerpt1 = (contentType === "html") ? "text/" : "application/" + beforeSend(xhrObj) { + let headerpt1 = (contentType === "html") ? "text/" : "application/"; xhrObj.setRequestHeader("Accept", headerpt1 + contentType); }, - url: '/api/validate/' + flavour + '/', + url: "/api/validate/" + flavour + "/", type: 'POST', data: formData, dataType: contentType, From 0c84748e4a3f145defd11ac1966b9731cffd3450 Mon Sep 17 00:00:00 2001 From: Carl Wilson Date: Thu, 8 Feb 2024 12:29:49 +0000 Subject: [PATCH 5/6] DOCS: Better Swagger docs for validate methods - consolidated URL validation methods; - improved documentation of methods and params; - factored string duplication to constants for some cases; and - added quotes to param in `Dockerfile`. --- Dockerfile | 2 +- .../rest/resources/ValidateResource.java | 75 ++++++++----------- 2 files changed, 33 insertions(+), 44 deletions(-) diff --git a/Dockerfile b/Dockerfile index ef773af..5d9ff5d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -65,4 +65,4 @@ COPY --from=app-builder /build/veraPDF-rest/config /opt/verapdf-rest/config/ VOLUME /var/opt/verapdf-rest EXPOSE 8080 -ENTRYPOINT dumb-init java $JAVA_OPTS -Djava.awt.headless=true -jar /opt/verapdf-rest/verapdf-rest-${VERAPDF_REST_VERSION}.jar server /var/opt/verapdf-rest/config/server.yml +ENTRYPOINT dumb-init java "$JAVA_OPTS" -Djava.awt.headless=true -jar /opt/verapdf-rest/verapdf-rest-${VERAPDF_REST_VERSION}.jar server /var/opt/verapdf-rest/config/server.yml diff --git a/src/main/java/org/verapdf/rest/resources/ValidateResource.java b/src/main/java/org/verapdf/rest/resources/ValidateResource.java index 27062eb..9503788 100644 --- a/src/main/java/org/verapdf/rest/resources/ValidateResource.java +++ b/src/main/java/org/verapdf/rest/resources/ValidateResource.java @@ -13,10 +13,10 @@ import java.security.DigestInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.text.Format; import javax.ws.rs.BadRequestException; import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.InternalServerErrorException; @@ -37,6 +37,7 @@ import org.verapdf.io.SeekableInputStream; import org.verapdf.pdfa.Foundries; import org.verapdf.pdfa.flavours.PDFAFlavour; +import org.verapdf.pdfa.results.ValidationResult; import org.verapdf.pdfa.validation.validators.ValidatorConfig; import org.verapdf.processor.BatchProcessor; import org.verapdf.processor.FormatOption; @@ -60,6 +61,11 @@ * @author Carl Wilson */ public class ValidateResource { + private static final String PARAM_PROFILE_DESC = "the String id of the PDF Specification to validate against. " + + "must be one of: (auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2). " + + "Selecting 'auto' allows the validator to detect and apply the appropriate specification from the PDF metadata."; + private static final String PARAM_FILE_SIZE_DESC = "the size of the PDF to be validated in bytes, read from the request header."; + private static final String VALIDATION_OP_DESC = "against the selected PDF Specification/Validaton profile and return a report comprising the valdiation results."; // java.security.digest name for the SHA-1 algorithm private static final String SHA1_NAME = "SHA-1"; //$NON-NLS-1$ private static final String FILE_SIZE_HEADER = "X-File-Size"; @@ -104,65 +110,48 @@ public static ComponentDetails getDetails() { */ @POST @Path("/{profileId}") - @Operation(summary = "Validate the uploaded stream against the selected profile and return validation result") + @Operation(summary = "Validate the uploaded file " + VALIDATION_OP_DESC) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "OK", content = { - @Content(mediaType = "application/xml", schema = @Schema(implementation = InputStream.class)), - @Content(mediaType = "application/json", schema = @Schema(implementation = InputStream.class)), - @Content(mediaType = "text/html", schema = @Schema(implementation = InputStream.class)) }) }) + @Content(mediaType = "application/xml", schema = @Schema(implementation = BatchSummary.class)), + @Content(mediaType = "application/json", schema = @Schema(implementation = BatchSummary.class)), + @Content(mediaType = "text/html", schema = @Schema(implementation = BatchSummary.class)) }) }) @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML }) - public static Response validateXml(@Parameter(description = "the String id of the Validation profile " + - "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") @PathParam("profileId") String profileId, + public static Response validateXml( + @Parameter(description = PARAM_PROFILE_DESC) @PathParam("profileId") String profileId, @Parameter(description = "the hex String representation of the file's SHA-1 hash", required = false, allowEmptyValue = true) @FormDataParam("sha1Hex") String sha1Hex, - @Parameter(name = "file", schema = @Schema(implementation = File.class), style = ParameterStyle.FORM, description = "an InputStream of the PDF to be validated") @FormDataParam("file") InputStream uploadedInputStream, + @Parameter(name = "file", schema = @Schema(implementation = File.class), style = ParameterStyle.FORM, description = "a PDF file uploaded to be validated") @FormDataParam("file") InputStream uploadedInputStream, @Parameter(hidden = true) @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") @HeaderParam(FILE_SIZE_HEADER) Integer fileSize, + @Parameter(name = FILE_SIZE_HEADER, description = PARAM_FILE_SIZE_DESC) @HeaderParam(FILE_SIZE_HEADER) Integer fileSize, @HeaderParam("Accept") String accepts) { - FormatOption formatOption = formatOptionFromAccepts(accepts); return Response - .ok(validateFile(uploadedInputStream, contentDispositionHeader, profileId, sha1Hex, formatOption, + .ok(validateFile(uploadedInputStream, contentDispositionHeader, profileId, sha1Hex, + formatOptionFromAccepts(accepts), fileSize), accepts) .build(); } @POST @Path("/url/{profileId}") - @Operation(summary = "Validate PDF given by URL against the selected profile and return validation result") + @Operation(summary = "Validate PDF located at the supplied URL " + VALIDATION_OP_DESC) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "OK", content = { - @Content(mediaType = "application/xml", schema = @Schema(implementation = InputStream.class)), - @Content(mediaType = "application/json", schema = @Schema(implementation = InputStream.class)), - @Content(mediaType = "text/html", schema = @Schema(implementation = InputStream.class)) }) }) + @Content(mediaType = "application/xml", schema = @Schema(implementation = BatchSummary.class)), + @Content(mediaType = "application/json", schema = @Schema(implementation = BatchSummary.class)), + @Content(mediaType = "text/html", schema = @Schema(implementation = BatchSummary.class)) }) }) @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({ MediaType.APPLICATION_XML }) - public static InputStream validateXml(@Parameter(description = "the String id of the Validation profile " + - "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") @PathParam("profileId") String profileId, - @Parameter(description = "a URL of PDF to be validated") @FormDataParam("url") String urlLink, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { - return validateUrl(urlLink, profileId, FormatOption.XML, fileSize); - } - - @POST - @Path("/url/{profileId}") - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({ MediaType.APPLICATION_JSON }) - public static InputStream validateJson(@Parameter(description = "the String id of the Validation profile " + - "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") @PathParam("profileId") String profileId, - @Parameter(description = "a URL of PDF to be validated") @FormDataParam("url") String urlLink, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { - return validateUrl(urlLink, profileId, FormatOption.JSON, fileSize); - } - - @POST - @Path("/url/{profileId}") - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({ MediaType.TEXT_HTML }) - public static InputStream validateHtml(@Parameter(description = "the String id of the Validation profile " + - "(auto, 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1 or ua2)") @PathParam("profileId") String profileId, - @Parameter(description = "a URL of PDF to be validated") @FormDataParam("url") String urlLink, - @Parameter(name = FILE_SIZE_HEADER, description = "a size of the PDF to be validated") @HeaderParam(FILE_SIZE_HEADER) Integer fileSize) { - return validateUrl(urlLink, profileId, FormatOption.HTML, fileSize); + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML }) + public static Response validateXml( + @Parameter(description = PARAM_PROFILE_DESC) @PathParam("profileId") String profileId, + @Parameter(description = "a URL that resolves to PDF resource to be validated") @FormDataParam("url") String urlLink, + @Parameter(name = FILE_SIZE_HEADER, description = PARAM_FILE_SIZE_DESC) @HeaderParam(FILE_SIZE_HEADER) Integer fileSize, + @HeaderParam("Accept") String accepts) { + return Response + .ok(validateUrl(urlLink, profileId, + formatOptionFromAccepts(accepts), + fileSize), accepts) + .build(); } public static void setMaxFileSize(Integer maxFileSize) { From 16bee5f364230e3e78a07113065ac69c85aaeac1 Mon Sep 17 00:00:00 2001 From: Carl Wilson Date: Thu, 8 Feb 2024 13:28:13 +0000 Subject: [PATCH 6/6] FIX: Field order warning. --- src/main/java/org/verapdf/rest/resources/ValidateResource.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/verapdf/rest/resources/ValidateResource.java b/src/main/java/org/verapdf/rest/resources/ValidateResource.java index 9503788..ce92737 100644 --- a/src/main/java/org/verapdf/rest/resources/ValidateResource.java +++ b/src/main/java/org/verapdf/rest/resources/ValidateResource.java @@ -72,7 +72,6 @@ public class ValidateResource { private static final int CONVERTER_MB_TO_B = 1_048_576; private static int maxFileSize; private static final String MAX_ALLOWED_FILE_SIZE = "Maximum allowed file size exceeded: %d MB"; - private static final ConfigManager configManager; static {