From: Erik Brakkee Date: Wed, 14 May 2008 12:10:03 +0000 (+0000) Subject: Now added support for ProvidedInterfaces in Container. X-Git-Tag: wamblee-utils-0.7~735 X-Git-Url: http://wamblee.org/gitweb/?a=commitdiff_plain;h=f9145c96b66fea2db0b9f04b009caf992ad1ab70;p=utils Now added support for ProvidedInterfaces in Container. As a result. UserAdministrationComponent can be simplified and in general writing composite components becomes easier. --- diff --git a/system/general/src/main/java/org/wamblee/system/core/AbstractComponent.java b/system/general/src/main/java/org/wamblee/system/core/AbstractComponent.java index 3c6be957..6567e4e7 100644 --- a/system/general/src/main/java/org/wamblee/system/core/AbstractComponent.java +++ b/system/general/src/main/java/org/wamblee/system/core/AbstractComponent.java @@ -112,12 +112,13 @@ public abstract class AbstractComponent implements Component { @Override public final Type start(Scope aScope) { - LOG.info("Initializing '" + getQualifiedName() + "'"); + LOG.info("Initialization starting '" + getQualifiedName() + "'"); List oldRemaining = _remaining.get(); _remaining.set(new ArrayList(Arrays.asList(getProvidedInterfaces()))); try { Type runtime = doStart(aScope); checkNotStartedInterfaces(); + LOG.info("Initialization finished '" + getQualifiedName() + "'"); return runtime; } finally { _remaining.set(oldRemaining); @@ -164,8 +165,9 @@ public abstract class AbstractComponent implements Component { @Override public void stop(Type aRuntime) { - LOG.info("Stopping '" + getQualifiedName() + "'"); + LOG.info("Stopping initiated '" + getQualifiedName() + "'"); doStop(aRuntime); + LOG.info("Stopping completed '" + getQualifiedName() + "'"); } protected abstract void doStop(Type aRuntime); diff --git a/system/general/src/main/java/org/wamblee/system/core/Container.java b/system/general/src/main/java/org/wamblee/system/core/Container.java index 1c19be34..d117da95 100644 --- a/system/general/src/main/java/org/wamblee/system/core/Container.java +++ b/system/general/src/main/java/org/wamblee/system/core/Container.java @@ -185,23 +185,42 @@ public class Container extends AbstractComponent { } private void validateProvidedInterfacesArePresent() { - List provided = new ArrayList(); - for (Component component : _components) { - provided.addAll(Arrays.asList(component.getProvidedInterfaces())); - } for (ProvidedInterface service : getProvidedInterfaces()) { - // TODO provided interfaces by components could be - // provide subclasses or implementations of the - // provided interfaces of the container. - // The code below assumes an exact match. - if (!(provided.contains(service))) { - throw new SystemAssemblyException(getQualifiedName() + ": Service '" - + service - + "' is not provided by any of its components"); + findProvidedInterface(service); + } + } + + /** + * Finds the component and provided interface that matches a provided interface of this + * container. + * @param aProvided Interface to provide externally. + * @return Pair of component and provided interface + * @throws SystemAssemblyException In case there are multiple matches or no match at all. + */ + private Pair findProvidedInterface(ProvidedInterface aProvided) { + List> result = + new ArrayList>(); + for (Component component: _components) { + for (ProvidedInterface provided: component.getProvidedInterfaces()) { + if ( aProvided.equals(provided) ) { + result.add(new Pair(component, provided)); + } } } + if ( result.size() == 0) { + throw new SystemAssemblyException(getQualifiedName() + ": Service '" + + aProvided + + "' is not provided by any of its components"); + } + if ( result.size() > 1) { + throw new SystemAssemblyException(getQualifiedName() + ": Service '" + + aProvided + + "' is provided by multiple components: " + result); + } + return result.get(0); } + /** * Seal the container, meaning that no further components or interfaces may * be added. @@ -235,10 +254,19 @@ public class Container extends AbstractComponent { validate(); Scope scope = new DefaultScope(getProvidedInterfaces(), aExternalScope); doStartOptionalDryRun(scope, false); + exposeProvidedInterfaces(aExternalScope, scope); seal(); return scope; } + private void exposeProvidedInterfaces(Scope aExternalScope, Scope aInternalScope) { + for (ProvidedInterface intf: getProvidedInterfaces()) { + Pair found = findProvidedInterface(intf); + Object svc = aInternalScope.getInterfaceImplementation(found.getSecond(), Object.class); + addInterface(intf, svc, aExternalScope); + } + } + private void doStartOptionalDryRun(Scope aScope, boolean aDryRun) { LOG.info("Starting '" + getQualifiedName() + "'"); diff --git a/system/general/src/test/java/org/wamblee/system/core/ContainerTest.java b/system/general/src/test/java/org/wamblee/system/core/ContainerTest.java index 2104e3a9..da8f8350 100644 --- a/system/general/src/test/java/org/wamblee/system/core/ContainerTest.java +++ b/system/general/src/test/java/org/wamblee/system/core/ContainerTest.java @@ -69,30 +69,33 @@ public class ContainerTest extends TestCase { Serializable.class); ProvidedInterface prov3 = new DefaultProvidedInterface("name", MyMultiple.class); - + Component client = new Application("client"); Component dummy = new Application("dummy"); - - InterfaceRestriction noRestriction = new InterfaceRestriction() { - @Override + + InterfaceRestriction noRestriction = new InterfaceRestriction() { + @Override public boolean isViolated(Component aClient, RequiredInterface aRequired, Component aServer, ProvidedInterface aProvided) { return false; - } + } }; AssertionUtils.assertEquals(new ProvidedInterface[] { prov1 }, - Container.filterProvidedServices(client, req1, - createProvidedInput(new ProvidedInterface[] { prov1 }, dummy), noRestriction)); + Container.filterProvidedServices(client, req1, + createProvidedInput(new ProvidedInterface[] { prov1 }, + dummy), noRestriction)); AssertionUtils.assertEquals(new ProvidedInterface[] { prov1 }, - Container.filterProvidedServices(client, req1, - createProvidedInput(new ProvidedInterface[] { prov1, prov2 }, dummy), noRestriction)); + Container.filterProvidedServices(client, req1, + createProvidedInput(new ProvidedInterface[] { prov1, + prov2 }, dummy), noRestriction)); AssertionUtils.assertEquals(new ProvidedInterface[] { prov1, prov3 }, - Container.filterProvidedServices(client, req1, - createProvidedInput(new ProvidedInterface[] { prov1, prov3 }, dummy), noRestriction)); - - InterfaceRestriction everything = new InterfaceRestriction() { + Container.filterProvidedServices(client, req1, + createProvidedInput(new ProvidedInterface[] { prov1, + prov3 }, dummy), noRestriction)); + + InterfaceRestriction everything = new InterfaceRestriction() { @Override public boolean isViolated(Component aClient, RequiredInterface aRequired, Component aServer, @@ -100,10 +103,11 @@ public class ContainerTest extends TestCase { return true; } }; - AssertionUtils.assertEquals(new ProvidedInterface[0], - Container.filterProvidedServices(client, req1, - createProvidedInput(new ProvidedInterface[] { prov1, prov3 }, dummy), everything)); - + AssertionUtils.assertEquals(new ProvidedInterface[0], Container + .filterProvidedServices(client, req1, createProvidedInput( + new ProvidedInterface[] { prov1, prov3 }, dummy), + everything)); + } public void testEnvironmentApplication() { @@ -504,22 +508,66 @@ public class ContainerTest extends TestCase { assertEquals(env1.getString(), app.getString()); assertFalse(env2.getString().equals(app.getString())); } - - public void testProvidedInDifferentScopes() { - // Scoping problem occurred. Externally and internally provided components clashed - // because unique id generation in the scope was wrong. - + + public void testProvidedInDifferentScopes() { + // Scoping problem occurred. Externally and internally provided + // components clashed + // because unique id generation in the scope was wrong. + StringComponent str = new StringComponent("string"); Application app = new Application("app"); - Container container = new Container("top").addComponent(str).addComponent(app); - container.addRequiredInterface(new DefaultRequiredInterface("integer", Integer.class)); - - ProvidedInterface provided = new DefaultProvidedInterface("hallo", Integer.class); - container.getRequiredInterfaces()[0] - .setProvider(provided); - + Container container = new Container("top").addComponent(str) + .addComponent(app); + container.addRequiredInterface(new DefaultRequiredInterface("integer", + Integer.class)); + + ProvidedInterface provided = new DefaultProvidedInterface("hallo", + Integer.class); + container.getRequiredInterfaces()[0].setProvider(provided); + Scope external = new DefaultScope(new ProvidedInterface[0]); external.publishInterface(provided, 100); Scope scope = container.start(external); } + + public void testProvidedInterfaces() { + Environment env = new Environment(_tracker); + Container envcontainer = new Container("0").addComponent(env) + .addProvidedInterface( + new DefaultProvidedInterface("string", String.class)) + .addProvidedInterface( + new DefaultProvidedInterface("integer", Integer.class)); + Scope scope = envcontainer.start(); + + AssertionUtils.assertEquals(new String[] { "start.environment" }, + _tracker.getEvents(Thread.currentThread()).toArray( + new String[0])); + + envcontainer.stop(scope); + } + + public void testCoupleTwoContainers() { + Environment env = new Environment(_tracker); + Container envcontainer = new Container("0").addComponent(env) + .addProvidedInterface( + new DefaultProvidedInterface("string", String.class)) + .addProvidedInterface( + new DefaultProvidedInterface("integer", Integer.class)); + + Application app = new Application(_tracker); + Container appcontainer = new Container("1").addComponent(app) + .addRequiredInterface( + new DefaultRequiredInterface("string", String.class)) + .addRequiredInterface( + new DefaultRequiredInterface("integer", Integer.class)); + + Container top = new Container("top"); + top.addComponent(envcontainer).addComponent(appcontainer); + + top.start(); + AssertionUtils.assertEquals(new String[] { "start.environment", "start.application" }, + _tracker.getEvents(Thread.currentThread()).toArray( + new String[0])); + + } }