You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by gn...@apache.org on 2009/04/22 21:05:15 UTC
svn commit: r767623 - in /geronimo/sandbox/blueprint/blueprint-core/src:
main/java/org/apache/geronimo/blueprint/
main/java/org/apache/geronimo/blueprint/context/
main/java/org/apache/geronimo/blueprint/namespace/
test/java/org/apache/geronimo/blueprint/
Author: gnodet
Date: Wed Apr 22 19:05:14 2009
New Revision: 767623
URL: http://svn.apache.org/viewvc?rev=767623&view=rev
Log:
Refactor context / parser a bit to allow step by step creation and prepare for mandatory dependencies processing
Modified:
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/Activator.java
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/NamespaceHandlerRegistry.java
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintContextImpl.java
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Parser.java
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/namespace/NamespaceHandlerRegistryImpl.java
geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/AbstractBlueprintTest.java
geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/ParserTest.java
Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/Activator.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/Activator.java?rev=767623&r1=767622&r2=767623&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/Activator.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/Activator.java Wed Apr 22 19:05:14 2009
@@ -128,13 +128,9 @@
}
if (!urls.isEmpty()) {
LOGGER.debug("Found blueprint application in bundle " + bundle.getSymbolicName() + " with urls: " + urls);
- final BlueprintContextImpl moduleContext = new BlueprintContextImpl(bundle.getBundleContext(), sender, handlers, urls);
+ final BlueprintContextImpl moduleContext = new BlueprintContextImpl(bundle.getBundleContext(), sender, handlers, executors, urls);
contextMap.put(bundle, moduleContext);
- executors.submit(new Runnable() {
- public void run() {
- moduleContext.create();
- }
- });
+ executors.submit(moduleContext);
} else {
LOGGER.debug("No blueprint application found in bundle " + bundle.getSymbolicName());
}
Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/NamespaceHandlerRegistry.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/NamespaceHandlerRegistry.java?rev=767623&r1=767622&r2=767623&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/NamespaceHandlerRegistry.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/NamespaceHandlerRegistry.java Wed Apr 22 19:05:14 2009
@@ -39,4 +39,12 @@
NamespaceHandler getNamespaceHandler(URI uri);
void destroy();
+
+ void addListener(Listener listener);
+ void removeListener(Listener listener);
+
+ public interface Listener {
+ void namespaceHandlerRegistered(URI uri);
+ void namespaceHandlerUnregistered(URI uri);
+ }
}
Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintContextImpl.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintContextImpl.java?rev=767623&r1=767622&r2=767623&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintContextImpl.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintContextImpl.java Wed Apr 22 19:05:14 2009
@@ -19,6 +19,7 @@
package org.apache.geronimo.blueprint.context;
import java.net.URL;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -27,6 +28,7 @@
import java.util.Map;
import java.util.Set;
import java.util.Properties;
+import java.util.concurrent.ExecutorService;
import org.apache.geronimo.blueprint.BlueprintConstants;
import org.apache.geronimo.blueprint.HeaderParser;
@@ -35,6 +37,7 @@
import org.apache.geronimo.blueprint.NamespaceHandlerRegistry;
import org.apache.geronimo.blueprint.convert.ConversionServiceImpl;
import org.apache.geronimo.blueprint.namespace.ComponentDefinitionRegistryImpl;
+import org.apache.geronimo.blueprint.namespace.NamespaceHandlerRegistryImpl;
import org.apache.xbean.recipe.ObjectGraph;
import org.apache.xbean.recipe.Repository;
import org.osgi.framework.Bundle;
@@ -46,6 +49,7 @@
import org.osgi.service.blueprint.convert.ConversionService;
import org.osgi.service.blueprint.convert.Converter;
import org.osgi.service.blueprint.namespace.ComponentDefinitionRegistry;
+import org.osgi.service.blueprint.namespace.NamespaceHandler;
import org.osgi.service.blueprint.reflect.ComponentMetadata;
import org.osgi.service.blueprint.reflect.BeanMetadata;
import org.osgi.service.blueprint.reflect.ServiceMetadata;
@@ -57,7 +61,15 @@
* @author <a href="mailto:dev@geronimo.apache.org">Apache Geronimo Project</a>
* @version $Rev: 760378 $, $Date: 2009-03-31 11:31:38 +0200 (Tue, 31 Mar 2009) $
*/
-public class BlueprintContextImpl implements BlueprintContext {
+public class BlueprintContextImpl implements BlueprintContext, NamespaceHandlerRegistry.Listener, Runnable {
+
+ private enum State {
+ Unknown,
+ WaitForNamespaceHandlers,
+ Populated,
+ Created,
+ Failed
+ }
private final BundleContext bundleContext;
private final ModuleContextEventSender sender;
@@ -65,16 +77,22 @@
private final List<URL> urls;
private final ComponentDefinitionRegistryImpl componentDefinitionRegistry;
private final ConversionServiceImpl conversionService;
+ private final ExecutorService executors;
+ private Set<URI> namespaces;
+ private State state = State.Unknown;
+ private Parser parser;
private ObjectGraph objectGraph;
private ServiceRegistration registration;
+ private boolean waitForNamespaceHandlersEventSent;
- public BlueprintContextImpl(BundleContext bundleContext, ModuleContextEventSender sender, NamespaceHandlerRegistry handlers, List<URL> urls) {
+ public BlueprintContextImpl(BundleContext bundleContext, ModuleContextEventSender sender, NamespaceHandlerRegistry handlers, ExecutorService executors, List<URL> urls) {
this.bundleContext = bundleContext;
this.sender = sender;
this.handlers = handlers;
this.urls = urls;
this.conversionService = new ConversionServiceImpl();
this.componentDefinitionRegistry = new ComponentDefinitionRegistryImpl();
+ this.executors = executors;
}
public ModuleContextEventSender getSender() {
@@ -99,39 +117,69 @@
}
}
- public void create() {
- checkDirectives();
- sender.sendCreating(this);
+ public synchronized void run() {
try {
- Parser parser = new Parser(handlers, componentDefinitionRegistry, urls);
- parser.parse();
- Instanciator i = new Instanciator(this);
- Repository repository = i.createRepository();
- objectGraph = new ObjectGraph(repository);
-
- registerTypeConverters();
-
- instantiateComponents();
-
- // TODO: access to any OSGi reference proxy is currently a problem at this point, because calling toString() will
- // TODO: wait for a service to be available. We may need to catch toString(), equals() and hashCode() and make them
- // TODO: work even if there's no service available.
-
- registerAllServices();
-
- // Register the ModuleContext in the OSGi registry
- Properties props = new Properties();
- props.put(BlueprintConstants.CONTEXT_SYMBOLIC_NAME_PROPERTY,
- bundleContext.getBundle().getSymbolicName());
- props.put(BlueprintConstants.CONTEXT_VERSION_PROPERTY,
- bundleContext.getBundle().getHeaders().get(Constants.BUNDLE_VERSION));
- registration = bundleContext.registerService(BlueprintContext.class.getName(), this, props);
-
- sender.sendCreated(this);
- } catch (WaitForDependencyException e) {
- sender.sendWaiting(this, e.getServiceObjectClass(), e.getServiceFilter());
- // TODO: wait for dependency
+ for (;;) {
+ switch (state) {
+ case Unknown:
+ checkDirectives();
+ sender.sendCreating(this);
+ parser = new Parser();
+ parser.parse(urls);
+ namespaces = parser.getNamespaces();
+ if (namespaces.size() > 0) {
+ handlers.addListener(this);
+ }
+ state = State.WaitForNamespaceHandlers;
+ break;
+ case WaitForNamespaceHandlers:
+ for (URI ns : namespaces) {
+ if (handlers.getNamespaceHandler(ns) == null) {
+ if (!waitForNamespaceHandlersEventSent) {
+ sender.sendWaiting(this, new String[] {NamespaceHandler.class.getName() }, null);
+ waitForNamespaceHandlersEventSent = true;
+ }
+ return;
+ }
+ }
+ parser.populate(handlers, componentDefinitionRegistry);
+ state = State.Populated;
+ break;
+ case Populated:
+ Instanciator i = new Instanciator(this);
+ Repository repository = i.createRepository();
+ objectGraph = new ObjectGraph(repository);
+
+ registerTypeConverters();
+
+ instantiateComponents();
+
+ // TODO: access to any OSGi reference proxy is currently a problem at this point, because calling toString() will
+ // TODO: wait for a service to be available. We may need to catch toString(), equals() and hashCode() and make them
+ // TODO: work even if there's no service available.
+
+ registerAllServices();
+
+ // Register the ModuleContext in the OSGi registry
+ if (registration == null) {
+ Properties props = new Properties();
+ props.put(BlueprintConstants.CONTEXT_SYMBOLIC_NAME_PROPERTY,
+ bundleContext.getBundle().getSymbolicName());
+ props.put(BlueprintConstants.CONTEXT_VERSION_PROPERTY,
+ bundleContext.getBundle().getHeaders().get(Constants.BUNDLE_VERSION));
+ registration = bundleContext.registerService(BlueprintContext.class.getName(), this, props);
+
+ sender.sendCreated(this);
+ state = State.Created;
+ }
+ break;
+ case Created:
+ case Failed:
+ return;
+ }
+ }
} catch (Exception e) {
+ state = State.Failed;
sender.sendFailure(this, e);
e.printStackTrace(); // TODO: log failure
}
@@ -249,6 +297,7 @@
if (registration != null) {
registration.unregister();
}
+ handlers.removeListener(this);
sender.sendDestroying(this);
unregisterAllServices();
System.out.println("Module context destroyed: " + this.bundleContext);
@@ -256,4 +305,18 @@
sender.sendDestroyed(this);
}
+ public synchronized void namespaceHandlerRegistered(URI uri) {
+ if (namespaces != null && namespaces.contains(uri)) {
+ executors.submit(this);
+ }
+ }
+
+ public synchronized void namespaceHandlerUnregistered(URI uri) {
+ if (namespaces != null && namespaces.contains(uri)) {
+ // TODO: destroy all instances
+ waitForNamespaceHandlersEventSent = false;
+ state = State.WaitForNamespaceHandlers;
+ executors.submit(this);
+ }
+ }
}
Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Parser.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Parser.java?rev=767623&r1=767622&r2=767623&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Parser.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Parser.java Wed Apr 22 19:05:14 2009
@@ -176,8 +176,7 @@
public static final String ODERING_BASIS_SERVICE_REFERENCES = "service-reference";
public static final String LAZY_INIT_DEFAULT = BOOLEAN_FALSE;
- private DocumentBuilderFactory documentBuilderFactory;
- private List<URL> urls;
+ private List<Document> documents;
private ComponentDefinitionRegistryImpl registry;
private NamespaceHandlerRegistry namespaceHandlerRegistry;
private int nameCounter;
@@ -187,50 +186,45 @@
private String defaultInitMethod;
private String defaultDestroyMethod;
- public Parser(NamespaceHandlerRegistry handlers,
- ComponentDefinitionRegistryImpl registry,
- List<URL> urls) {
- this.urls = urls;
- this.registry = registry;
- this.namespaceHandlerRegistry = handlers;
+ public Parser() {
}
- public void parse() throws Exception {
+ public void parse(List<URL> urls) throws Exception {
List<Document> documents = new ArrayList<Document>();
+ // Create document builder factory
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ documentBuilderFactory.setNamespaceAware(true);
// Load documents
for (URL url : urls) {
InputStream inputStream = url.openStream();
try {
InputSource inputSource = new InputSource(inputStream);
- DocumentBuilder builder = getDocumentBuilderFactory().newDocumentBuilder();
+ DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
Document doc = builder.parse(inputSource);
documents.add(doc);
} finally {
inputStream.close();
}
}
- // Look for namespace handler requirements
- Set<String> namespaces = new HashSet<String>();
- for (Document doc : documents) {
- findNamespaces(namespaces, doc);
- }
- for (String namespace : namespaces) {
- NamespaceHandler handler = namespaceHandlerRegistry.getNamespaceHandler(URI.create(namespace));
- if (handler == null) {
- throw new WaitForDependencyException(NamespaceHandler.class.getName(), null);
- }
+ this.documents = documents;
+ }
+
+ public Set<URI> getNamespaces() {
+ if (documents == null) {
+ throw new IllegalStateException("Documents should be parsed before retrieving required namespaces");
}
- // Parse components
+ Set<URI> namespaces = new HashSet<URI>();
for (Document doc : documents) {
- loadComponents(doc);
+ findNamespaces(namespaces, doc);
}
+ return namespaces;
}
- private void findNamespaces(Set<String> namespaces, Node node) {
+ private void findNamespaces(Set<URI> namespaces, Node node) {
if (node instanceof Element || node instanceof Attr) {
String ns = node.getNamespaceURI();
if (ns != null && !isBlueprintNamespace(ns) && !isBlueprintCompendiumNamespace(ns)) {
- namespaces.add(ns);
+ namespaces.add(URI.create(ns));
}
}
NodeList nl = node.getChildNodes();
@@ -239,6 +233,19 @@
}
}
+ public void populate(NamespaceHandlerRegistry handlers,
+ ComponentDefinitionRegistryImpl registry) {
+ if (this.documents == null) {
+ throw new IllegalStateException("Documents should be parsed before populating the registry");
+ }
+ this.namespaceHandlerRegistry = handlers;
+ this.registry = registry;
+ // Parse components
+ for (Document doc : this.documents) {
+ loadComponents(doc);
+ }
+ }
+
private void loadComponents(Document doc) {
defaultTimeout = TIMEOUT_DEFAULT;
defaultAvailability = AVAILABILITY_DEFAULT;
@@ -331,7 +338,7 @@
}
private void parseBlueprintCompendiumElement(Element element) {
- // TODO
+ // TODO: maybe use a namespace handler instead?
throw new ComponentDefinitionException("Unknown element " + element.getNodeName() + " in namespace " + BLUEPRINT_COMPENDIUM_NAMESPACE);
}
@@ -834,7 +841,6 @@
if (nodeNameEquals(e, VALUE_ELEMENT)) {
interfaceNames.add(getTextValue(e));
} else {
- // TODO: RFC0124 seems to allow other elements here ... is that a bug ?
throw new ComponentDefinitionException("Unsupported element " + e.getNodeName() + " inside an " + INTERFACES_ELEMENT + " element");
}
}
@@ -957,22 +963,6 @@
return handler;
}
- private boolean isBlueprintNamespace(String ns) {
- return BLUEPRINT_NAMESPACE.equals(ns);
- }
-
- private boolean isBlueprintCompendiumNamespace(String ns) {
- return BLUEPRINT_COMPENDIUM_NAMESPACE.equals(ns);
- }
-
- private DocumentBuilderFactory getDocumentBuilderFactory() {
- if (documentBuilderFactory == null) {
- documentBuilderFactory = DocumentBuilderFactory.newInstance();
- documentBuilderFactory.setNamespaceAware(true);
- }
- return documentBuilderFactory;
- }
-
private String getName(Element element) {
if (element.hasAttribute(ID_ATTRIBUTE)) {
return element.getAttribute(ID_ATTRIBUTE);
@@ -980,7 +970,15 @@
return "component-" + ++nameCounter;
}
}
-
+
+ private static boolean isBlueprintNamespace(String ns) {
+ return BLUEPRINT_NAMESPACE.equals(ns);
+ }
+
+ private static boolean isBlueprintCompendiumNamespace(String ns) {
+ return BLUEPRINT_COMPENDIUM_NAMESPACE.equals(ns);
+ }
+
private static boolean nodeNameEquals(Node node, String name) {
return (name.equals(node.getNodeName()) || name.equals(node.getLocalName()));
}
Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/namespace/NamespaceHandlerRegistryImpl.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/namespace/NamespaceHandlerRegistryImpl.java?rev=767623&r1=767622&r2=767623&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/namespace/NamespaceHandlerRegistryImpl.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/namespace/NamespaceHandlerRegistryImpl.java Wed Apr 22 19:05:14 2009
@@ -44,11 +44,13 @@
private final BundleContext bundleContext;
private final Map<URI, NamespaceHandler> handlers;
private final ServiceTracker tracker;
+ private final Map<Listener, Boolean> listeners;
public NamespaceHandlerRegistryImpl(BundleContext bundleContext) {
this.bundleContext = bundleContext;
- handlers = new ConcurrentHashMap<URI, NamespaceHandler>();
+ handlers = new HashMap<URI, NamespaceHandler>();
tracker = new ServiceTracker(bundleContext, NamespaceHandler.class.getName(), this);
+ listeners = new HashMap<Listener, Boolean>();
}
public Object addingService(ServiceReference reference) {
@@ -84,7 +86,7 @@
}
}
- public void registerHandler(NamespaceHandler handler, Map properties) throws Exception {
+ public synchronized void registerHandler(NamespaceHandler handler, Map properties) throws Exception {
Object ns = properties != null ? properties.get(NAMESPACE) : null;
URI[] namespaces = getNamespaces(ns);
for (URI uri : namespaces) {
@@ -94,10 +96,17 @@
}
for (URI uri : namespaces) {
handlers.put(uri, handler);
+ for (Listener listener : listeners.keySet()) {
+ try {
+ listener.namespaceHandlerRegistered(uri);
+ } catch (Throwable t) {
+ t.printStackTrace(); // TODO: log
+ }
+ }
}
}
- private URI[] getNamespaces(Object ns) {
+ private static URI[] getNamespaces(Object ns) {
URI[] namespaces;
if (ns == null) {
throw new IllegalArgumentException("NamespaceHandler service does not have an associated " + NAMESPACE + " property defined");
@@ -130,7 +139,7 @@
return namespaces;
}
- public void unregisterHandler(NamespaceHandler handler, Map properties) throws Exception {
+ public synchronized void unregisterHandler(NamespaceHandler handler, Map properties) throws Exception {
Object ns = properties != null ? properties.get(NAMESPACE) : null;
if (ns instanceof URI[]) {
for (URI uri : (URI[]) ns) {
@@ -140,17 +149,32 @@
}
for (URI uri : (URI[]) ns) {
handlers.remove(uri);
+ for (Listener listener : listeners.keySet()) {
+ try {
+ listener.namespaceHandlerUnregistered(uri);
+ } catch (Throwable t) {
+ t.printStackTrace(); // TODO: log
+ }
+ }
}
} else {
throw new IllegalArgumentException("NamespaceHandler service does not have an associated " + NAMESPACE + " property defined");
}
}
- public NamespaceHandler getNamespaceHandler(URI uri) {
+ public synchronized NamespaceHandler getNamespaceHandler(URI uri) {
return handlers.get(uri);
}
public void destroy() {
tracker.close();
}
+
+ public synchronized void addListener(Listener listener) {
+ listeners.put(listener, Boolean.TRUE);
+ }
+
+ public synchronized void removeListener(Listener listener) {
+ listeners.remove(listener);
+ }
}
Modified: geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/AbstractBlueprintTest.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/AbstractBlueprintTest.java?rev=767623&r1=767622&r2=767623&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/AbstractBlueprintTest.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/AbstractBlueprintTest.java Wed Apr 22 19:05:14 2009
@@ -38,14 +38,19 @@
}
public void destroy() {
}
+ public void addListener(Listener listener) {
+ }
+ public void removeListener(Listener listener) {
+ }
};
return parse(name, handlers);
}
protected ComponentDefinitionRegistryImpl parse(String name, NamespaceHandlerRegistry handlers) throws Exception {
ComponentDefinitionRegistryImpl registry = new ComponentDefinitionRegistryImpl();
- Parser parser = new Parser(handlers, registry, Collections.singletonList(getClass().getResource(name)));
- parser.parse();
+ Parser parser = new Parser();
+ parser.parse(Collections.singletonList(getClass().getResource(name)));
+ parser.populate(handlers, registry);
return registry;
}
Modified: geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/ParserTest.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/ParserTest.java?rev=767623&r1=767622&r2=767623&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/ParserTest.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/ParserTest.java Wed Apr 22 19:05:14 2009
@@ -185,7 +185,12 @@
return null;
}
}
-
+
+ public void addListener(Listener listener) {
+ }
+
+ public void removeListener(Listener listener) {
+ }
}
private static class TestNamespaceHandler implements NamespaceHandler {