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 }