EntityResolvers and DefaultNamespaceHandlerResolver support concurrent access now (SPR-5679)
This commit is contained in:
parent
e54a44b577
commit
10d8abea3b
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2007 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.beans.factory.xml;
|
package org.springframework.beans.factory.xml;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
@ -56,8 +57,8 @@ public class BeansDtdResolver implements EntityResolver {
|
||||||
}
|
}
|
||||||
if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
|
if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
|
||||||
int lastPathSeparator = systemId.lastIndexOf("/");
|
int lastPathSeparator = systemId.lastIndexOf("/");
|
||||||
for (int i = 0; i < DTD_NAMES.length; ++i) {
|
for (String DTD_NAME : DTD_NAMES) {
|
||||||
int dtdNameStart = systemId.indexOf(DTD_NAMES[i]);
|
int dtdNameStart = systemId.indexOf(DTD_NAME);
|
||||||
if (dtdNameStart > lastPathSeparator) {
|
if (dtdNameStart > lastPathSeparator) {
|
||||||
String dtdFile = systemId.substring(dtdNameStart);
|
String dtdFile = systemId.substring(dtdNameStart);
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
|
|
@ -78,7 +79,7 @@ public class BeansDtdResolver implements EntityResolver {
|
||||||
logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in class path", ex);
|
logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in class path", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -87,4 +88,10 @@ public class BeansDtdResolver implements EntityResolver {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "EntityResolver for DTDs " + Arrays.toString(DTD_NAMES);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,9 +17,9 @@
|
||||||
package org.springframework.beans.factory.xml;
|
package org.springframework.beans.factory.xml;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
@ -64,7 +64,7 @@ public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver
|
||||||
private final String handlerMappingsLocation;
|
private final String handlerMappingsLocation;
|
||||||
|
|
||||||
/** Stores the mappings from namespace URI to NamespaceHandler class name / instance */
|
/** Stores the mappings from namespace URI to NamespaceHandler class name / instance */
|
||||||
private Map<String, NamespaceHandler> handlerMappings;
|
private volatile Map<String, Object> handlerMappings;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -110,7 +110,7 @@ public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver
|
||||||
* @return the located {@link NamespaceHandler}, or <code>null</code> if none found
|
* @return the located {@link NamespaceHandler}, or <code>null</code> if none found
|
||||||
*/
|
*/
|
||||||
public NamespaceHandler resolve(String namespaceUri) {
|
public NamespaceHandler resolve(String namespaceUri) {
|
||||||
Map<String, NamespaceHandler> handlerMappings = getHandlerMappings();
|
Map<String, Object> handlerMappings = getHandlerMappings();
|
||||||
Object handlerOrClassName = handlerMappings.get(namespaceUri);
|
Object handlerOrClassName = handlerMappings.get(namespaceUri);
|
||||||
if (handlerOrClassName == null) {
|
if (handlerOrClassName == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -121,7 +121,7 @@ public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver
|
||||||
else {
|
else {
|
||||||
String className = (String) handlerOrClassName;
|
String className = (String) handlerOrClassName;
|
||||||
try {
|
try {
|
||||||
Class handlerClass = ClassUtils.forName(className, this.classLoader);
|
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
|
||||||
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
|
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
|
||||||
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
|
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
|
||||||
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
|
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
|
||||||
|
|
@ -145,23 +145,34 @@ public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver
|
||||||
/**
|
/**
|
||||||
* Load the specified NamespaceHandler mappings lazily.
|
* Load the specified NamespaceHandler mappings lazily.
|
||||||
*/
|
*/
|
||||||
private Map<String, NamespaceHandler> getHandlerMappings() {
|
private Map<String, Object> getHandlerMappings() {
|
||||||
if (this.handlerMappings == null) {
|
if (this.handlerMappings == null) {
|
||||||
try {
|
synchronized (this) {
|
||||||
Properties mappings =
|
if (this.handlerMappings == null) {
|
||||||
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
|
try {
|
||||||
if (logger.isDebugEnabled()) {
|
Properties mappings =
|
||||||
logger.debug("Loaded mappings [" + mappings + "]");
|
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Loaded NamespaceHandler mappings: " + mappings);
|
||||||
|
}
|
||||||
|
Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>();
|
||||||
|
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
|
||||||
|
this.handlerMappings = handlerMappings;
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.handlerMappings = new HashMap<String, NamespaceHandler>();
|
|
||||||
CollectionUtils.mergePropertiesIntoMap(mappings, this.handlerMappings);
|
|
||||||
}
|
|
||||||
catch (IOException ex) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.handlerMappings;
|
return this.handlerMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "NamespaceHandlerResolver using mappings " + getHandlerMappings();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2007 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -88,4 +88,11 @@ public class DelegatingEntityResolver implements EntityResolver {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "EntityResolver delegating " + XSD_SUFFIX + " to " + this.schemaResolver +
|
||||||
|
" and " + DTD_SUFFIX + " to " + this.dtdResolver;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2007 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,18 +17,20 @@
|
||||||
package org.springframework.beans.factory.xml;
|
package org.springframework.beans.factory.xml;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.xml.sax.EntityResolver;
|
import org.xml.sax.EntityResolver;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
import org.springframework.beans.FatalBeanException;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link EntityResolver} implementation that attempts to resolve schema URLs into
|
* {@link EntityResolver} implementation that attempts to resolve schema URLs into
|
||||||
|
|
@ -67,7 +69,7 @@ public class PluggableSchemaResolver implements EntityResolver {
|
||||||
private final String schemaMappingsLocation;
|
private final String schemaMappingsLocation;
|
||||||
|
|
||||||
/** Stores the mapping of schema URL -> local schema path */
|
/** Stores the mapping of schema URL -> local schema path */
|
||||||
private Properties schemaMappings;
|
private volatile Map<String, String> schemaMappings;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -104,7 +106,7 @@ public class PluggableSchemaResolver implements EntityResolver {
|
||||||
"] and system id [" + systemId + "]");
|
"] and system id [" + systemId + "]");
|
||||||
}
|
}
|
||||||
if (systemId != null) {
|
if (systemId != null) {
|
||||||
String resourceLocation = getSchemaMapping(systemId);
|
String resourceLocation = getSchemaMappings().get(systemId);
|
||||||
if (resourceLocation != null) {
|
if (resourceLocation != null) {
|
||||||
Resource resource = new ClassPathResource(resourceLocation, this.classLoader);
|
Resource resource = new ClassPathResource(resourceLocation, this.classLoader);
|
||||||
InputSource source = new InputSource(resource.getInputStream());
|
InputSource source = new InputSource(resource.getInputStream());
|
||||||
|
|
@ -119,24 +121,40 @@ public class PluggableSchemaResolver implements EntityResolver {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getSchemaMapping(String systemId) {
|
/**
|
||||||
|
* Load the specified schema mappings lazily.
|
||||||
|
*/
|
||||||
|
private Map<String, String> getSchemaMappings() {
|
||||||
if (this.schemaMappings == null) {
|
if (this.schemaMappings == null) {
|
||||||
if (logger.isDebugEnabled()) {
|
synchronized (this) {
|
||||||
logger.debug("Loading schema mappings from [" + this.schemaMappingsLocation + "]");
|
if (this.schemaMappings == null) {
|
||||||
}
|
if (logger.isDebugEnabled()) {
|
||||||
try {
|
logger.debug("Loading schema mappings from [" + this.schemaMappingsLocation + "]");
|
||||||
this.schemaMappings =
|
}
|
||||||
PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation, this.classLoader);
|
try {
|
||||||
if (logger.isDebugEnabled()) {
|
Properties mappings =
|
||||||
logger.debug("Loaded schema mappings: " + this.schemaMappings);
|
PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation, this.classLoader);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Loaded schema mappings: " + mappings);
|
||||||
|
}
|
||||||
|
Map<String, String> schemaMappings = new ConcurrentHashMap<String, String>();
|
||||||
|
CollectionUtils.mergePropertiesIntoMap(mappings, schemaMappings);
|
||||||
|
this.schemaMappings = schemaMappings;
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Unable to load schema mappings from location [" + this.schemaMappingsLocation + "]", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
|
||||||
throw new FatalBeanException(
|
|
||||||
"Unable to load schema mappings from location [" + this.schemaMappingsLocation + "]", ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return this.schemaMappings.getProperty(systemId);
|
return this.schemaMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "EntityResolver using mappings " + getSchemaMappings();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue