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