EveritJsonschemaValidator.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */

  20. package org.openspcoop2.utils.json.validation;

  21. import java.util.HashMap;
  22. import java.util.List;
  23. import java.util.Map;

  24. import org.everit.json.schema.Schema;
  25. import org.everit.json.schema.loader.SchemaLoader;
  26. import org.json.JSONObject;
  27. import org.openspcoop2.utils.LoggerWrapperFactory;
  28. import org.openspcoop2.utils.json.IJsonSchemaValidator;
  29. import org.openspcoop2.utils.json.JsonSchemaValidatorConfig;
  30. import org.openspcoop2.utils.json.ValidationException;
  31. import org.openspcoop2.utils.json.ValidationResponse;
  32. import org.openspcoop2.utils.json.ValidationResponse.ESITO;
  33. import org.slf4j.Logger;

  34. import net.sf.json.JSONArray;

  35. /**
  36.  * EveritJsonschemaValidator
  37.  *
  38.  * @author Giovanni Bussu (bussu@link.it)
  39.  * @author $Author$
  40.  * @version $Rev$, $Date$
  41.  */
  42. public class EveritJsonschemaValidator implements IJsonSchemaValidator {

  43.     private Schema schema;
  44.     private byte[] schemaBytes;
  45.     private Logger log;
  46.     private boolean logError;

  47.     @Override
  48.     public void setSchema(byte[] schema, JsonSchemaValidatorConfig config, Logger log) throws ValidationException {
  49.        
  50.         this.log = log;
  51.         if(this.log==null) {
  52.             this.log = LoggerWrapperFactory.getLogger(EveritJsonschemaValidator.class);
  53.         }
  54.         this.logError = config!=null ? config.isEmitLogError() : true;
  55.         this.schemaBytes = schema;
  56.        
  57.         try {
  58.             JSONObject jsonSchemaObject = new JSONObject(new String(schema));
  59.             Map<String, String> map = new HashMap<>();
  60.             map.put("type", "string");
  61.             JSONObject jsonStringObject = new JSONObject(map);
  62.            
  63.             if(config!=null) {
  64.                 switch(config.getAdditionalProperties()) {
  65.                 case DEFAULT:
  66.                     break;
  67.                 case FORCE_DISABLE: addAdditionalProperties(jsonSchemaObject, Boolean.FALSE, true);
  68.                     break;
  69.                 case FORCE_STRING: addAdditionalProperties(jsonSchemaObject, jsonStringObject, true);
  70.                     break;
  71.                 case IF_NULL_DISABLE: addAdditionalProperties(jsonSchemaObject, Boolean.FALSE, false);
  72.                     break;
  73.                 case IF_NULL_STRING: addAdditionalProperties(jsonSchemaObject, jsonStringObject, false);
  74.                     break;
  75.                 default:
  76.                     break;
  77.                 }
  78.             }
  79.            
  80.             if(config!=null) {
  81.                 switch(config.getPoliticaInclusioneTipi()) {
  82.                 case DEFAULT:
  83.                     break;
  84.                 case ALL: addTypes(jsonSchemaObject, config.getTipi(), true);
  85.                     break;
  86.                 case ANY: addTypes(jsonSchemaObject, config.getTipi(), false);
  87.                     break;
  88.                 default:
  89.                     break;
  90.                 }
  91.             }
  92.            
  93.             this.schema = SchemaLoader.load(jsonSchemaObject);
  94.            
  95.             if(config!=null && config.isVerbose()) {
  96.                 try {
  97.                     String debugSchema = jsonSchemaObject.toString();
  98.                     this.log.debug("JSON Schema: "+debugSchema);
  99.                 }catch(Exception e) {
  100.                     this.log.debug("JSON Schema build error: "+e.getMessage(),e);
  101.                 }
  102.             }
  103.            
  104.         } catch(Exception e) {
  105.             throw new ValidationException(e);
  106.         }
  107.     }

  108.     private void addTypes(JSONObject jsonSchemaObject, List<String> nomi, boolean all) {
  109.        
  110.         String allAny = all ? "allOf" : "anyOf";
  111.         JSONArray array = new JSONArray();
  112.         for(String nome: nomi) {
  113.             Map<String, String> map = new HashMap<>();
  114.             map.put("$ref", nome);
  115.             JSONObject obj = new JSONObject(map);
  116.             array.element(obj);
  117.         }

  118.         jsonSchemaObject.remove("anyOf");
  119.         jsonSchemaObject.remove("allOf");
  120.         jsonSchemaObject.put(allAny, array);
  121.     }

  122.     private void addAdditionalProperties(JSONObject jsonSchemaObject, Object additionalPropertiesObject, boolean force) {
  123.         JSONObject definitions = (JSONObject) jsonSchemaObject.get("definitions");
  124.        
  125.         for(String def: definitions.keySet()) {
  126.             JSONObject definition = (JSONObject) definitions.get(def);
  127.             if(force || !definition.has("additionalProperties")) {
  128.                 definition.put("additionalProperties", additionalPropertiesObject);
  129.             }
  130.         }
  131.     }

  132.     @Override
  133.     public ValidationResponse validate(byte[] object) throws ValidationException {
  134.        
  135.         ValidationResponse response = new ValidationResponse();
  136.         try {
  137.             JSONObject jsonObject = null;
  138.             try {
  139.                 jsonObject = new JSONObject(new String(object));
  140.             }
  141.             catch(Exception e) {
  142.                 this.log.error(e.getMessage(),e);
  143.                 String messageString = "Read rawObject as jsonObject failed: "+e.getMessage();
  144.                 response.setEsito(ESITO.KO);
  145.                 if(this.logError) {
  146.                     ValidationUtils.logError(this.log, messageString.toString(), object, this.schemaBytes, null);
  147.                 }
  148.                 response.setException(new Exception(messageString.toString()));
  149.             }
  150.            
  151.             if(jsonObject!=null) {
  152.                 try {
  153.                     this.schema.validate(jsonObject); // throws a ValidationException if this object is invalid
  154.                     response.setEsito(ESITO.OK);
  155.                 } catch(org.everit.json.schema.ValidationException e) {
  156.                     response.setEsito(ESITO.KO);
  157.                     response.setException(e);
  158.                     response.getErrors().add(e.getErrorMessage());
  159.                     if(this.logError) {
  160.                         ValidationUtils.logError(this.log, e.getErrorMessage(), object, this.schemaBytes, null);
  161.                     }
  162.                 }
  163.             }

  164.         } catch(Exception e) {
  165.             throw new ValidationException(e);
  166.         }
  167.        
  168.         return response;
  169.     }
  170.    
  171. }