diff --git a/CHANGELOG.md b/CHANGELOG.md index 37086009d..8666dc665 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- [fj-doc-val-core] DocValidatorTypeCheck facade to check file type +- [fj-doc-val-p7m] check the inner type on P7MContentValidator + ### Changed - [fj-doc-playground-quarkus] show quakus version diff --git a/fj-doc-val-core/src/main/java/org/fugerit/java/doc/val/core/DocValidatorTypeCheck.java b/fj-doc-val-core/src/main/java/org/fugerit/java/doc/val/core/DocValidatorTypeCheck.java new file mode 100644 index 000000000..7f4b1dd5c --- /dev/null +++ b/fj-doc-val-core/src/main/java/org/fugerit/java/doc/val/core/DocValidatorTypeCheck.java @@ -0,0 +1,69 @@ +package org.fugerit.java.doc.val.core; + +import lombok.Getter; +import org.fugerit.java.core.function.SafeFunction; +import org.fugerit.java.core.io.StreamIO; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/** + * This facade tries to retrieve a document's type. + * + */ +public class DocValidatorTypeCheck { + + @Getter + private DocValidatorFacade facade; + + private DocValidatorTypeCheck( DocValidatorFacade facade ) { + this.facade = facade; + } + + /** + * Type check of a byte stream against the configured DocTypeValidator facade. + * + * It will return null if the stream is not valid for all the validators, otherwise DocTypeValidator.getMimeType() of the first validator matching the type. + * + * NOTE: This method always buffer the input, so it can be memory consuming. + * + * @param is the byte stream to check + * @return null if the stream is not valid for all the validators, otherwise DocTypeValidator.getMimeType() of the first validator matching the type + */ + public String checkType(InputStream is) { + return SafeFunction.get( () -> this.checkType( StreamIO.readBytes( is ) ) ); + } + + /** + * Type check for an input document against the configured DocTypeValidator facade. + * + * It will return null if the stream is not valid for all the validators, otherwise DocTypeValidator.getMimeType() of the first validator matching the type. + * + * NOTE: This method always buffer the input, so it can be memory consuming. + * + * @param buffer the document to check + * @return null if the input is not valid for all the validators, otherwise DocTypeValidator.getMimeType() of the first validator matching the type + */ + public String checkType(byte[] buffer) { + return SafeFunction.get( () -> { + for ( DocTypeValidator validator : this.facade.validators() ) { + try (ByteArrayInputStream input = new ByteArrayInputStream( buffer )) { + if ( validator.check( input ) ) { + return validator.getMimeType(); + } + } + } + // default case, type not found + return null; + } ); + } + + public static DocValidatorTypeCheck newInstance( DocTypeValidator... validator ) { + return newInstance( DocValidatorFacade.newFacadeStrict( validator ) ); + } + + public static DocValidatorTypeCheck newInstance( DocValidatorFacade facade ) { + return new DocValidatorTypeCheck( facade ); + } + +} diff --git a/fj-doc-val-core/src/test/java/test/org/fugerit/java/doc/core/val/TestDocValidatorTypeCheck.java b/fj-doc-val-core/src/test/java/test/org/fugerit/java/doc/core/val/TestDocValidatorTypeCheck.java new file mode 100644 index 000000000..9cf835f68 --- /dev/null +++ b/fj-doc-val-core/src/test/java/test/org/fugerit/java/doc/core/val/TestDocValidatorTypeCheck.java @@ -0,0 +1,47 @@ +package test.org.fugerit.java.doc.core.val; + +import lombok.extern.slf4j.Slf4j; +import org.fugerit.java.core.function.SafeFunction; +import org.fugerit.java.core.lang.helpers.ClassHelper; +import org.fugerit.java.doc.val.core.DocValidatorTypeCheck; +import org.fugerit.java.doc.val.core.basic.ImageValidator; +import org.junit.Assert; +import org.junit.Test; + +import java.awt.*; +import java.io.InputStream; + +@Slf4j +public class TestDocValidatorTypeCheck { + + private static final DocValidatorTypeCheck TYPE_CHECK = DocValidatorTypeCheck.newInstance( + ImageValidator.JPG_VALIDATOR, ImageValidator.PNG_VALIDATOR ); + + private static final String BASE_PATH = "sample"; + + private String worker( String fileName ) { + return SafeFunction.get( () -> { + String path = BASE_PATH+"/"+fileName; + log.info( "test path {}", path ); + try ( InputStream is = ClassHelper.loadFromDefaultClassLoader( path ) ) { + return TYPE_CHECK.checkType( is ); + } + } ); + } + + @Test + public void testJpg() { + Assert.assertEquals(ImageValidator.JPG_VALIDATOR.getMimeType(), this.worker( "jpg_as_jpg.jpg" ) ); + } + + @Test + public void testPng() { + Assert.assertEquals(ImageValidator.PNG_VALIDATOR.getMimeType(), this.worker( "png_as_png.png" ) ); + } + + @Test + public void testNull() { + Assert.assertNull( this.worker( "pdf_as_jpg.jpg" ) ); + } + +} diff --git a/fj-doc-val-p7m/src/main/java/org/fugerit/java/doc/val/p7m/P7MContentValidator.java b/fj-doc-val-p7m/src/main/java/org/fugerit/java/doc/val/p7m/P7MContentValidator.java index e72b30f9e..60922b0d7 100644 --- a/fj-doc-val-p7m/src/main/java/org/fugerit/java/doc/val/p7m/P7MContentValidator.java +++ b/fj-doc-val-p7m/src/main/java/org/fugerit/java/doc/val/p7m/P7MContentValidator.java @@ -1,25 +1,34 @@ package org.fugerit.java.doc.val.p7m; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import org.fugerit.java.core.cfg.ConfigRuntimeException; +import org.fugerit.java.core.function.SafeFunction; import org.fugerit.java.doc.val.core.DocTypeValidationResult; -import org.fugerit.java.doc.val.core.DocTypeValidator; import org.fugerit.java.doc.val.core.DocValidatorFacade; +import org.fugerit.java.doc.val.core.DocValidatorTypeCheck; import org.fugerit.java.doc.val.core.basic.AbstractDocTypeValidator; import lombok.Getter; import lombok.Setter; public class P7MContentValidator extends AbstractDocTypeValidator { + + public static final boolean DEFAULT_PROCEED_ON_INNTER_CHECK = Boolean.FALSE; + + @Getter @Setter private DocValidatorTypeCheck facade; + + @Getter private boolean proceedOnInnerTypeCheck; - @Getter @Setter private DocValidatorFacade facade; - - public P7MContentValidator(DocValidatorFacade facade) { + public P7MContentValidator(DocValidatorFacade facade, boolean proceedOnInnerTypeCheck) { super( P7MValidator.MIME_TYPE, P7MValidator.EXTENSION ); - this.facade = facade; + this.facade = DocValidatorTypeCheck.newInstance( facade ); + this.proceedOnInnerTypeCheck = proceedOnInnerTypeCheck; + } + + public P7MContentValidator(DocValidatorFacade facade) { + this( facade, DEFAULT_PROCEED_ON_INNTER_CHECK ); } public P7MContentValidator() { @@ -28,34 +37,43 @@ public P7MContentValidator() { @Override public DocTypeValidationResult validate(InputStream is) { - return this.validationHelper( () -> { + return this.validationHelper( () -> this.checkInnerType( is ) ); + } + + public String checkInnerType(InputStream is ) { + return SafeFunction.get( () -> { try ( ByteArrayOutputStream os = new ByteArrayOutputStream() ) { P7MUtils.extractContent(is, os); - if ( this.getFacade() != null ) { - boolean isValid = false; - for ( DocTypeValidator validator : this.getFacade().validators() ) { - try ( ByteArrayInputStream bis = new ByteArrayInputStream( os.toByteArray() ) ) { - if ( validator.check( bis ) ) { - isValid = true; - break; - } - } - } - if ( !isValid ) { + if ( this.facade.getFacade() != null ) { + String mimeType = this.facade.checkType( os.toByteArray() ); + if ( mimeType != null || this.proceedOnInnerTypeCheck ) { + return mimeType; + } else { throw new ConfigRuntimeException( "Content not valid for this validator facade!" ); } + } else { + return null; } } } ); } public P7MContentValidator withDocValidatorFacade( DocValidatorFacade facade ) { - this.setFacade( facade ); + this.setFacade( DocValidatorTypeCheck.newInstance( facade ) ); return this; } - + + public P7MContentValidator withProceedOnInnerTypeCheck( boolean proceedOnInnerTypeCheck ) { + this.proceedOnInnerTypeCheck = proceedOnInnerTypeCheck; + return this; + } + public static P7MContentValidator newValidator( DocValidatorFacade facade ) { - return new P7MContentValidator().withDocValidatorFacade(facade); + return newValidator( facade, DEFAULT_PROCEED_ON_INNTER_CHECK ); + } + + public static P7MContentValidator newValidator( DocValidatorFacade facade, boolean proceedOnInnerTypeCheck ) { + return new P7MContentValidator().withDocValidatorFacade(facade).withProceedOnInnerTypeCheck( proceedOnInnerTypeCheck ); } } diff --git a/fj-doc-val-p7m/src/test/java/test/org/fugerit/java/doc/val/p7m/TestDocValidatorFacade.java b/fj-doc-val-p7m/src/test/java/test/org/fugerit/java/doc/val/p7m/TestDocValidatorFacade.java index 605018461..dc18bf191 100644 --- a/fj-doc-val-p7m/src/test/java/test/org/fugerit/java/doc/val/p7m/TestDocValidatorFacade.java +++ b/fj-doc-val-p7m/src/test/java/test/org/fugerit/java/doc/val/p7m/TestDocValidatorFacade.java @@ -2,6 +2,7 @@ import java.io.InputStream; +import lombok.extern.slf4j.Slf4j; import org.fugerit.java.core.function.SafeFunction; import org.fugerit.java.core.lang.helpers.ClassHelper; import org.fugerit.java.doc.val.core.DocValidatorFacade; @@ -9,16 +10,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@Slf4j public class TestDocValidatorFacade { - private static final Logger logger = LoggerFactory.getLogger( TestDocValidatorFacade.class ); - - private static final String BASE_PATH = "sample"; + protected static final String BASE_PATH = "sample"; protected boolean worker( DocValidatorFacade facade, String fileName, boolean result ) { return SafeFunction.get( () -> { String path = BASE_PATH+"/"+fileName; - logger.info( "test path {}, expected result {}", path, result ); + log.info( "test path {}, expected result {}", path, result ); try ( InputStream is = ClassHelper.loadFromDefaultClassLoader( path ) ) { boolean check = facade.check(fileName, is); Assert.assertEquals( "File check failed", result, check ); diff --git a/fj-doc-val-p7m/src/test/java/test/org/fugerit/java/doc/val/p7m/TestP7MContentValidator.java b/fj-doc-val-p7m/src/test/java/test/org/fugerit/java/doc/val/p7m/TestP7MContentValidator.java index 37e000a21..9ce7090ba 100644 --- a/fj-doc-val-p7m/src/test/java/test/org/fugerit/java/doc/val/p7m/TestP7MContentValidator.java +++ b/fj-doc-val-p7m/src/test/java/test/org/fugerit/java/doc/val/p7m/TestP7MContentValidator.java @@ -1,5 +1,8 @@ package test.org.fugerit.java.doc.val.p7m; +import lombok.extern.slf4j.Slf4j; +import org.fugerit.java.core.function.SafeFunction; +import org.fugerit.java.core.lang.helpers.ClassHelper; import org.fugerit.java.doc.val.core.DocValidatorFacade; import org.fugerit.java.doc.val.core.basic.ImageValidator; import org.fugerit.java.doc.val.p7m.P7MContentValidator; @@ -7,8 +10,13 @@ import org.junit.Assert; import org.junit.Test; +import java.io.InputStream; + +@Slf4j public class TestP7MContentValidator extends TestDocValidatorFacade { + private static final String FILENAME_PDF_AS_P7M = "pdf_as_pdf.p7m"; + private static final DocValidatorFacade FACADE_PDF = DocValidatorFacade.newFacadeStrict( P7MContentValidator.newValidator( DocValidatorFacade.newFacade( PdfboxStrictValidator.DEFAULT ) ) ); @@ -20,23 +28,49 @@ public class TestP7MContentValidator extends TestDocValidatorFacade { private static final DocValidatorFacade FACADE_NULL = DocValidatorFacade.newFacadeStrict( P7MContentValidator.newValidator( null ) ); + + private static final P7MContentValidator CONTENT_JPG_PROCEED = + P7MContentValidator.newValidator( DocValidatorFacade.newFacade( ImageValidator.JPG_VALIDATOR ), true ); + + private static final P7MContentValidator CONTENT_PDF_PROCEED = + P7MContentValidator.newValidator( DocValidatorFacade.newFacade( PdfboxStrictValidator.DEFAULT ), true ); + + protected String worker( P7MContentValidator validator, String fileName ) { + return SafeFunction.get( () -> { + String path = BASE_PATH+"/"+fileName; + log.info( "test path to check {}", path ); + try ( InputStream is = ClassHelper.loadFromDefaultClassLoader( path ) ) { + return validator.checkInnerType( is ); + } + } ); + } @Test public void testP7MAsP7M() { - boolean ok = this.worker(FACADE_PDF, "pdf_as_pdf.p7m", true ); + boolean ok = this.worker(FACADE_PDF, FILENAME_PDF_AS_P7M, true ); Assert.assertTrue( ok ); } @Test public void testP7MAsP7MNull() { - boolean ok = this.worker(FACADE_NULL, "pdf_as_pdf.p7m", true ); + boolean ok = this.worker(FACADE_NULL, FILENAME_PDF_AS_P7M, true ); Assert.assertTrue( ok ); } @Test public void testP7MAsP7MKo() { - boolean ok = this.worker(FACADE_JPG, "pdf_as_pdf.p7m", false ); + boolean ok = this.worker(FACADE_JPG, FILENAME_PDF_AS_P7M, false ); Assert.assertTrue( ok ); } + + @Test + public void testProccedKo() { + Assert.assertNull( this.worker( CONTENT_JPG_PROCEED, FILENAME_PDF_AS_P7M ) ); + } + + @Test + public void testProccedOk() { + Assert.assertEquals( PdfboxStrictValidator.DEFAULT.getMimeType(), this.worker( CONTENT_PDF_PROCEED, FILENAME_PDF_AS_P7M ) ); + } }