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.Result;
025 import javax.xml.transform.Source;
026 import javax.xml.transform.dom.DOMResult;
027 import javax.xml.transform.dom.DOMSource;
028 import javax.xml.transform.sax.SAXResult;
029 import javax.xml.transform.sax.SAXSource;
030 import javax.xml.validation.Schema;
031 import javax.xml.validation.SchemaFactory;
032 import javax.xml.validation.Validator;
033
034 import org.xml.sax.SAXException;
035
036 import org.apache.camel.Exchange;
037 import org.apache.camel.Processor;
038
039 /**
040 * A processor which validates the XML version of the inbound message body
041 * against some schema either in XSD or RelaxNG
042 *
043 * @version $Revision: 787958 $
044 */
045 public class ValidatingProcessor implements Processor {
046 // for lazy creation of the Schema
047 private String schemaLanguage = XMLConstants.W3C_XML_SCHEMA_NS_URI;
048 private Schema schema;
049 private Source schemaSource;
050 private SchemaFactory schemaFactory;
051 private URL schemaUrl;
052 private File schemaFile;
053 private ValidatorErrorHandler errorHandler = new DefaultValidationErrorHandler();
054 private boolean useDom;
055
056 public void process(Exchange exchange) throws Exception {
057 Schema schema = getSchema();
058 Validator validator = schema.newValidator();
059
060 Source source;
061 Result result;
062 if (useDom) {
063 source = exchange.getIn().getBody(DOMSource.class);
064 result = new DOMResult();
065 } else {
066 source = exchange.getIn().getBody(SAXSource.class);
067 result = new SAXResult();
068 }
069 if (source == null) {
070 throw new NoXmlBodyValidationException(exchange);
071 }
072
073 // create a new errorHandler and set it on the validator
074 // must be a local instance to avoid problems with concurrency (to be thread safe)
075 ValidatorErrorHandler handler = errorHandler.getClass().newInstance();
076 validator.setErrorHandler(handler);
077
078 validator.validate(source, result);
079
080 handler.handleErrors(exchange, schema, result);
081 }
082
083 public void loadSchema() throws Exception {
084 // force loading of schema
085 schema = createSchema();
086 }
087
088 // Properties
089 // -----------------------------------------------------------------------
090
091 public Schema getSchema() throws IOException, SAXException {
092 if (schema == null) {
093 schema = createSchema();
094 }
095 return schema;
096 }
097
098 public void setSchema(Schema schema) {
099 this.schema = schema;
100 }
101
102 public String getSchemaLanguage() {
103 return schemaLanguage;
104 }
105
106 public void setSchemaLanguage(String schemaLanguage) {
107 this.schemaLanguage = schemaLanguage;
108 }
109
110 public Source getSchemaSource() throws IOException {
111 if (schemaSource == null) {
112 schemaSource = createSchemaSource();
113 }
114 return schemaSource;
115 }
116
117 public void setSchemaSource(Source schemaSource) {
118 this.schemaSource = schemaSource;
119 }
120
121 public URL getSchemaUrl() {
122 return schemaUrl;
123 }
124
125 public void setSchemaUrl(URL schemaUrl) {
126 this.schemaUrl = schemaUrl;
127 }
128
129 public File getSchemaFile() {
130 return schemaFile;
131 }
132
133 public void setSchemaFile(File schemaFile) {
134 this.schemaFile = schemaFile;
135 }
136
137 public SchemaFactory getSchemaFactory() {
138 if (schemaFactory == null) {
139 schemaFactory = createSchemaFactory();
140 }
141 return schemaFactory;
142 }
143
144 public void setSchemaFactory(SchemaFactory schemaFactory) {
145 this.schemaFactory = schemaFactory;
146 }
147
148 public ValidatorErrorHandler getErrorHandler() {
149 return errorHandler;
150 }
151
152 public void setErrorHandler(ValidatorErrorHandler errorHandler) {
153 this.errorHandler = errorHandler;
154 }
155
156 public boolean isUseDom() {
157 return useDom;
158 }
159
160 /**
161 * Sets whether DOMSource and DOMResult should be used, or
162 * SaxSource and SaxResult.
163 *
164 * @param useDom true to use DOM otherwise Sax is used
165 */
166 public void setUseDom(boolean useDom) {
167 this.useDom = useDom;
168 }
169
170 // Implementation methods
171 // -----------------------------------------------------------------------
172
173 protected SchemaFactory createSchemaFactory() {
174 return SchemaFactory.newInstance(schemaLanguage);
175 }
176
177 protected Source createSchemaSource() throws IOException {
178 throw new IllegalArgumentException("You must specify either a schema, schemaFile, schemaSource or schemaUrl property");
179 }
180
181 protected Schema createSchema() throws SAXException, IOException {
182 SchemaFactory factory = getSchemaFactory();
183
184 URL url = getSchemaUrl();
185 if (url != null) {
186 return factory.newSchema(url);
187 }
188 File file = getSchemaFile();
189 if (file != null) {
190 return factory.newSchema(file);
191 }
192 return factory.newSchema(getSchemaSource());
193 }
194
195 }