Skip to content

Commit

Permalink
[fj-doc-val-core] DocValidatorTypeCheck facade to check file type #260
Browse files Browse the repository at this point in the history
[fj-doc-val-p7m] check the inner type on P7MContentValidator
  • Loading branch information
fugerit79 committed Nov 19, 2024
1 parent 068f5fa commit 63f9f5e
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 28 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <code>null</code> 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 <code>null</code> 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 <code>null</code> 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 <code>null</code> 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 );
}

}
Original file line number Diff line number Diff line change
@@ -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" ) );
}

}
Original file line number Diff line number Diff line change
@@ -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() {
Expand All @@ -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 );
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@

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;
import org.junit.Assert;
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 );
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
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;
import org.fugerit.java.doc.val.pdf.box.PdfboxStrictValidator;
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 ) )
);
Expand All @@ -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 ) );
}

}

0 comments on commit 63f9f5e

Please sign in to comment.