001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.beans.factory.xml; 018 019import java.io.IOException; 020 021import org.xml.sax.EntityResolver; 022import org.xml.sax.InputSource; 023import org.xml.sax.SAXException; 024 025import org.springframework.lang.Nullable; 026import org.springframework.util.Assert; 027 028/** 029 * {@link EntityResolver} implementation that delegates to a {@link BeansDtdResolver} 030 * and a {@link PluggableSchemaResolver} for DTDs and XML schemas, respectively. 031 * 032 * @author Rob Harrop 033 * @author Juergen Hoeller 034 * @author Rick Evans 035 * @since 2.0 036 * @see BeansDtdResolver 037 * @see PluggableSchemaResolver 038 */ 039public class DelegatingEntityResolver implements EntityResolver { 040 041 /** Suffix for DTD files. */ 042 public static final String DTD_SUFFIX = ".dtd"; 043 044 /** Suffix for schema definition files. */ 045 public static final String XSD_SUFFIX = ".xsd"; 046 047 048 private final EntityResolver dtdResolver; 049 050 private final EntityResolver schemaResolver; 051 052 053 /** 054 * Create a new DelegatingEntityResolver that delegates to 055 * a default {@link BeansDtdResolver} and a default {@link PluggableSchemaResolver}. 056 * <p>Configures the {@link PluggableSchemaResolver} with the supplied 057 * {@link ClassLoader}. 058 * @param classLoader the ClassLoader to use for loading 059 * (can be {@code null}) to use the default ClassLoader) 060 */ 061 public DelegatingEntityResolver(@Nullable ClassLoader classLoader) { 062 this.dtdResolver = new BeansDtdResolver(); 063 this.schemaResolver = new PluggableSchemaResolver(classLoader); 064 } 065 066 /** 067 * Create a new DelegatingEntityResolver that delegates to 068 * the given {@link EntityResolver EntityResolvers}. 069 * @param dtdResolver the EntityResolver to resolve DTDs with 070 * @param schemaResolver the EntityResolver to resolve XML schemas with 071 */ 072 public DelegatingEntityResolver(EntityResolver dtdResolver, EntityResolver schemaResolver) { 073 Assert.notNull(dtdResolver, "'dtdResolver' is required"); 074 Assert.notNull(schemaResolver, "'schemaResolver' is required"); 075 this.dtdResolver = dtdResolver; 076 this.schemaResolver = schemaResolver; 077 } 078 079 080 @Override 081 @Nullable 082 public InputSource resolveEntity(@Nullable String publicId, @Nullable String systemId) 083 throws SAXException, IOException { 084 085 if (systemId != null) { 086 if (systemId.endsWith(DTD_SUFFIX)) { 087 return this.dtdResolver.resolveEntity(publicId, systemId); 088 } 089 else if (systemId.endsWith(XSD_SUFFIX)) { 090 return this.schemaResolver.resolveEntity(publicId, systemId); 091 } 092 } 093 094 // Fall back to the parser's default behavior. 095 return null; 096 } 097 098 099 @Override 100 public String toString() { 101 return "EntityResolver delegating " + XSD_SUFFIX + " to " + this.schemaResolver + 102 " and " + DTD_SUFFIX + " to " + this.dtdResolver; 103 } 104 105}