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: 768342 $
041     */
042    public class ValidatingProcessor implements Processor {
043        // for lazy creation of the Schema
044        private String schemaLanguage = XMLConstants.W3C_XML_SCHEMA_NS_URI;
045        private Schema schema;
046        private Source schemaSource;
047        private SchemaFactory schemaFactory;
048        private URL schemaUrl;
049        private File schemaFile;
050        private ValidatorErrorHandler errorHandler = new DefaultValidationErrorHandler();
051    
052        public void process(Exchange exchange) throws Exception {
053            Schema schema = getSchema();
054            Validator validator = schema.newValidator();
055    
056            Source source = exchange.getIn().getBody(DOMSource.class);
057            if (source == null) {
058                throw new NoXmlBodyValidationException(exchange);
059            }
060    
061            // create a new errorHandler and set it on the validator
062            // must be a local instance to avoid problems with concurrency (to be thread safe)
063            ValidatorErrorHandler handler = errorHandler.getClass().newInstance();
064            validator.setErrorHandler(handler);
065    
066            DOMResult result = new DOMResult();
067            validator.validate(source, result);
068    
069            handler.handleErrors(exchange, schema, result);
070        }
071    
072        public void loadSchema() throws Exception {
073            // force loading of schema
074            schema = createSchema();
075        }
076    
077        // Properties
078        // -----------------------------------------------------------------------
079    
080        public Schema getSchema() throws IOException, SAXException {
081            if (schema == null) {
082                schema = createSchema();
083            }
084            return schema;
085        }
086    
087        public void setSchema(Schema schema) {
088            this.schema = schema;
089        }
090    
091        public String getSchemaLanguage() {
092            return schemaLanguage;
093        }
094    
095        public void setSchemaLanguage(String schemaLanguage) {
096            this.schemaLanguage = schemaLanguage;
097        }
098    
099        public Source getSchemaSource() throws IOException {
100            if (schemaSource == null) {
101                schemaSource = createSchemaSource();
102            }
103            return schemaSource;
104        }
105    
106        public void setSchemaSource(Source schemaSource) {
107            this.schemaSource = schemaSource;
108        }
109    
110        public URL getSchemaUrl() {
111            return schemaUrl;
112        }
113    
114        public void setSchemaUrl(URL schemaUrl) {
115            this.schemaUrl = schemaUrl;
116        }
117    
118        public File getSchemaFile() {
119            return schemaFile;
120        }
121    
122        public void setSchemaFile(File schemaFile) {
123            this.schemaFile = schemaFile;
124        }
125    
126        public SchemaFactory getSchemaFactory() {
127            if (schemaFactory == null) {
128                schemaFactory = createSchemaFactory();
129            }
130            return schemaFactory;
131        }
132    
133        public void setSchemaFactory(SchemaFactory schemaFactory) {
134            this.schemaFactory = schemaFactory;
135        }
136    
137        public ValidatorErrorHandler getErrorHandler() {
138            return errorHandler;
139        }
140    
141        public void setErrorHandler(ValidatorErrorHandler errorHandler) {
142            this.errorHandler = errorHandler;
143        }
144    
145        // Implementation methods
146        // -----------------------------------------------------------------------
147    
148        protected SchemaFactory createSchemaFactory() {
149            return SchemaFactory.newInstance(schemaLanguage);
150        }
151    
152        protected Source createSchemaSource() throws IOException {
153            throw new IllegalArgumentException("You must specify either a schema, schemaFile, schemaSource or schemaUrl property");
154        }
155    
156        protected Schema createSchema() throws SAXException, IOException {
157            SchemaFactory factory = getSchemaFactory();
158    
159            URL url = getSchemaUrl();
160            if (url != null) {
161                return factory.newSchema(url);
162            }
163            File file = getSchemaFile();
164            if (file != null) {
165                return factory.newSchema(file);
166            }
167            return factory.newSchema(getSchemaSource());
168        }
169    
170    }