001: /*
002: * Copyright 2002-2007 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: * http://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:
017: package org.springframework.beans.factory.xml;
018:
019: import java.io.File;
020: import java.io.IOException;
021: import java.net.URL;
022: import java.net.URLDecoder;
023:
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026: import org.xml.sax.InputSource;
027: import org.xml.sax.SAXException;
028:
029: import org.springframework.core.io.Resource;
030: import org.springframework.core.io.ResourceLoader;
031:
032: /**
033: * EntityResolver implementation that tries to resolve entity references
034: * through a {@link org.springframework.core.io.ResourceLoader} (usually,
035: * relative to the resource base of an ApplicationContext), if applicable.
036: * Extends {@link DelegatingEntityResolver} to also provide DTD and XSD lookup.
037: *
038: * <p>Allows to use standard XML entities to include XML snippets into an
039: * application context definition, for example to split a large XML file
040: * into various modules. The include paths can be relative to the
041: * application context's resource base as usual, instead of relative
042: * to the JVM working directory (the XML parser's default).
043: *
044: * <p>Note: In addition to relative paths, every URL that specifies a
045: * file in the current system root, i.e. the JVM working directory,
046: * will be interpreted relative to the application context too.
047: *
048: * @author Juergen Hoeller
049: * @since 31.07.2003
050: * @see org.springframework.core.io.ResourceLoader
051: * @see org.springframework.context.ApplicationContext
052: */
053: public class ResourceEntityResolver extends DelegatingEntityResolver {
054:
055: private static final Log logger = LogFactory
056: .getLog(ResourceEntityResolver.class);
057:
058: private final ResourceLoader resourceLoader;
059:
060: /**
061: * Create a ResourceEntityResolver for the specified ResourceLoader
062: * (usually, an ApplicationContext).
063: * @param resourceLoader the ResourceLoader (or ApplicationContext)
064: * to load XML entity includes with
065: */
066: public ResourceEntityResolver(ResourceLoader resourceLoader) {
067: super (resourceLoader.getClassLoader());
068: this .resourceLoader = resourceLoader;
069: }
070:
071: public InputSource resolveEntity(String publicId, String systemId)
072: throws SAXException, IOException {
073: InputSource source = super .resolveEntity(publicId, systemId);
074: if (source == null && systemId != null) {
075: String resourcePath = null;
076: try {
077: String decodedSystemId = URLDecoder.decode(systemId);
078: String givenUrl = new URL(decodedSystemId).toString();
079: String systemRootUrl = new File("").toURL().toString();
080: // Try relative to resource base if currently in system root.
081: if (givenUrl.startsWith(systemRootUrl)) {
082: resourcePath = givenUrl.substring(systemRootUrl
083: .length());
084: }
085: } catch (Exception ex) {
086: // Typically a MalformedURLException or AccessControlException.
087: if (logger.isDebugEnabled()) {
088: logger.debug("Could not resolve XML entity ["
089: + systemId + "] against system root URL",
090: ex);
091: }
092: // No URL (or no resolvable URL) -> try relative to resource base.
093: resourcePath = systemId;
094: }
095: if (resourcePath != null) {
096: if (logger.isTraceEnabled()) {
097: logger.trace("Trying to locate XML entity ["
098: + systemId + "] as resource ["
099: + resourcePath + "]");
100: }
101: Resource resource = this .resourceLoader
102: .getResource(resourcePath);
103: source = new InputSource(resource.getInputStream());
104: source.setPublicId(publicId);
105: source.setSystemId(systemId);
106: if (logger.isDebugEnabled()) {
107: logger.debug("Found XML entity [" + systemId
108: + "]: " + resource);
109: }
110: }
111: }
112: return source;
113: }
114:
115: }
|