FGEJsonschemaValidator.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2024 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.utils.json.validation;
import java.io.ByteArrayOutputStream;
import java.util.Iterator;
import org.openspcoop2.utils.LoggerWrapperFactory;
import org.openspcoop2.utils.json.IJsonSchemaValidator;
import org.openspcoop2.utils.json.JSONUtils;
import org.openspcoop2.utils.json.JsonSchemaValidatorConfig;
import org.openspcoop2.utils.json.ValidationException;
import org.openspcoop2.utils.json.ValidationResponse;
import org.openspcoop2.utils.json.ValidationResponse.ESITO;
import org.slf4j.Logger;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.fge.jsonschema.core.report.LogLevel;
import com.github.fge.jsonschema.core.report.ProcessingMessage;
import com.github.fge.jsonschema.core.report.ProcessingReport;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
import com.github.fge.jsonschema.main.JsonValidator;
/**
* FGEJsonschemaValidator
*
* @author Giovanni Bussu (bussu@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class FGEJsonschemaValidator implements IJsonSchemaValidator {
private JsonValidator validator;
private JsonNode schema;
private byte[] schemaBytes;
private ObjectMapper jsonMapper;
private Logger log;
private boolean logError;
public FGEJsonschemaValidator() {
this.validator = JsonSchemaFactory.byDefault().getValidator();
this.jsonMapper = new ObjectMapper();
}
@Override
public void setSchema(byte[] schema, JsonSchemaValidatorConfig config, Logger log) throws ValidationException {
this.log = log;
if(this.log==null) {
this.log = LoggerWrapperFactory.getLogger(FGEJsonschemaValidator.class);
}
this.logError = config!=null ? config.isEmitLogError() : true;
this.schemaBytes = schema;
try {
this.schema = this.jsonMapper.readTree(schema);
if(config!=null) {
switch(config.getAdditionalProperties()) {
case DEFAULT:
break;
case FORCE_DISABLE: ValidationUtils.disableAdditionalProperties(this.jsonMapper, this.schema, true, true);
break;
case FORCE_STRING: ValidationUtils.disableAdditionalProperties(this.jsonMapper, this.schema, false, true);
break;
case IF_NULL_DISABLE: ValidationUtils.disableAdditionalProperties(this.jsonMapper, this.schema, true, false);
break;
case IF_NULL_STRING: ValidationUtils.disableAdditionalProperties(this.jsonMapper, this.schema, false, false);
break;
default:
break;
}
}
if(config!=null) {
switch(config.getPoliticaInclusioneTipi()) {
case DEFAULT:
break;
case ALL: ValidationUtils.addTypes(this.jsonMapper, this.schema, config.getTipi(), true);
break;
case ANY: ValidationUtils.addTypes(this.jsonMapper, this.schema, config.getTipi(), false);
break;
default:
break;
}
}
if(config!=null && config.isVerbose()) {
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
JSONUtils.getInstance(true).writeTo(this.schema, bout);
bout.flush();
bout.close();
this.log.debug("JSON Schema: "+bout.toString());
}catch(Exception e) {
this.log.debug("JSON Schema build error: "+e.getMessage(),e);
}
}
} catch(Exception e) {
throw new ValidationException(e);
}
}
@Override
public ValidationResponse validate(byte[] rawObject) throws ValidationException {
ValidationResponse response = new ValidationResponse();
try {
boolean expectedString = false;
if(this.schema.has("type")) {
try {
JsonNode type = this.schema.get("type");
String vType = type.asText();
expectedString = "string".equals(vType);
}catch(Exception e) {}
}
JsonNode object = null;
try {
if(expectedString) {
object = this.jsonMapper.getNodeFactory().textNode(new String(rawObject));
}
else {
object = this.jsonMapper.readTree(rawObject);
}
}
catch(Exception e) {
this.log.error(e.getMessage(),e);
String messageString = "Read rawObject as jsonNode failed: "+e.getMessage();
response.setEsito(ESITO.KO);
if(this.logError) {
ValidationUtils.logError(this.log, messageString.toString(), rawObject, this.schemaBytes, this.schema);
}
response.setException(new Exception(messageString.toString()));
}
if(object!=null) {
ProcessingReport report = this.validator.validate(this.schema, object, true);
if(report.isSuccess()) {
response.setEsito(ESITO.OK);
} else {
response.setEsito(ESITO.KO);
Iterator<ProcessingMessage> iterator = report.iterator();
while(iterator.hasNext()) {
ProcessingMessage msg = iterator.next();
StringBuilder messageString = new StringBuilder();
if(msg.getLogLevel().equals(LogLevel.ERROR) || msg.getLogLevel().equals(LogLevel.FATAL)) {
response.getErrors().add(msg.getMessage());
messageString.append(msg.getMessage()).append("\n");
}
if(this.logError) {
ValidationUtils.logError(this.log, messageString.toString(), rawObject, this.schemaBytes, this.schema);
}
response.setException(new Exception(messageString.toString()));
}
}
}
} catch(Exception e) {
throw new ValidationException(e);
}
return response;
}
}