/* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.activiti.engine.impl.util.xml; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.activiti.engine.ActivitiException; import org.activiti.engine.impl.util.io.InputStreamSource; import org.activiti.engine.impl.util.io.ResourceStreamSource; import org.activiti.engine.impl.util.io.StreamSource; import org.activiti.engine.impl.util.io.StringStreamSource; import org.activiti.engine.impl.util.io.UrlStreamSource; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; /** * @author Tom Baeyens */ public class Parse extends DefaultHandler { private static final Logger LOGGER = Logger.getLogger(Parse.class.getName()); private static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; private static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; private static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; private static final String NEW_LINE = System.getProperty("line.separator"); protected Parser parser; protected String name; protected StreamSource streamSource; protected Element rootElement = null; protected List<Problem> errors = new ArrayList<Problem>(); protected List<Problem> warnings = new ArrayList<Problem>(); protected String schemaResource; public Parse(Parser parser) { this.parser = parser; } public Parse name(String name) { this.name = name; return this; } public Parse sourceInputStream(InputStream inputStream) { if (name==null) { name("inputStream"); } setStreamSource(new InputStreamSource(inputStream)); return this; } public Parse sourceResource(String resource) { return sourceResource(resource, null); } public Parse sourceUrl(URL url) { if (name==null) { name(url.toString()); } setStreamSource(new UrlStreamSource(url)); return this; } public Parse sourceUrl(String url) { try { return sourceUrl(new URL(url)); } catch (MalformedURLException e) { throw new ActivitiException("malformed url: "+url, e); } } public Parse sourceResource(String resource, ClassLoader classLoader) { if (name==null) { name(resource); } setStreamSource(new ResourceStreamSource(resource, classLoader)); return this; } public Parse sourceString(String string) { if (name==null) { name("string"); } setStreamSource(new StringStreamSource(string)); return this; } protected void setStreamSource(StreamSource streamSource) { if (this.streamSource!=null) { throw new ActivitiException("invalid: multiple sources "+this.streamSource+" and "+streamSource); } this.streamSource = streamSource; } public Parse execute() { try { InputStream inputStream = streamSource.getInputStream(); if (schemaResource == null) { // must be done before parser is created parser.getSaxParserFactory().setNamespaceAware(false); parser.getSaxParserFactory().setValidating(false); } SAXParser saxParser = parser.getSaxParser(); if (schemaResource != null) { saxParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA); saxParser.setProperty(JAXP_SCHEMA_SOURCE, schemaResource); } saxParser.parse(inputStream, new ParseHandler(this)); } catch (Exception e) { // any exception can happen (Activiti, Io, etc.) throw new ActivitiException("couldn't parse '"+name+"': "+e.getMessage(), e); } return this; } public Element getRootElement() { return rootElement; } public List<Problem> getProblems() { return errors; } public void addError(SAXParseException e) { errors.add(new Problem(e, name)); } public void addError(String errorMessage, Element element) { errors.add(new Problem(errorMessage, name, element)); } public boolean hasErrors() { return errors != null && !errors.isEmpty(); } public void addWarning(SAXParseException e) { warnings.add(new Problem(e, name)); } public void addWarning(String errorMessage, Element element) { warnings.add(new Problem(errorMessage, name, element)); } public boolean hasWarnings() { return warnings != null && !warnings.isEmpty(); } public void logWarnings() { for (Problem warning : warnings) { LOGGER.warning(warning.toString()); } } public void throwActivitiExceptionForErrors() { StringBuilder strb = new StringBuilder(); for (Problem error : errors) { strb.append(error.toString()); strb.append(NEW_LINE); } throw new ActivitiException(strb.toString()); } public void setSchemaResource(String schemaResource) { SAXParserFactory saxParserFactory = parser.getSaxParserFactory(); saxParserFactory.setNamespaceAware(true); saxParserFactory.setValidating(true); try { saxParserFactory.setFeature("http://xml.org/sax/features/namespace-prefixes", true); } catch (Exception e) { LOGGER.warning(e.getMessage()); } this.schemaResource = schemaResource; } }