001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.processor.validation;
018    
019    import java.io.File;
020    import java.io.IOException;
021    import java.net.URL;
022    
023    import javax.xml.XMLConstants;
024    import javax.xml.transform.Source;
025    import javax.xml.transform.dom.DOMResult;
026    import javax.xml.transform.dom.DOMSource;
027    import javax.xml.validation.Schema;
028    import javax.xml.validation.SchemaFactory;
029    import javax.xml.validation.Validator;
030    
031    import org.xml.sax.SAXException;
032    
033    import org.apache.camel.Exchange;
034    import org.apache.camel.Processor;
035    
036    /**
037     * A processor which validates the XML version of the inbound message body
038     * against some schema either in XSD or RelaxNG
039     * 
040     * @version $Revision: 35332 $
041     */
042    public class ValidatingProcessor implements Processor {
043        private Schema schema;
044        private ValidatorErrorHandler errorHandler = new DefaultValidationErrorHandler();
045    
046        // for lazy creation of the Schema
047        private String schemaLanguage = XMLConstants.W3C_XML_SCHEMA_NS_URI;
048        private Source schemaSource;
049        private SchemaFactory schemaFactory;
050        private URL schemaUrl;
051        private File schemaFile;
052    
053        public void process(Exchange exchange) throws Exception {
054            Schema schema = getSchema();
055            Validator validator = schema.newValidator();
056    
057            Source source = exchange.getIn().getBody(DOMSource.class);
058            if (source == null) {
059                throw new NoXmlBodyValidationException(exchange);
060            }
061    
062            // create a new errorHandler and set it on the validator
063            errorHandler.reset();
064            validator.setErrorHandler(errorHandler);
065    
066            DOMResult result = new DOMResult();
067            validator.validate(source, result);
068    
069            errorHandler.handleErrors(exchange, schema, result);
070            /*
071             * Fault fault = exchange.createFault(); if (errorHandler.hasErrors()) { //
072             * set the schema and source document as properties on the fault
073             * fault.setProperty("org.apache.servicemix.schema", schema);
074             * fault.setProperty("org.apache.servicemix.xml", source);
075             * 
076             *//*
077                 * check if this error handler supports the capturing of error
078                 * messages.
079                 *//*
080                 * if (errorHandler.capturesMessages()) {
081                 * 
082                 *//*
083                 * In descending order of preference select a format to use. If
084                 * neither DOMSource, StringSource or String are supported throw a
085                 * messaging exception.
086                 *//*
087                 * if (errorHandler.supportsMessageFormat(DOMSource.class)) {
088                 * fault.setContent( (DOMSource)
089                 * errorHandler.getMessagesAs(DOMSource.class)); } else if
090                 * (errorHandler.supportsMessageFormat(StringSource.class)) {
091                 * fault.setContent(sourceTransformer.toDOMSource( (StringSource)
092                 * errorHandler.getMessagesAs(StringSource.class))); } else if
093                 * (errorHandler.supportsMessageFormat(String.class)) {
094                 * fault.setContent( sourceTransformer.toDOMSource( new
095                 * StringSource( (String)
096                 * errorHandler.getMessagesAs(String.class)))); } else { throw new
097                 * MessagingException("MessageAwareErrorHandler implementation " +
098                 * errorHandler.getClass().getName() + " does not support a
099                 * compatible error message format."); } } else {
100                 *//*
101                 * we can't do much here if the ErrorHandler implementation does not
102                 * support capturing messages
103                 *//*
104                 * fault.setContent(new DOMSource(result.getNode(),
105                 * result.getSystemId())); } throw new FaultException("Failed to
106                 * validate against schema: " + schema, exchange, fault); } else { //
107                 * Retrieve the ouput of the validation // as it may have been
108                 * changed by the validator out.setContent(new
109                 * DOMSource(result.getNode(), result.getSystemId())); } }
110                 */
111        }
112    
113        // Properties
114        // -----------------------------------------------------------------------
115    
116        public Schema getSchema() throws IOException, SAXException {
117            if (schema == null) {
118                schema = createSchema();
119            }
120            return schema;
121        }
122    
123        public void setSchema(Schema schema) {
124            this.schema = schema;
125        }
126    
127        public String getSchemaLanguage() {
128            return schemaLanguage;
129        }
130    
131        public void setSchemaLanguage(String schemaLanguage) {
132            this.schemaLanguage = schemaLanguage;
133        }
134    
135        public Source getSchemaSource() throws IOException {
136            if (schemaSource == null) {
137                schemaSource = createSchemaSource();
138            }
139            return schemaSource;
140        }
141    
142        public void setSchemaSource(Source schemaSource) {
143            this.schemaSource = schemaSource;
144        }
145    
146        public URL getSchemaUrl() {
147            return schemaUrl;
148        }
149    
150        public void setSchemaUrl(URL schemaUrl) {
151            this.schemaUrl = schemaUrl;
152        }
153    
154        public File getSchemaFile() {
155            return schemaFile;
156        }
157    
158        public void setSchemaFile(File schemaFile) {
159            this.schemaFile = schemaFile;
160        }
161    
162        public SchemaFactory getSchemaFactory() {
163            if (schemaFactory == null) {
164                schemaFactory = createSchemaFactory();
165            }
166            return schemaFactory;
167        }
168    
169        public void setSchemaFactory(SchemaFactory schemaFactory) {
170            this.schemaFactory = schemaFactory;
171        }
172    
173        public ValidatorErrorHandler getErrorHandler() {
174            return errorHandler;
175        }
176    
177        public void setErrorHandler(ValidatorErrorHandler errorHandler) {
178            this.errorHandler = errorHandler;
179        }
180    
181        // Implementation methods
182        // -----------------------------------------------------------------------
183    
184        protected SchemaFactory createSchemaFactory() {
185            return SchemaFactory.newInstance(schemaLanguage);
186        }
187    
188        protected Source createSchemaSource() throws IOException {
189            throw new IllegalArgumentException("You must specify a schema, "
190                                               + "schemaFile, schemaSource or schemaUrl property");
191        }
192    
193        protected Schema createSchema() throws SAXException, IOException {
194            SchemaFactory factory = getSchemaFactory();
195    
196            URL url = getSchemaUrl();
197            if (url != null) {
198                return factory.newSchema(url);
199            }
200            File file = getSchemaFile();
201            if (file != null) {
202                return factory.newSchema(file);
203            }
204            return factory.newSchema(getSchemaSource());
205        }
206    
207    }