1 16 17 package org.springframework.beans.factory.xml; 18 19 import java.io.IOException ; 20 import java.io.InputStream ; 21 22 import javax.xml.parsers.ParserConfigurationException ; 23 24 import org.w3c.dom.Document ; 25 import org.xml.sax.EntityResolver ; 26 import org.xml.sax.ErrorHandler ; 27 import org.xml.sax.InputSource ; 28 import org.xml.sax.SAXException ; 29 import org.xml.sax.SAXParseException ; 30 31 import org.springframework.beans.BeanUtils; 32 import org.springframework.beans.factory.BeanDefinitionStoreException; 33 import org.springframework.beans.factory.parsing.EmptyReaderEventListener; 34 import org.springframework.beans.factory.parsing.FailFastProblemReporter; 35 import org.springframework.beans.factory.parsing.NullSourceExtractor; 36 import org.springframework.beans.factory.parsing.ProblemReporter; 37 import org.springframework.beans.factory.parsing.ReaderEventListener; 38 import org.springframework.beans.factory.parsing.SourceExtractor; 39 import org.springframework.beans.factory.support.AbstractBeanDefinitionReader; 40 import org.springframework.beans.factory.support.BeanDefinitionRegistry; 41 import org.springframework.core.Constants; 42 import org.springframework.core.io.DescriptiveResource; 43 import org.springframework.core.io.Resource; 44 import org.springframework.core.io.support.EncodedResource; 45 import org.springframework.util.Assert; 46 import org.springframework.util.ClassUtils; 47 import org.springframework.util.xml.SimpleSaxErrorHandler; 48 import org.springframework.util.xml.XmlValidationModeDetector; 49 50 74 public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader { 75 76 79 public static final int VALIDATION_NONE = 0; 80 81 84 public static final int VALIDATION_AUTO = XmlValidationModeDetector.VALIDATION_AUTO; 85 86 89 public static final int VALIDATION_DTD = XmlValidationModeDetector.VALIDATION_DTD; 90 91 94 public static final int VALIDATION_XSD = XmlValidationModeDetector.VALIDATION_XSD; 95 96 97 98 private static final Constants constants = new Constants(XmlBeanDefinitionReader.class); 99 100 private boolean namespaceAware; 101 102 private int validationMode = VALIDATION_AUTO; 103 104 private Class parserClass; 105 106 private Class documentReaderClass = DefaultBeanDefinitionDocumentReader.class; 107 108 private ProblemReporter problemReporter = new FailFastProblemReporter(); 109 110 private ReaderEventListener eventListener = new EmptyReaderEventListener(); 111 112 private SourceExtractor sourceExtractor = new NullSourceExtractor(); 113 114 private NamespaceHandlerResolver namespaceHandlerResolver; 115 116 private DocumentLoader documentLoader = new DefaultDocumentLoader(); 117 118 private EntityResolver entityResolver; 119 120 private ErrorHandler errorHandler = new SimpleSaxErrorHandler(logger); 121 122 private final XmlValidationModeDetector validationModeDetector = new XmlValidationModeDetector(); 123 124 125 130 public XmlBeanDefinitionReader(BeanDefinitionRegistry beanFactory) { 131 super(beanFactory); 132 133 if (getResourceLoader() != null) { 135 this.entityResolver = new ResourceEntityResolver(getResourceLoader()); 136 } 137 else { 138 this.entityResolver = new DelegatingEntityResolver(ClassUtils.getDefaultClassLoader()); 139 } 140 } 141 142 143 147 public void setNamespaceAware(boolean namespaceAware) { 148 this.namespaceAware = namespaceAware; 149 } 150 151 156 public void setValidating(boolean validating) { 157 this.validationMode = (validating ? VALIDATION_AUTO : VALIDATION_NONE); 158 } 159 160 163 public void setValidationModeName(String validationModeName) { 164 setValidationMode(constants.asNumber(validationModeName).intValue()); 165 } 166 167 170 public void setValidationMode(int validationMode) { 171 this.validationMode = validationMode; 172 } 173 174 180 public void setProblemReporter(ProblemReporter problemReporter) { 181 this.problemReporter = (problemReporter != null ? problemReporter : new FailFastProblemReporter()); 182 } 183 184 190 public void setEventListener(ReaderEventListener eventListener) { 191 this.eventListener = (eventListener != null ? eventListener : new EmptyReaderEventListener()); 192 } 193 194 200 public void setSourceExtractor(SourceExtractor sourceExtractor) { 201 this.sourceExtractor = (sourceExtractor != null ? sourceExtractor : new NullSourceExtractor()); 202 } 203 204 208 public void setNamespaceHandlerResolver(NamespaceHandlerResolver namespaceHandlerResolver) { 209 this.namespaceHandlerResolver = namespaceHandlerResolver; 210 } 211 212 216 public void setDocumentLoader(DocumentLoader documentLoader) { 217 this.documentLoader = (documentLoader != null ? documentLoader : new DefaultDocumentLoader()); 218 } 219 220 226 public void setEntityResolver(EntityResolver entityResolver) { 227 this.entityResolver = entityResolver; 228 } 229 230 238 public void setErrorHandler(ErrorHandler errorHandler) { 239 this.errorHandler = errorHandler; 240 } 241 242 249 public void setParserClass(Class parserClass) { 250 if (this.parserClass == null || !XmlBeanDefinitionParser.class.isAssignableFrom(parserClass)) { 251 throw new IllegalArgumentException ("'parserClass' must be an XmlBeanDefinitionParser"); 252 } 253 this.parserClass = parserClass; 254 } 255 256 264 public void setDocumentReaderClass(Class documentReaderClass) { 265 if (documentReaderClass == null || !BeanDefinitionDocumentReader.class.isAssignableFrom(documentReaderClass)) { 266 throw new IllegalArgumentException ( 267 "documentReaderClass must be an implementation of the BeanDefinitionDocumentReader interface"); 268 } 269 this.documentReaderClass = documentReaderClass; 270 } 271 272 273 279 public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { 280 return loadBeanDefinitions(new EncodedResource(resource)); 281 } 282 283 290 public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { 291 Assert.notNull(encodedResource, "EncodedResource must not be null"); 292 if (logger.isInfoEnabled()) { 293 logger.info("Loading XML bean definitions from " + encodedResource.getResource()); 294 } 295 296 try { 297 InputStream inputStream = encodedResource.getResource().getInputStream(); 298 try { 299 InputSource inputSource = new InputSource (inputStream); 300 if (encodedResource.getEncoding() != null) { 301 inputSource.setEncoding(encodedResource.getEncoding()); 302 } 303 return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); 304 } 305 finally { 306 inputStream.close(); 307 } 308 } 309 catch (IOException ex) { 310 throw new BeanDefinitionStoreException( 311 "IOException parsing XML document from " + encodedResource.getResource(), ex); 312 } 313 } 314 315 321 public int loadBeanDefinitions(InputSource inputSource) throws BeanDefinitionStoreException { 322 return loadBeanDefinitions(inputSource, "resource loaded through SAX InputSource"); 323 } 324 325 333 public int loadBeanDefinitions(InputSource inputSource, String resourceDescription) 334 throws BeanDefinitionStoreException { 335 336 return doLoadBeanDefinitions(inputSource, new DescriptiveResource(resourceDescription)); 337 } 338 339 340 347 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) 348 throws BeanDefinitionStoreException { 349 try { 350 int validationMode = getValidationModeForResource(resource); 351 Document doc = this.documentLoader.loadDocument( 352 inputSource, this.entityResolver, this.errorHandler, validationMode, this.namespaceAware); 353 return registerBeanDefinitions(doc, resource); 354 } 355 catch (BeanDefinitionStoreException ex) { 356 throw ex; 357 } 358 catch (SAXParseException ex) { 359 throw new XmlBeanDefinitionStoreException(resource.getDescription(), 360 "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex); 361 } 362 catch (SAXException ex) { 363 throw new XmlBeanDefinitionStoreException(resource.getDescription(), 364 "XML document from " + resource + " is invalid", ex); 365 } 366 catch (ParserConfigurationException ex) { 367 throw new BeanDefinitionStoreException(resource.getDescription(), 368 "Parser configuration exception parsing XML from " + resource, ex); 369 } 370 catch (IOException ex) { 371 throw new BeanDefinitionStoreException(resource.getDescription(), 372 "IOException parsing XML document from " + resource, ex); 373 } 374 catch (Throwable ex) { 375 throw new BeanDefinitionStoreException(resource.getDescription(), 376 "Unexpected exception parsing XML document from " + resource, ex); 377 } 378 } 379 380 381 386 private int getValidationModeForResource(Resource resource) { 387 if (this.validationMode != VALIDATION_AUTO) { 388 return this.validationMode; 389 } 390 int detectedMode = detectValidationMode(resource); 391 if (detectedMode != VALIDATION_AUTO) { 392 return detectedMode; 393 } 394 return VALIDATION_XSD; 398 } 399 400 406 protected int detectValidationMode(Resource resource) { 407 if (resource.isOpen()) { 408 throw new BeanDefinitionStoreException( 409 "Passed-in Resource [" + resource + "] contains an open stream: " + 410 "cannot determine validation mode automatically. Either pass in a Resource " + 411 "that is able to create fresh streams, or explicitly specify the validationMode " + 412 "on your XmlBeanDefinitionReader instance."); 413 } 414 415 InputStream inputStream; 416 try { 417 inputStream = resource.getInputStream(); 418 } 419 catch (IOException ex) { 420 throw new BeanDefinitionStoreException( 421 "Unable to determine validation mode for [" + resource + "]: cannot open InputStream. " + 422 "Did you attempt to load directly from a SAX InputSource without specifying the " + 423 "validationMode on your XmlBeanDefinitionReader instance?", ex); 424 } 425 426 try { 427 return this.validationModeDetector.detectValidationMode(inputStream); 428 } 429 catch (IOException ex) { 430 throw new BeanDefinitionStoreException("Unable to determine validation mode for [" + 431 resource + "]: an error occurred whilst reading from the InputStream.", ex); 432 } 433 } 434 435 448 public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { 449 if (this.parserClass != null) { 451 XmlBeanDefinitionParser parser = 452 (XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass); 453 return parser.registerBeanDefinitions(this, doc, resource); 454 } 455 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); 457 int countBefore = getBeanFactory().getBeanDefinitionCount(); 458 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); 459 return getBeanFactory().getBeanDefinitionCount() - countBefore; 460 } 461 462 468 protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() { 469 return (BeanDefinitionDocumentReader) BeanUtils.instantiateClass(this.documentReaderClass); 470 } 471 472 475 protected XmlReaderContext createReaderContext(Resource resource) { 476 NamespaceHandlerResolver resolver = this.namespaceHandlerResolver; 477 if (resolver == null) { 478 resolver = createDefaultNamespaceHandlerResolver(); 479 } 480 return new XmlReaderContext( 481 resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, resolver); 482 } 483 484 488 protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { 489 return new DefaultNamespaceHandlerResolver(getResourceLoader().getClassLoader()); 490 } 491 492 } 493 | Popular Tags |