Coverage Report - org.mule.module.xml.filters.SchemaValidationFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
SchemaValidationFilter
0%
0/110
0%
0/46
0
SchemaValidationFilter$1
0%
0/6
N/A
0
 
 1  
 /*
 2  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 3  
  * The software in this package is published under the terms of the CPAL v1.0
 4  
  * license, a copy of which has been included with this distribution in the
 5  
  * LICENSE.txt file.
 6  
  */
 7  
 package org.mule.module.xml.filters;
 8  
 
 9  
 import org.mule.api.MuleMessage;
 10  
 import org.mule.api.lifecycle.Initialisable;
 11  
 import org.mule.api.lifecycle.InitialisationException;
 12  
 import org.mule.api.routing.filter.Filter;
 13  
 import org.mule.config.i18n.CoreMessages;
 14  
 import org.mule.module.xml.transformer.DelayedResult;
 15  
 import org.mule.module.xml.util.XMLUtils;
 16  
 import org.mule.util.IOUtils;
 17  
 import org.mule.util.StringUtils;
 18  
 
 19  
 import java.io.IOException;
 20  
 import java.io.InputStream;
 21  
 import java.util.Map;
 22  
 
 23  
 import javax.xml.stream.XMLInputFactory;
 24  
 import javax.xml.transform.Result;
 25  
 import javax.xml.transform.Source;
 26  
 import javax.xml.transform.dom.DOMResult;
 27  
 import javax.xml.transform.stream.StreamSource;
 28  
 import javax.xml.validation.Schema;
 29  
 import javax.xml.validation.SchemaFactory;
 30  
 import javax.xml.validation.Validator;
 31  
 
 32  
 import org.apache.commons.logging.Log;
 33  
 import org.apache.commons.logging.LogFactory;
 34  
 import org.w3c.dom.ls.LSResourceResolver;
 35  
 import org.xml.sax.ErrorHandler;
 36  
 import org.xml.sax.SAXException;
 37  
 
 38  
 /**
 39  
  * Filter for schema validation.
 40  
  * 
 41  
  * @author Ryan Heaton
 42  
  */
 43  0
 public class SchemaValidationFilter extends AbstractJaxpFilter implements Filter, Initialisable
 44  
 {
 45  
     public static final String DEFAULT_SCHEMA_LANGUAGE = "http://www.w3.org/2001/XMLSchema";
 46  
 
 47  0
     protected transient Log logger = LogFactory.getLog(getClass());
 48  
     private String schemaLocations;
 49  0
     private String schemaLanguage = DEFAULT_SCHEMA_LANGUAGE;
 50  
     private Schema schemaObject;
 51  
     private ErrorHandler errorHandler;
 52  
     private Map<String, Boolean> validatorFeatures;
 53  
     private Map<String, Object> validatorProperties;
 54  
     private LSResourceResolver resourceResolver;
 55  0
     private boolean useStaxSource = false;
 56  0
     private boolean returnResult = true;
 57  0
     private XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
 58  
 
 59  
     /**
 60  
      * Accepts the message if schema validation passes.
 61  
      * 
 62  
      * @param message The message.
 63  
      * @return Whether the message passes schema validation.
 64  
      */
 65  
     public boolean accept(MuleMessage message)
 66  
     {
 67  
         Source source;
 68  
         try
 69  
         {
 70  0
             source = loadSource(message);
 71  
         }
 72  0
         catch (Exception e)
 73  
         {
 74  0
             if (e instanceof RuntimeException)
 75  
             {
 76  0
                 throw (RuntimeException) e;
 77  
             }
 78  
             
 79  0
             if (logger.isInfoEnabled())
 80  
             {
 81  0
                 logger.info("SchemaValidationFilter rejected a message because there was a problem interpreting the payload as XML.", e);
 82  
             }
 83  0
             return false;
 84  0
         }
 85  
 
 86  0
         if (source == null)
 87  
         {
 88  0
             if (logger.isInfoEnabled())
 89  
             {
 90  0
                 logger.info("SchemaValidationFilter rejected a message because the XML source was null.");
 91  
             }
 92  0
             return false;
 93  
         }
 94  
 
 95  
         
 96  0
         DOMResult result = null;
 97  
         
 98  
         try
 99  
         {
 100  0
             if (returnResult) 
 101  
             {
 102  0
                 result = new DOMResult();
 103  0
                 createValidator().validate(source, result);
 104  
             }
 105  
             else 
 106  
             {
 107  0
                 createValidator().validate(source);
 108  
             }
 109  
         }
 110  0
         catch (SAXException e)
 111  
         {
 112  0
             if (logger.isDebugEnabled())
 113  
             {
 114  0
                 logger.debug(
 115  
                     "SchemaValidationFilter rejected a message because it apparently failed to validate against the schema.",
 116  
                     e);
 117  
             }
 118  0
             return false;
 119  
         }
 120  0
         catch (IOException e)
 121  
         {
 122  0
             if (logger.isInfoEnabled())
 123  
             {
 124  0
                 logger.info(
 125  
                     "SchemaValidationFilter rejected a message because there was a problem reading the XML.",
 126  
                     e);
 127  
             }
 128  0
             return false;
 129  
         }
 130  
         finally 
 131  
         {
 132  0
             if (result != null && result.getNode() != null)
 133  
             {
 134  0
                 message.setPayload(result.getNode());
 135  
             }
 136  
         }
 137  
         
 138  0
         if (logger.isDebugEnabled())
 139  
         {
 140  0
             logger.debug("SchemaValidationFilter accepted the message.");
 141  
         }
 142  
 
 143  0
         return true;
 144  
     }
 145  
 
 146  
     /**
 147  
      * Get a delayed result.
 148  
      * 
 149  
      * @param source The source.
 150  
      * @return The result.
 151  
      */
 152  
     protected Object getDelayedResult(final Source source)
 153  
     {
 154  0
         return new DelayedResult()
 155  0
         {
 156  
             private String systemId;
 157  
 
 158  
             public void write(Result result) throws Exception
 159  
             {
 160  0
                 createValidator().validate(source, result);
 161  0
             }
 162  
 
 163  
             public String getSystemId()
 164  
             {
 165  0
                 return systemId;
 166  
             }
 167  
 
 168  
             public void setSystemId(String systemId)
 169  
             {
 170  0
                 this.systemId = systemId;
 171  0
             }
 172  
         };
 173  
     }
 174  
 
 175  
     /**
 176  
      * Load the source from the specified object.
 177  
      * 
 178  
      * @param msg Encompassing message
 179  
      * @return The source
 180  
      */
 181  
     protected Source loadSource(MuleMessage msg) throws Exception
 182  
     {
 183  0
         Object payload = msg.getPayload();
 184  0
         if (returnResult)
 185  
         {
 186  
             // Validation requires that a DOM goes in for a DOM to go out
 187  0
             payload = toDOMNode(payload);
 188  
         }
 189  0
         return XMLUtils.toXmlSource(getXMLInputFactory(), isUseStaxSource(), payload);
 190  
     }
 191  
 
 192  
     public void initialise() throws InitialisationException
 193  
     {
 194  0
         super.initialise();
 195  
         
 196  0
         if (getSchemaObject() == null)
 197  
         {
 198  0
             if (schemaLocations == null)
 199  
             {
 200  0
                 throw new InitialisationException(CoreMessages.objectIsNull("schemaLocations"), this);
 201  
             }
 202  
 
 203  0
             String[] split = StringUtils.splitAndTrim(schemaLocations, ",");
 204  0
             Source[] schemas = new Source[split.length];
 205  0
             for (int i = 0; i < split.length; i++)
 206  
             {
 207  0
                 String loc = split[i];
 208  
                 InputStream schemaStream;
 209  
                 try
 210  
                 {
 211  0
                     schemaStream = loadSchemaStream(loc);
 212  
                 }
 213  0
                 catch (IOException e)
 214  
                 {
 215  0
                     throw new InitialisationException(e, this);
 216  0
                 }
 217  
     
 218  0
                 if (schemaStream == null)
 219  
                 {
 220  0
                     throw new InitialisationException(CoreMessages.failedToLoad(loc), this);
 221  
                 }
 222  
                 
 223  0
                 schemas[i] = new StreamSource(schemaStream);
 224  
             }
 225  
             
 226  0
             SchemaFactory schemaFactory = SchemaFactory.newInstance(getSchemaLanguage());
 227  
 
 228  0
             if (logger.isInfoEnabled())
 229  
             {
 230  0
                 logger.info("Schema factory implementation: " + schemaFactory);
 231  
             }
 232  
 
 233  0
             if (this.errorHandler != null)
 234  
             {
 235  0
                 schemaFactory.setErrorHandler(this.errorHandler);
 236  
             }
 237  
 
 238  0
             if (this.resourceResolver != null)
 239  
             {
 240  0
                 schemaFactory.setResourceResolver(this.resourceResolver);
 241  
             }
 242  
 
 243  
             Schema schema;
 244  
             try
 245  
             {
 246  0
                 schema = schemaFactory.newSchema(schemas);
 247  
             }
 248  0
             catch (SAXException e)
 249  
             {
 250  0
                 throw new InitialisationException(e, this);
 251  0
             }
 252  
 
 253  0
             setSchemaObject(schema);
 254  
         }
 255  
 
 256  0
         if (getSchemaObject() == null)
 257  
         {
 258  0
             throw new InitialisationException(CoreMessages.objectIsNull("schemaObject"), this);
 259  
         }
 260  0
     }
 261  
 
 262  
     protected InputStream loadSchemaStream(String schemaLocation) throws IOException
 263  
     {
 264  0
         return IOUtils.getResourceAsStream(schemaLocation, getClass());
 265  
     }
 266  
 
 267  
     /**
 268  
      * Create a validator.
 269  
      * 
 270  
      * @return The validator.
 271  
      */
 272  
     public Validator createValidator() throws SAXException
 273  
     {
 274  0
         Validator validator = getSchemaObject().newValidator();
 275  
 
 276  0
         if (this.validatorFeatures != null)
 277  
         {
 278  0
             for (Map.Entry<String, Boolean> feature : this.validatorFeatures.entrySet())
 279  
             {
 280  0
                 validator.setFeature(feature.getKey(), feature.getValue());
 281  
             }
 282  
         }
 283  
 
 284  0
         if (this.validatorProperties != null)
 285  
         {
 286  0
             for (Map.Entry<String, Object> validatorProperty : this.validatorProperties.entrySet())
 287  
             {
 288  0
                 validator.setProperty(validatorProperty.getKey(), validatorProperty.getValue());
 289  
             }
 290  
         }
 291  
 
 292  0
         return validator;
 293  
     }
 294  
 
 295  
     public String getSchemaLocations()
 296  
     {
 297  0
         return schemaLocations;
 298  
     }
 299  
 
 300  
     public void setSchemaLocations(String schemaLocations)
 301  
     {
 302  0
         this.schemaLocations = schemaLocations;
 303  0
     }
 304  
 
 305  
     public String getSchemaLanguage()
 306  
     {
 307  0
         return schemaLanguage;
 308  
     }
 309  
 
 310  
     public void setSchemaLanguage(String schemaLanguage)
 311  
     {
 312  0
         this.schemaLanguage = schemaLanguage;
 313  0
     }
 314  
 
 315  
     public Schema getSchemaObject()
 316  
     {
 317  0
         return schemaObject;
 318  
     }
 319  
 
 320  
     public void setSchemaObject(Schema schemaObject)
 321  
     {
 322  0
         this.schemaObject = schemaObject;
 323  0
     }
 324  
 
 325  
     public ErrorHandler getErrorHandler()
 326  
     {
 327  0
         return errorHandler;
 328  
     }
 329  
 
 330  
     public void setErrorHandler(ErrorHandler errorHandler)
 331  
     {
 332  0
         this.errorHandler = errorHandler;
 333  0
     }
 334  
 
 335  
     public LSResourceResolver getResourceResolver()
 336  
     {
 337  0
         return resourceResolver;
 338  
     }
 339  
 
 340  
     public void setResourceResolver(LSResourceResolver resourceResolver)
 341  
     {
 342  0
         this.resourceResolver = resourceResolver;
 343  0
     }
 344  
 
 345  
     public Map<String, Boolean> getValidatorFeatures()
 346  
     {
 347  0
         return validatorFeatures;
 348  
     }
 349  
 
 350  
     public void setValidatorFeatures(Map<String, Boolean> validatorFeatures)
 351  
     {
 352  0
         this.validatorFeatures = validatorFeatures;
 353  0
     }
 354  
 
 355  
     public Map<String, Object> getValidatorProperties()
 356  
     {
 357  0
         return validatorProperties;
 358  
     }
 359  
 
 360  
     public void setValidatorProperties(Map<String, Object> validatorProperties)
 361  
     {
 362  0
         this.validatorProperties = validatorProperties;
 363  0
     }
 364  
 
 365  
     public XMLInputFactory getXMLInputFactory()
 366  
     {
 367  0
         return xmlInputFactory;
 368  
     }
 369  
 
 370  
     public void setXMLInputFactory(XMLInputFactory xmlInputFactory)
 371  
     {
 372  0
         this.xmlInputFactory = xmlInputFactory;
 373  0
     }
 374  
 
 375  
     public boolean isUseStaxSource()
 376  
     {
 377  0
         return useStaxSource;
 378  
     }
 379  
 
 380  
     public void setUseStaxSource(boolean useStaxSource)
 381  
     {
 382  0
         this.useStaxSource = useStaxSource;
 383  0
     }
 384  
 
 385  
     public boolean isReturnResult()
 386  
     {
 387  0
         return returnResult;
 388  
     }
 389  
 
 390  
     public void setReturnResult(boolean returnResult)
 391  
     {
 392  0
         this.returnResult = returnResult;
 393  0
     }
 394  
 }