001 // Copyright 2004, 2005 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.hivemind.parse;
016
017 import java.io.IOException;
018 import java.net.URL;
019
020 import javax.xml.parsers.FactoryConfigurationError;
021 import javax.xml.parsers.ParserConfigurationException;
022 import javax.xml.parsers.SAXParser;
023 import javax.xml.parsers.SAXParserFactory;
024
025 import org.apache.commons.logging.Log;
026 import org.apache.commons.logging.LogFactory;
027 import org.apache.hivemind.ApplicationRuntimeException;
028 import org.apache.hivemind.ClassResolver;
029 import org.apache.hivemind.ErrorHandler;
030 import org.apache.hivemind.Resource;
031 import org.xml.sax.InputSource;
032 import org.xml.sax.SAXException;
033
034 /**
035 * The XmlResourceProcessor processes XML {@link Resource resources} using the
036 * {@link DescriptorParser} which is used as a SAX ContentHandler. The result of
037 * {@link #processResource(Resource) processing a resource} is a {@link ModuleDescriptor}.
038 *
039 * @see org.apache.hivemind.parse.DescriptorParser
040 * @see org.apache.hivemind.ModuleDescriptorProvider
041 * @since 1.1
042 * @author Knut Wannheden
043 */
044 public class XmlResourceProcessor
045 {
046 private static final Log LOG = LogFactory.getLog(XmlResourceProcessor.class);
047
048 protected ClassResolver _resolver;
049
050 protected ErrorHandler _errorHandler;
051
052 private DescriptorParser _contentHandler;
053
054 private SAXParser _saxParser;
055
056 public XmlResourceProcessor(ClassResolver resolver, ErrorHandler errorHandler)
057 {
058 _resolver = resolver;
059 _errorHandler = errorHandler;
060 }
061
062 /**
063 * Initializes the {@link DescriptorParser parser},
064 * {@link #processResource(Resource) processes} the Resource, resets the parser, and finally
065 * returns the parsed {@link ModuleDescriptor}.
066 *
067 * @throws ApplicationRuntimeException
068 * Thrown if errors are encountered while parsing the resource.
069 */
070 public ModuleDescriptor processResource(Resource resource)
071 {
072 if (_contentHandler == null)
073 _contentHandler = new DescriptorParser(_errorHandler);
074
075 _contentHandler.initialize(resource, _resolver);
076
077 try
078 {
079 if (LOG.isDebugEnabled())
080 LOG.debug("Parsing " + resource);
081
082 ModuleDescriptor descriptor = parseResource(resource, getSAXParser(), _contentHandler);
083
084 if (LOG.isDebugEnabled())
085 LOG.debug("Result: " + descriptor);
086
087 return descriptor;
088 }
089 catch (ApplicationRuntimeException e)
090 {
091 throw e;
092 }
093 catch (Exception e)
094 {
095 _saxParser = null;
096
097 throw new ApplicationRuntimeException(
098 ParseMessages.errorReadingDescriptor(resource, e), resource, _contentHandler
099 .getLocation(), e);
100 }
101 finally
102 {
103 _contentHandler.resetParser();
104 }
105 }
106
107 /**
108 * Returns the ModuleDescriptor obtained by parsing the specified Resource using the given
109 * {@link SAXParser} and {@link DescriptorParser}. Called by {@link #processResource(Resource)}
110 * after the DescriptorParser has been
111 * {@link DescriptorParser#initialize(Resource, ClassResolver) initialized}. Suitable for
112 * overriding by subclasses.
113 */
114 protected ModuleDescriptor parseResource(Resource resource, SAXParser parser,
115 DescriptorParser contentHandler) throws SAXException, IOException
116 {
117 InputSource source = getInputSource(resource);
118
119 parser.parse(source, contentHandler);
120
121 return contentHandler.getModuleDescriptor();
122 }
123
124 private InputSource getInputSource(Resource resource)
125 {
126 try
127 {
128 URL url = resource.getResourceURL();
129
130 return new InputSource(url.openStream());
131 }
132 catch (Exception e)
133 {
134 throw new ApplicationRuntimeException(ParseMessages.missingResource(resource),
135 resource, null, e);
136 }
137 }
138
139 private SAXParser getSAXParser() throws ParserConfigurationException, SAXException,
140 FactoryConfigurationError
141 {
142 if (_saxParser == null)
143 _saxParser = SAXParserFactory.newInstance().newSAXParser();
144
145 return _saxParser;
146 }
147
148 }