Browse Source

EntityResolvers and DefaultNamespaceHandlerResolver support concurrent access now (SPR-5679)

conversation
Juergen Hoeller 16 years ago
parent
commit
10d8abea3b
  1. 15
      org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/BeansDtdResolver.java
  2. 45
      org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/DefaultNamespaceHandlerResolver.java
  3. 9
      org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/DelegatingEntityResolver.java
  4. 54
      org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/PluggableSchemaResolver.java

15
org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/BeansDtdResolver.java

@ -1,5 +1,5 @@ @@ -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 @@ @@ -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 { @@ -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()) {
@ -78,7 +79,7 @@ public class BeansDtdResolver implements EntityResolver { @@ -78,7 +79,7 @@ public class BeansDtdResolver implements EntityResolver {
logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in class path", ex);
}
}
}
}
}
@ -87,4 +88,10 @@ public class BeansDtdResolver implements EntityResolver { @@ -87,4 +88,10 @@ public class BeansDtdResolver implements EntityResolver {
return null;
}
@Override
public String toString() {
return "EntityResolver for DTDs " + Arrays.toString(DTD_NAMES);
}
}

45
org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/DefaultNamespaceHandlerResolver.java

@ -1,5 +1,5 @@ @@ -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 @@ @@ -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 @@ -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 @@ -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 @@ -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 @@ -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) {
try {
Properties mappings =
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if (logger.isDebugEnabled()) {
logger.debug("Loaded mappings [" + mappings + "]");
synchronized (this) {
if (this.handlerMappings == null) {
try {
Properties 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;
}
@Override
public String toString() {
return "NamespaceHandlerResolver using mappings " + getHandlerMappings();
}
}

9
org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/DelegatingEntityResolver.java

@ -1,5 +1,5 @@ @@ -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 { @@ -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;
}
}

54
org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/PluggableSchemaResolver.java

@ -1,5 +1,5 @@ @@ -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 @@ @@ -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 { @@ -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 { @@ -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 { @@ -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) {
if (logger.isDebugEnabled()) {
logger.debug("Loading schema mappings from [" + this.schemaMappingsLocation + "]");
}
try {
this.schemaMappings =
PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation, this.classLoader);
if (logger.isDebugEnabled()) {
logger.debug("Loaded schema mappings: " + this.schemaMappings);
synchronized (this) {
if (this.schemaMappings == null) {
if (logger.isDebugEnabled()) {
logger.debug("Loading schema mappings from [" + this.schemaMappingsLocation + "]");
}
try {
Properties mappings =
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…
Cancel
Save