You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by gn...@apache.org on 2012/08/28 14:55:03 UTC
svn commit: r1378113 -
/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/NamespaceHandlerRegistryImpl.java
Author: gnodet
Date: Tue Aug 28 12:55:03 2012
New Revision: 1378113
URL: http://svn.apache.org/viewvc?rev=1378113&view=rev
Log:
[ARIES-899] Another peek at improving concurrency on the namespace handler registry
Modified:
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/NamespaceHandlerRegistryImpl.java
Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/NamespaceHandlerRegistryImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/NamespaceHandlerRegistryImpl.java?rev=1378113&r1=1378112&r2=1378113&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/NamespaceHandlerRegistryImpl.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/NamespaceHandlerRegistryImpl.java Tue Aug 28 12:55:03 2012
@@ -18,6 +18,10 @@
*/
package org.apache.aries.blueprint.namespace;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.net.URI;
@@ -30,30 +34,27 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
-import java.util.HashSet;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import javax.xml.XMLConstants;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.transform.Source;
-import javax.xml.XMLConstants;
-
-import org.w3c.dom.ls.LSInput;
-import org.w3c.dom.ls.LSResourceResolver;
import org.apache.aries.blueprint.NamespaceHandler;
import org.apache.aries.blueprint.container.NamespaceHandlerRegistry;
import org.apache.aries.blueprint.parser.NamespaceHandlerSet;
-import org.apache.aries.blueprint.parser.NamespaceHandlerSet.Listener;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
@@ -61,9 +62,9 @@ import org.osgi.util.tracker.ServiceTrac
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
/**
* Default implementation of the NamespaceHandlerRegistry.
@@ -81,25 +82,41 @@ public class NamespaceHandlerRegistryImp
private static final Logger LOGGER = LoggerFactory.getLogger(NamespaceHandlerRegistryImpl.class);
+ // The bundle context is thread safe
private final BundleContext bundleContext;
- private final Map<URI, Set<NamespaceHandler>> handlers;
+
+ // The service tracker is thread safe
private final ServiceTracker tracker;
- private final Map<Map<URI, NamespaceHandler>, Reference<Schema>> schemas = new LRUMap<Map<URI, NamespaceHandler>, Reference<Schema>>(10);
- private SchemaFactory schemaFactory;
- private List<NamespaceHandlerSetImpl> sets;
+
+ // The handlers map is concurrent
+ private final ConcurrentHashMap<URI, CopyOnWriteArraySet<NamespaceHandler>> handlers =
+ new ConcurrentHashMap<URI, CopyOnWriteArraySet<NamespaceHandler>>();
+
+ // Access to the LRU schemas map is synchronized on the lock object
+ private final Map<Map<URI, NamespaceHandler>, Reference<Schema>> schemas =
+ new LRUMap<Map<URI, NamespaceHandler>, Reference<Schema>>(10);
+
+ // Lock to protect access to the schema list
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+ // Access to this factory is synchronized on itself
+ private final SchemaFactory schemaFactory =
+ SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+
+ // Access to this variable is not synchronized. The list itself is concurrent
+ private final CopyOnWriteArrayList<NamespaceHandlerSetImpl> sets =
+ new CopyOnWriteArrayList<NamespaceHandlerSetImpl>();
public NamespaceHandlerRegistryImpl(BundleContext bundleContext) {
this.bundleContext = bundleContext;
- handlers = new HashMap<URI, Set<NamespaceHandler>>();
- sets = new ArrayList<NamespaceHandlerSetImpl>();
tracker = new ServiceTracker(bundleContext, NamespaceHandler.class.getName(), this);
tracker.open();
}
public Object addingService(ServiceReference reference) {
- LOGGER.debug("Adding NamespaceHandler "+reference.toString());
+ LOGGER.debug("Adding NamespaceHandler " + reference.toString());
NamespaceHandler handler = (NamespaceHandler) bundleContext.getService(reference);
- if(handler!=null){
+ if (handler != null) {
try {
Map<String, Object> props = new HashMap<String, Object>();
for (String name : reference.getPropertyKeys()) {
@@ -109,8 +126,9 @@ public class NamespaceHandlerRegistryImp
} catch (Exception e) {
LOGGER.warn("Error registering NamespaceHandler", e);
}
- }else{
- LOGGER.warn("Error resolving NamespaceHandler, null Service obtained from tracked ServiceReference {} for bundle {}, ver {}", new Object[]{reference.toString(), reference.getBundle().getSymbolicName(), reference.getBundle().getVersion()});
+ } else {
+ LOGGER.warn("Error resolving NamespaceHandler, null Service obtained from tracked ServiceReference {} for bundle {}, ver {}",
+ new Object[] { reference.toString(), reference.getBundle().getSymbolicName(), reference.getBundle().getVersion() });
}
return handler;
}
@@ -122,6 +140,7 @@ public class NamespaceHandlerRegistryImp
public void removedService(ServiceReference reference, Object service) {
try {
+ LOGGER.debug("Removing NamespaceHandler " + reference.toString());
NamespaceHandler handler = (NamespaceHandler) service;
Map<String, Object> props = new HashMap<String, Object>();
for (String name : reference.getPropertyKeys()) {
@@ -133,13 +152,12 @@ public class NamespaceHandlerRegistryImp
}
}
- public synchronized void registerHandler(NamespaceHandler handler, Map properties) {
+ public void registerHandler(NamespaceHandler handler, Map properties) {
List<URI> namespaces = getNamespaces(properties);
for (URI uri : namespaces) {
- Set<NamespaceHandler> h = handlers.get(uri);
+ CopyOnWriteArraySet<NamespaceHandler> h = handlers.putIfAbsent(uri, new CopyOnWriteArraySet<NamespaceHandler>());
if (h == null) {
- h = new HashSet<NamespaceHandler>();
- handlers.put(uri, h);
+ h = handlers.get(uri);
}
if (h.add(handler)) {
for (NamespaceHandlerSetImpl s : sets) {
@@ -149,11 +167,11 @@ public class NamespaceHandlerRegistryImp
}
}
- public synchronized void unregisterHandler(NamespaceHandler handler, Map properties) {
+ public void unregisterHandler(NamespaceHandler handler, Map properties) {
List<URI> namespaces = getNamespaces(properties);
for (URI uri : namespaces) {
- Set<NamespaceHandler> h = handlers.get(uri);
- if (h == null || !h.remove(handler)) {
+ CopyOnWriteArraySet<NamespaceHandler> h = handlers.get(uri);
+ if (!h.remove(handler)) {
continue;
}
for (NamespaceHandlerSetImpl s : sets) {
@@ -166,7 +184,8 @@ public class NamespaceHandlerRegistryImp
private static List<URI> getNamespaces(Map properties) {
Object ns = properties != null ? properties.get(NAMESPACE) : null;
if (ns == null) {
- throw new IllegalArgumentException("NamespaceHandler service does not have an associated " + NAMESPACE + " property defined");
+ throw new IllegalArgumentException("NamespaceHandler service does not have an associated "
+ + NAMESPACE + " property defined");
} else if (ns instanceof URI[]) {
return Arrays.asList((URI[]) ns);
} else if (ns instanceof URI) {
@@ -195,7 +214,8 @@ public class NamespaceHandlerRegistryImp
}
return namespaces;
} else {
- throw new IllegalArgumentException("NamespaceHandler service has an associated " + NAMESPACE + " property defined which can not be converted to an array of URI");
+ throw new IllegalArgumentException("NamespaceHandler service has an associated "
+ + NAMESPACE + " property defined which can not be converted to an array of URI");
}
}
@@ -205,11 +225,12 @@ public class NamespaceHandlerRegistryImp
} else if (o instanceof String) {
return URI.create((String) o);
} else {
- throw new IllegalArgumentException("NamespaceHandler service has an associated " + NAMESPACE + " property defined which can not be converted to an array of URI");
+ throw new IllegalArgumentException("NamespaceHandler service has an associated "
+ + NAMESPACE + " property defined which can not be converted to an array of URI");
}
}
- public synchronized NamespaceHandlerSet getNamespaceHandlers(Set<URI> uris, Bundle bundle) {
+ public NamespaceHandlerSet getNamespaceHandlers(Set<URI> uris, Bundle bundle) {
NamespaceHandlerSetImpl s = new NamespaceHandlerSetImpl(uris, bundle);
sets.add(s);
return s;
@@ -218,222 +239,282 @@ public class NamespaceHandlerRegistryImp
public void destroy() {
tracker.close();
}
- public synchronized Schema getSchema(Map<URI, NamespaceHandler> handlers)
- throws IOException, SAXException {
- return getSchema(handlers, null, new Properties());
- }
- private synchronized Schema getSchema(Map<URI, NamespaceHandler> handlers,
- final Bundle bundle,
- final Properties schemaMap) throws IOException, SAXException {
- Schema schema = null;
+
+ private Schema getSchema(Map<URI, NamespaceHandler> handlers,
+ final Bundle bundle,
+ final Properties schemaMap) throws IOException, SAXException {
+ if (schemaMap != null && !schemaMap.isEmpty()) {
+ return createSchema(handlers, bundle, schemaMap);
+ }
// Find a schema that can handle all the requested namespaces
// If it contains additional namespaces, it should not be a problem since
// they won't be used at all
- if (schemaMap == null || schemaMap.isEmpty()) {
+ lock.readLock().lock();
+ try {
+ Schema schema = getExistingSchema(handlers);
+ if (schema != null) {
+ return schema;
+ }
+ } finally {
+ lock.readLock().unlock();
+ }
+ // Create schema
+ lock.writeLock().lock();
+ try {
+ Schema schema = getExistingSchema(handlers);
+ if (schema == null) {
+ schema = createSchema(handlers, bundle, schemaMap);
+ cacheSchema(handlers, schema);
+ }
+ return schema;
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ private Schema getExistingSchema(Map<URI, NamespaceHandler> handlers) {
+ for (Map<URI, NamespaceHandler> key : schemas.keySet()) {
+ boolean found = true;
+ for (URI uri : handlers.keySet()) {
+ if (!handlers.get(uri).equals(key.get(uri))) {
+ found = false;
+ break;
+ }
+ }
+ if (found) {
+ return schemas.get(key).get();
+ }
+ }
+ return null;
+ }
+
+ private void removeSchemasFor(NamespaceHandler handler) {
+ List<Map<URI, NamespaceHandler>> keys = new ArrayList<Map<URI, NamespaceHandler>>();
+ lock.readLock().lock();
+ try {
for (Map<URI, NamespaceHandler> key : schemas.keySet()) {
- boolean found = true;
- for (URI uri : handlers.keySet()) {
- if (!handlers.get(uri).equals(key.get(uri))) {
- found = false;
- break;
- }
+ if (key.values().contains(handler)) {
+ keys.add(key);
}
- if (found) {
- schema = schemas.get(key).get();
+ }
+ } finally {
+ lock.readLock().unlock();
+ }
+ if (!keys.isEmpty()) {
+ lock.writeLock().lock();
+ try {
+ for (Map<URI, NamespaceHandler> key : keys) {
+ schemas.remove(key);
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+ }
+
+ private void cacheSchema(Map<URI, NamespaceHandler> handlers, Schema schema) {
+ // Remove schemas that are fully included
+ for (Iterator<Map<URI, NamespaceHandler>> iterator = schemas.keySet().iterator(); iterator.hasNext();) {
+ Map<URI, NamespaceHandler> key = iterator.next();
+ boolean found = true;
+ for (URI uri : key.keySet()) {
+ if (!key.get(uri).equals(handlers.get(uri))) {
+ found = false;
break;
}
}
+ if (found) {
+ iterator.remove();
+ break;
+ }
}
- if (schema == null) {
- final List<StreamSource> schemaSources = new ArrayList<StreamSource>();
- try {
- schemaSources.add(new StreamSource(getClass().getResourceAsStream("/org/apache/aries/blueprint/blueprint.xsd")));
- // Create a schema for all namespaces known at this point
- // It will speed things as it can be reused for all other blueprint containers
- for (URI ns : handlers.keySet()) {
- URL url = handlers.get(ns).getSchemaLocation(ns.toString());
- if (url == null) {
- LOGGER.warn("No URL is defined for schema " + ns + ". This schema will not be validated");
- } else {
- schemaSources.add(new StreamSource(url.openStream(), url.toExternalForm()));
- }
+ // Add our new schema
+ schemas.put(handlers, new SoftReference<Schema>(schema));
+ }
+
+ private Schema createSchema(Map<URI, NamespaceHandler> handlers,
+ Bundle bundle,
+ Properties schemaMap) throws IOException, SAXException {
+ final List<StreamSource> schemaSources = new ArrayList<StreamSource>();
+ try {
+ schemaSources.add(new StreamSource(getClass().getResourceAsStream("/org/apache/aries/blueprint/blueprint.xsd")));
+ // Create a schema for all namespaces known at this point
+ // It will speed things as it can be reused for all other blueprint containers
+ for (URI ns : handlers.keySet()) {
+ URL url = handlers.get(ns).getSchemaLocation(ns.toString());
+ if (url == null) {
+ LOGGER.warn("No URL is defined for schema " + ns + ". This schema will not be validated");
+ } else {
+ schemaSources.add(new StreamSource(url.openStream(), url.toExternalForm()));
}
- for (Object ns : schemaMap.values()) {
- URL url = bundle.getResource(ns.toString());
- if (url == null) {
- LOGGER.warn("No URL is defined for schema " + ns + ". This schema will not be validated");
- } else {
- schemaSources.add(new StreamSource(url.openStream(), url.toExternalForm()));
- }
+ }
+ for (Object ns : schemaMap.values()) {
+ URL url = bundle.getResource(ns.toString());
+ if (url == null) {
+ LOGGER.warn("No URL is defined for schema " + ns + ". This schema will not be validated");
+ } else {
+ schemaSources.add(new StreamSource(url.openStream(), url.toExternalForm()));
}
- SchemaFactory factory = getSchemaFactory();
- factory.setResourceResolver(new LSResourceResolver() {
- public LSInput resolveResource(String type,
- final String namespaceURI,
- final String publicId,
- String systemId, String baseURI) {
- String loc = null;
- if (namespaceURI != null) {
- loc = schemaMap.getProperty(namespaceURI);
- }
- if (loc == null && publicId != null) {
- loc = schemaMap.getProperty(publicId);
- }
- if (loc == null && systemId != null) {
- loc = schemaMap.getProperty(systemId);
- }
- if (loc != null) {
- URL url = bundle.getResource(loc);
- if (url != null) {
- try {
- StreamSource source
- = new StreamSource(url.openStream(), url.toExternalForm());
- schemaSources.add(source);
- return new SourceLSInput(source, publicId, url);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }
- URI uri = URI.create((String) namespaceURI);
- Set<NamespaceHandler> hs = NamespaceHandlerRegistryImpl.this.handlers.get(uri);
- if (hs == null) {
- return null;
- }
- for (NamespaceHandler h : hs) {
- URL url = h.getSchemaLocation(namespaceURI);
- if (url != null) {
- // handling include-relative-path case
- if (systemId != null && !systemId.matches("^[a-z][-+.0-9a-z]*:.*")) {
- try {
- url = new URL(url, systemId);
- } catch (Exception e) {
- // ignore and use the given systemId
- }
- }
-
-
- try {
- final StreamSource source
- = new StreamSource(url.openStream(), url.toExternalForm());
- schemaSources.add(source);
- return new SourceLSInput(source, publicId, url);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }
- return null;
+ }
+ synchronized (schemaFactory) {
+ schemaFactory.setResourceResolver(new BundleResourceResolver(schemaMap, bundle, schemaSources));
+ return schemaFactory.newSchema(schemaSources.toArray(new Source[schemaSources.size()]));
+ }
+ } finally {
+ for (StreamSource s : schemaSources) {
+ closeQuietly(s.getInputStream());
+ }
+ }
+ }
+
+ private static void closeQuietly(Closeable closeable) {
+ try {
+ if (closeable != null) {
+ closeable.close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+
+ private class BundleResourceResolver implements LSResourceResolver {
+ private final Properties schemaMap;
+ private final Bundle bundle;
+ private final List<StreamSource> schemaSources;
+
+ public BundleResourceResolver(Properties schemaMap, Bundle bundle, List<StreamSource> schemaSources) {
+ this.schemaMap = schemaMap;
+ this.bundle = bundle;
+ this.schemaSources = schemaSources;
+ }
+
+ public LSInput resolveResource(String type,
+ final String namespaceURI,
+ final String publicId,
+ String systemId, String baseURI) {
+ String loc = null;
+ if (namespaceURI != null) {
+ loc = schemaMap.getProperty(namespaceURI);
+ }
+ if (loc == null && publicId != null) {
+ loc = schemaMap.getProperty(publicId);
+ }
+ if (loc == null && systemId != null) {
+ loc = schemaMap.getProperty(systemId);
+ }
+ if (loc != null) {
+ URL url = bundle.getResource(loc);
+ if (url != null) {
+ try {
+ StreamSource source
+ = new StreamSource(url.openStream(), url.toExternalForm());
+ schemaSources.add(source);
+ return new SourceLSInput(source, publicId, url);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
}
-
- });
- schema = factory.newSchema(schemaSources.toArray(new Source[schemaSources.size()]));
- // Remove schemas that are fully included
- for (Iterator<Map<URI, NamespaceHandler>> iterator = schemas.keySet().iterator(); iterator.hasNext();) {
- Map<URI, NamespaceHandler> key = iterator.next();
- boolean found = true;
- for (URI uri : key.keySet()) {
- if (!key.get(uri).equals(handlers.get(uri))) {
- found = false;
- break;
+ }
+ }
+ URI uri = URI.create(namespaceURI);
+ Set<NamespaceHandler> hs = NamespaceHandlerRegistryImpl.this.handlers.get(uri);
+ if (hs == null) {
+ return null;
+ }
+ for (NamespaceHandler h : hs) {
+ URL url = h.getSchemaLocation(namespaceURI);
+ if (url != null) {
+ // handling include-relative-path case
+ if (systemId != null && !systemId.matches("^[a-z][-+.0-9a-z]*:.*")) {
+ try {
+ url = new URL(url, systemId);
+ } catch (Exception e) {
+ // ignore and use the given systemId
}
}
- if (found) {
- iterator.remove();
- break;
- }
- }
- // Add our new schema
- if (schemaMap.isEmpty()) {
- //only cache non-custom schemas
- schemas.put(handlers, new SoftReference<Schema>(schema));
- }
- } finally {
- for (StreamSource s : schemaSources) {
try {
- s.getInputStream().close();
+ final StreamSource source = new StreamSource(url.openStream(), url.toExternalForm());
+ schemaSources.add(source);
+ return new SourceLSInput(source, publicId, url);
} catch (IOException e) {
- // Ignore
+ throw new RuntimeException(e);
}
}
}
+ return null;
}
- return schema;
}
-
+
private class SourceLSInput implements LSInput {
- StreamSource source;
- URL systemId;
- String publicId;
- public SourceLSInput(StreamSource src, String pid, URL sys) {
- source = src;
- publicId = pid;
- systemId = sys;
+ private final StreamSource source;
+ private final URL systemId;
+ private final String publicId;
+
+ public SourceLSInput(StreamSource source, String publicId, URL systemId) {
+ this.source = source;
+ this.publicId = publicId;
+ this.systemId = systemId;
}
+
public Reader getCharacterStream() {
return null;
}
+
public void setCharacterStream(Reader characterStream) {
}
+
public InputStream getByteStream() {
return source.getInputStream();
}
+
public void setByteStream(InputStream byteStream) {
}
+
public String getStringData() {
return null;
}
+
public void setStringData(String stringData) {
}
+
public String getSystemId() {
return systemId.toExternalForm();
}
+
public void setSystemId(String systemId) {
}
+
public String getPublicId() {
return publicId;
}
+
public void setPublicId(String publicId) {
}
+
public String getBaseURI() {
return null;
}
+
public void setBaseURI(String baseURI) {
}
+
public String getEncoding() {
return null;
}
+
public void setEncoding(String encoding) {
}
+
public boolean getCertifiedText() {
return false;
}
- public void setCertifiedText(boolean certifiedText) {
- }
- };
- protected synchronized void removeSchemasFor(NamespaceHandler handler) {
- List<Map<URI, NamespaceHandler>> keys = new ArrayList<Map<URI, NamespaceHandler>>();
- for (Map<URI, NamespaceHandler> key : schemas.keySet()) {
- if (key.values().contains(handler)) {
- keys.add(key);
- }
- }
- for (Map<URI, NamespaceHandler> key : keys) {
- schemas.remove(key);
- }
- }
-
- private SchemaFactory getSchemaFactory() {
- if (schemaFactory == null) {
- schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ public void setCertifiedText(boolean certifiedText) {
}
- return schemaFactory;
}
protected class NamespaceHandlerSetImpl implements NamespaceHandlerSet {
- private final Map<Listener, Boolean> listeners;
+ private final List<Listener> listeners;
private final Bundle bundle;
private final Set<URI> namespaces;
private final Map<URI, NamespaceHandler> handlers;
@@ -441,7 +522,7 @@ public class NamespaceHandlerRegistryImp
private Schema schema;
public NamespaceHandlerSetImpl(Set<URI> namespaces, Bundle bundle) {
- this.listeners = new HashMap<Listener, Boolean>();
+ this.listeners = new CopyOnWriteArrayList<Listener>();
this.namespaces = namespaces;
this.bundle = bundle;
handlers = new HashMap<URI, NamespaceHandler>();
@@ -458,13 +539,7 @@ public class NamespaceHandlerRegistryImp
ex.printStackTrace();
//ignore
} finally {
- if (ins != null) {
- try {
- ins.close();
- } catch (IOException e) {
- //ignore
- }
- }
+ closeQuietly(ins);
}
}
for (Object ns : schemaMap.keySet()) {
@@ -498,11 +573,11 @@ public class NamespaceHandlerRegistryImp
return schema;
}
- public synchronized void addListener(Listener listener) {
- listeners.put(listener, Boolean.TRUE);
+ public void addListener(Listener listener) {
+ listeners.add(listener);
}
- public synchronized void removeListener(Listener listener) {
+ public void removeListener(Listener listener) {
listeners.remove(listener);
}
@@ -513,7 +588,7 @@ public class NamespaceHandlerRegistryImp
public void registerHandler(URI uri, NamespaceHandler handler) {
if (namespaces.contains(uri) && handlers.get(uri) == null) {
if (findCompatibleNamespaceHandler(uri) != null) {
- for (Listener listener : listeners.keySet()) {
+ for (Listener listener : listeners) {
try {
listener.namespaceHandlerRegistered(uri);
} catch (Throwable t) {
@@ -527,7 +602,7 @@ public class NamespaceHandlerRegistryImp
public void unregisterHandler(URI uri, NamespaceHandler handler) {
if (handlers.get(uri) == handler) {
handlers.remove(uri);
- for (Listener listener : listeners.keySet()) {
+ for (Listener listener : listeners) {
try {
listener.namespaceHandlerUnregistered(uri);
} catch (Throwable t) {
@@ -578,64 +653,6 @@ public class NamespaceHandlerRegistryImp
}
}
- protected static Map<URI, NamespaceHandler> findHandlers(Map<URI, Set<NamespaceHandler>> allHandlers,
- Set<URI> namespaces,
- Bundle bundle) {
- Map<URI, NamespaceHandler> handlers = new HashMap<URI, NamespaceHandler>();
- Map<URI, Set<NamespaceHandler>> candidates = new HashMap<URI, Set<NamespaceHandler>>();
- // Populate initial candidates
- for (URI ns : namespaces) {
- Set<NamespaceHandler> h = new HashSet<NamespaceHandler>();
- if (allHandlers.get(ns) != null) {
- h.addAll(allHandlers.get(ns));
- }
- candidates.put(ns, h);
- }
- // Exclude directly incompatible handlers
- for (URI ns : namespaces) {
- for (Iterator<NamespaceHandler> it = candidates.get(ns).iterator(); it.hasNext();) {
- NamespaceHandler h = it.next();
- Set<Class> classes = h.getManagedClasses();
- boolean compat = true;
- if (classes != null) {
- Set<Class> allClasses = new HashSet<Class>();
- for (Class cl : classes) {
- for (Class c = cl; c != null; c = c.getSuperclass()) {
- allClasses.add(c);
- for (Class i : c.getInterfaces()) {
- allClasses.add(i);
- }
- }
- }
- for (Class cl : allClasses) {
- Class clb;
- try {
- clb = bundle.loadClass(cl.getName());
- } catch (Throwable t) {
- clb = null;
- }
- if (clb != cl) {
- compat = false;
- break;
- }
- }
- }
- if (!compat) {
- it.remove();
- }
- }
- }
- // TODO: do we need to check if there are incompatibilities between namespaces?
- // Pick the first ones
- for (URI ns : namespaces) {
- Set<NamespaceHandler> h = candidates.get(ns);
- if (!h.isEmpty()) {
- handlers.put(ns, h.iterator().next());
- }
- }
- return handlers;
- }
-
public static class LRUMap<K,V> extends AbstractMap<K,V> {
private final int bound;