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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.beans.factory.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
|
@ -56,8 +57,8 @@ public class BeansDtdResolver implements EntityResolver {
|
|||
}
|
||||
if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
|
||||
int lastPathSeparator = systemId.lastIndexOf("/");
|
||||
for (int i = 0; i < DTD_NAMES.length; ++i) {
|
||||
int dtdNameStart = systemId.indexOf(DTD_NAMES[i]);
|
||||
for (String DTD_NAME : DTD_NAMES) {
|
||||
int dtdNameStart = systemId.indexOf(DTD_NAME);
|
||||
if (dtdNameStart > lastPathSeparator) {
|
||||
String dtdFile = systemId.substring(dtdNameStart);
|
||||
if (logger.isTraceEnabled()) {
|
||||
|
|
@ -87,4 +88,10 @@ public class BeansDtdResolver implements EntityResolver {
|
|||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -17,9 +17,9 @@
|
|||
package org.springframework.beans.factory.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
|
@ -64,7 +64,7 @@ public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver
|
|||
private final String handlerMappingsLocation;
|
||||
|
||||
/** 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
|
||||
*/
|
||||
public NamespaceHandler resolve(String namespaceUri) {
|
||||
Map<String, NamespaceHandler> handlerMappings = getHandlerMappings();
|
||||
Map<String, Object> handlerMappings = getHandlerMappings();
|
||||
Object handlerOrClassName = handlerMappings.get(namespaceUri);
|
||||
if (handlerOrClassName == null) {
|
||||
return null;
|
||||
|
|
@ -121,7 +121,7 @@ public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver
|
|||
else {
|
||||
String className = (String) handlerOrClassName;
|
||||
try {
|
||||
Class handlerClass = ClassUtils.forName(className, this.classLoader);
|
||||
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
|
||||
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
|
||||
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
|
||||
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
|
||||
|
|
@ -145,23 +145,34 @@ public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver
|
|||
/**
|
||||
* Load the specified NamespaceHandler mappings lazily.
|
||||
*/
|
||||
private Map<String, NamespaceHandler> getHandlerMappings() {
|
||||
private Map<String, Object> getHandlerMappings() {
|
||||
if (this.handlerMappings == null) {
|
||||
synchronized (this) {
|
||||
if (this.handlerMappings == null) {
|
||||
try {
|
||||
Properties mappings =
|
||||
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loaded mappings [" + mappings + "]");
|
||||
logger.debug("Loaded NamespaceHandler mappings: " + mappings);
|
||||
}
|
||||
this.handlerMappings = new HashMap<String, NamespaceHandler>();
|
||||
CollectionUtils.mergePropertiesIntoMap(mappings, this.handlerMappings);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -88,4 +88,11 @@ public class DelegatingEntityResolver implements EntityResolver {
|
|||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -17,18 +17,20 @@
|
|||
package org.springframework.beans.factory.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* {@link EntityResolver} implementation that attempts to resolve schema URLs into
|
||||
|
|
@ -67,7 +69,7 @@ public class PluggableSchemaResolver implements EntityResolver {
|
|||
private final String schemaMappingsLocation;
|
||||
|
||||
/** 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 + "]");
|
||||
}
|
||||
if (systemId != null) {
|
||||
String resourceLocation = getSchemaMapping(systemId);
|
||||
String resourceLocation = getSchemaMappings().get(systemId);
|
||||
if (resourceLocation != null) {
|
||||
Resource resource = new ClassPathResource(resourceLocation, this.classLoader);
|
||||
InputSource source = new InputSource(resource.getInputStream());
|
||||
|
|
@ -119,24 +121,40 @@ public class PluggableSchemaResolver implements EntityResolver {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected String getSchemaMapping(String systemId) {
|
||||
/**
|
||||
* Load the specified schema mappings lazily.
|
||||
*/
|
||||
private Map<String, String> getSchemaMappings() {
|
||||
if (this.schemaMappings == null) {
|
||||
synchronized (this) {
|
||||
if (this.schemaMappings == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loading schema mappings from [" + this.schemaMappingsLocation + "]");
|
||||
}
|
||||
try {
|
||||
this.schemaMappings =
|
||||
Properties mappings =
|
||||
PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation, this.classLoader);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loaded schema mappings: " + this.schemaMappings);
|
||||
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 FatalBeanException(
|
||||
throw new IllegalStateException(
|
||||
"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