diff options
Diffstat (limited to 'israfil-foundation-container')
33 files changed, 2662 insertions, 0 deletions
diff --git a/israfil-foundation-container/pom.xml b/israfil-foundation-container/pom.xml new file mode 100644 index 0000000..742064d --- /dev/null +++ b/israfil-foundation-container/pom.xml @@ -0,0 +1,21 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + </parent> + <artifactId>israfil-foundation-container</artifactId> + <name>Israfil Foundation Trivial IoC Container</name> + <version>1.0.0-SNAPSHOT</version> + <url>http://www.israfil.net/projects/foundation/${artifactId}</url> + <inceptionYear>2008</inceptionYear> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> +</project>
\ No newline at end of file diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractContainer.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractContainer.java new file mode 100644 index 0000000..fe6a978 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractContainer.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import net.israfil.foundation.container.error.ComponentAlreadyRegisteredError; + +/** + * A convenience abstract class that implements basic component storage and + * lookup, as well as basic component instance assignment. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + * + */ +public abstract class AbstractContainer implements Container { + + private final Map components = new HashMap(); + + private final Container parent; + + private boolean running = false; + + public AbstractContainer() { + parent = null; + } + + public AbstractContainer(Container parent) { + this.parent = parent; + } + + protected boolean isStored(Object key) { + return components.containsKey(key); + } + + public boolean hasComponent(Object key) { + return components.containsKey(key) || (parent != null && parent.hasComponent(key)); + } + + public boolean isRunning() { + return this.running; + } + + public void start() { + this.running = true; + } + + protected Container getParent() { return parent; } + + protected Object getStoredComponent(Object key) { + Object result = components.get(key); + if (result == null && parent != null) + result = parent.getComponent(key); + return result; + } + + protected void store(Object key, Object component) { + if (hasComponent(key)) { + if (getComponent(key) == component) return; + throw new ComponentAlreadyRegisteredError("Object already registered for key: " + key); + } + components.put(key, component); + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractStartable.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractStartable.java new file mode 100644 index 0000000..c4047f1 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractStartable.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +/** + * A convenience implementation of Startable + */ +public abstract class AbstractStartable implements Startable { + + private boolean started = false; + + /** + * @see Startable.start(); + */ + public void start() { + this.started = true; + } + + /** + * @see Startable.isRunning(); + */ + public boolean isRunning() { return started; } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdaptableContainer.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdaptableContainer.java new file mode 100644 index 0000000..623851b --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdaptableContainer.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +/** + * A Container that uses an AutoWiringAdapter to ensure that + * components can be created appropriately with their dependencies + * satisfied automatically. + * + */ +public interface AutoWiringAdaptableContainer extends Container { + + public void start(); + + /** + * Register a component. The component's class must satisfy the + * test <code>Injectable.class.isAssignableFrom(type);</code> + * to ensure that the provided component implements the lifecycle + * mechanisms necessary to auto-wire. + * + */ + public void registerType(Object key, AutoWiringAdapter componentAdapter); + + /** + * Register an independent component. This is a convenience registry + * method for those components without dependencies, and which + * have a default constructor. Only classes which fit these + * criteria should be used in this method. + * + */ + public void registerType(Object key, Class<?> implementation); + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdapter.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdapter.java new file mode 100644 index 0000000..56436a5 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdapter.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +/** + * An adapter interface that's used in the "AutoWiringContainer" + * to allow the user to specify a component's dependencies upon registration. + * This is not ideal, in that it's not auto-discovered constructor-based + * dependency injection, but since dynamic reflection is not available in the + * J2ME CLDC 1.1 spec, an alternate and generic injection mechanism + * is necessary. Implementors of this interface should be CLDC safe. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + */ +public interface AutoWiringAdapter { + + /** + * This method should return a list of keys defining the dependencies + * this object requires to operate, in the order expected by the + * create(Object[]) method. + */ + public Object[] dependencies(); + + /** + * Returns the type that this adapter will create. This should be the + * most concrete (narrowest) common type this adapter will create, if + * there is more than one possibility. + */ + public Class getType(); + + /** + * A method that implementors use to create a component given a set of + * parameters. Callers must return the parameters in the order provided + * by the dependencies() method. + */ + public Object create(Object[] parameters) throws IllegalAccessException, InstantiationException; + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Container.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Container.java new file mode 100644 index 0000000..0bc0982 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Container.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +/** + * A container for components that will satisfy requests if the + * component is available. How these component requests are satisfied + * are implementation dependent, as well as how inter-component + * dependencies are resolved. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + * + */ +public interface Container { + + /** + * Returns true if the Component is available and prepared. + * It throws a ContainerNotStarted runtime exception if the this method + * is used before the container is started. + * + * This method must be implemented by implementors of Container in a + * thread-safe and reentrant way. + */ + public boolean hasComponent(Object key); + + /** + * Returns the component named by the key if it is available, or null if no + * such component is available. It throws a ContainerNotStarted runtime + * exception if this method is used before the container is started. + * + * This method must be implemented by implementors of Container in a + * thread-safe and reentrant way. + */ + public Object getComponent(Object key); + + /** + * Begin the lifecycle of the container, after which components should be + * accessible. Implementors should stop any component registration as of + * the start() call. Subsequent start() calls should be ignored. + */ + public void start(); + + /** + * Returns true if the container has been started, and false if it has + * not been started. + */ + public boolean isRunning(); + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultAutoWiringAdaptableContainer.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultAutoWiringAdaptableContainer.java new file mode 100644 index 0000000..89d3b11 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultAutoWiringAdaptableContainer.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2008-2009 Israfil Consulting Services Corporation + * Copyright (c) 2008-2009 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + + + +/** + * A deprecated class that was the old name for DefaultContainer. + * Maintained to reduce API breakage. + * @Deprecated Class renamed to DefaultContainer. + */ +public class DefaultAutoWiringAdaptableContainer extends DefaultContainer { + + public DefaultAutoWiringAdaptableContainer() { + super(); + } + + public DefaultAutoWiringAdaptableContainer(boolean failEarly) { + super(failEarly); + } + + public DefaultAutoWiringAdaptableContainer(Container parent, + boolean failEarly) { + super(parent, failEarly); + } + + public DefaultAutoWiringAdaptableContainer(Container parent) { + super(parent); + } + + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultContainer.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultContainer.java new file mode 100644 index 0000000..f11dc47 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultContainer.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +import java.util.HashMap; +import java.util.Map; + +import net.israfil.foundation.container.adapters.IndependentAutoWiringAdapter; +import net.israfil.foundation.container.error.ComponentAlreadyRegisteredError; +import net.israfil.foundation.container.error.CouldNotCreateComponentError; +import net.israfil.foundation.container.error.UnsatisfiedDependencyError; +import net.israfil.foundation.container.util.CyclicalReferenceDetectionUtil; +import net.israfil.foundation.container.util.NonDuplicateStack; + + +/** + * A default implementation of AutoWiringAdaptableContainer, a Container + * that uses an AutoWiringAdapter to ensure that components can be + * created appropriately with their dependencies satisfied automatically. + * + * This adapter is intended for constructor injection, but relies on the + * adapter to perform such. No reflection is used by this class itself. + * + */ +public class DefaultContainer extends AbstractContainer implements AutoWiringAdaptableContainer { + + private Map<Object,Object> registry = new HashMap<Object,Object>(); + + private final boolean failEarly; + + private boolean starting = false; + + private final Object CREATION_MUTEX = new Object(); + + /** + * A default constructor that will throw errors regarding circular + * dependencies at registration time, throw missing dependency errors + * at wire-up (getComponent()) time, and has no parent. + * + * @param failEarly A boolean to indicate that this container should detect missing or circular dependencies at start() time. + */ + public DefaultContainer() { + super(); + this.failEarly = false; + } + + /** + * Construct this container such that it detects missing dependencies + * upon invocation of start(). Otherwise, it will fail at wire time, + * rather than at registration time. Circular references will give errors + * at registration time. + * + * @param failEarly A boolean to indicate that this container should detect missing or circular dependencies at start() time. + */ + public DefaultContainer(boolean failEarly) { + super(); + this.failEarly = failEarly; + } + + /** + * This method constructs a DefaultAutoWiringAdaptableContainer that + * has a parent container for backup resolution. The parent container + * can be of any type of Container. + * + * @param parent The parent container (optional) + */ + public DefaultContainer(Container parent) { + super(parent); + this.failEarly = false; + } + + /** + * Construct this container such that it detects missing dependencies + * upon invocation of start(). Otherwise, it will fail at wire time, + * rather than at registration time. Circular references will give errors + * at registration time. This method also provides for a parent container. + * The parent container can be of any type of Container. + * + * @param failEarly A boolean to indicate that this container should detect missing or circular dependencies at start() time. + * @param parent The parent Container (optional) + */ + public DefaultContainer(Container parent, boolean failEarly) { + super(parent); + this.failEarly = failEarly; + } + + public synchronized void start() { + if (isRunning() || + starting) return; + if (getParent() != null && !getParent().isRunning()) throw new RuntimeException("Parent container is not started."); + this.starting = true; + if (failEarly) { + for (Object key : registry.keySet()) { + // force get each component, forcing all wiring. + Object ignore = getComponent(key); + if (false) ignore.hashCode(); // cover warning - compiler should remove + } + } + super.start(); + starting = false; + } + + public void registerType(Object key, Class<?> componentType) { + registerType(key,componentType, 0); + } + + protected void registerType(Object key, Class<?> componentType, long timeout) { + registerType(key,new IndependentAutoWiringAdapter(componentType), timeout); + } + + public void registerType(Object key, AutoWiringAdapter componentAdapter) { + registerType(key,componentAdapter,0); + } + + /** + * Registers a component for later instantiation and (optionally) startup. + * + * @param key the key by which this component will be identified in the system + * @param componentAdapter an AutoWiringAdapter for creating this component and listing its dependencies + * @param timeout an (optional) timeout applied to any startup lifecycle + */ + protected void registerType(Object key, AutoWiringAdapter componentAdapter, long timeout) { + if (this.isRunning()) throw new RuntimeException("Cannot register when container is started."); + // FIXME: Figure out whether to support parent registry checking. Probably can't do it. + + if (registry.containsKey(key)) throw new ComponentAlreadyRegisteredError("Component already registered for " + key); + detectCircularDependencies(key,componentAdapter); + registry.put(key, componentAdapter); + } + + private void detectCircularDependencies(Object key,AutoWiringAdapter componentAdapter) { + NonDuplicateStack nds = new NonDuplicateStack(); + nds.push(key); + CyclicalReferenceDetectionUtil.detectCircularDependencies(this.registry, nds, componentAdapter); + } + + /** + * This method wires the object up with its dependencies, providing said + * dependencies to the object's adapter. It also starts the object if its + * startable + * @param originalKey + * @param adapter + * @return + */ + private Object wireObject(Object originalKey, AutoWiringAdapter adapter) { + Object[] dependencies = adapter.dependencies(); + Object[] parameters = new Object[dependencies.length]; + for (int depn = 0; depn < dependencies.length; depn++ ) { + Object key = adapter.dependencies()[depn]; + parameters[depn] = getComponent(key); + if (parameters[depn] == null) throw new UnsatisfiedDependencyError("Could not materialize dependency for key " + key); + } + try { + Object o = adapter.create(parameters); + if (o == null) throw new InstantiationException("Could not create a non-null object. Adapter " + adapter.getClass().getName() + " returned null."); + else { + try { + Startable s = ((Startable)o); + if (!s.isRunning()) s.start(); + } catch (ClassCastException e) {} + return o; + } + } catch (IllegalAccessException e) { + throw new CouldNotCreateComponentError("Could not create component " + originalKey + " of type " + adapter.getType(),e); + } catch (InstantiationException e) { + throw new CouldNotCreateComponentError("Could not create component " + originalKey + " of type " + adapter.getType(),e); + } catch (Throwable e) { + throw new CouldNotCreateComponentError("Could not create component " + originalKey + " of type " + adapter.getType(),e); + } + } + + public Object getComponent(Object key) { + Object component = super.getStoredComponent(key); + if (component == null && registry.containsKey(key)) { + synchronized (CREATION_MUTEX) { + if (component == null) { // in case following thread gets in just after storage. + component = wireObject(key,(AutoWiringAdapter)registry.get(key)); + store(key, component); + } + } + } + return component; + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Startable.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Startable.java new file mode 100644 index 0000000..34b0399 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Startable.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +/** + * A simple interface that, if implemented, allows a component + * to participate in a startup phase of lifecycle. + */ +public interface Startable { + + /** + * Begin the lifecycle of the component, after which it should be + * usable. This component should only act on its own startup + * lifecycle, and should assume that any components that are + * provided through dependency injection are already started + * before this command is executed. + */ + public void start(); + + /** + * Returns true if the container has been started, and false if it has + * not been started. + */ + public boolean isRunning(); + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/AbstractAutoWiringAdapter.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/AbstractAutoWiringAdapter.java new file mode 100644 index 0000000..6500275 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/AbstractAutoWiringAdapter.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.adapters; + +import net.israfil.foundation.container.AutoWiringAdapter; + +/** + * A convenience implementation of AutoWiringAdapter which can be used + * for those clases that have no dependencies and have a default constructor. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + */ +public abstract class AbstractAutoWiringAdapter implements AutoWiringAdapter{ + + private final Object[] dependencies; + + private final Class type; + + public AbstractAutoWiringAdapter(Class type, Object[] dependencies) { + if (type == null) + throw new IllegalArgumentException("An independent component must have a type."); + this.type = type; + this.dependencies = dependencies; + } + + public Object[] dependencies() { return dependencies; } + + public Class getType() { return type; } + + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/IndependentAutoWiringAdapter.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/IndependentAutoWiringAdapter.java new file mode 100644 index 0000000..ff945a8 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/IndependentAutoWiringAdapter.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.adapters; + +import java.util.Map; + +/** + * A convenience implementation of AutoWiringAdapter which can be used + * for those clases that have no dependencies and have a default constructor. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + */ +public class IndependentAutoWiringAdapter extends AbstractAutoWiringAdapter{ + + private static final Object[] NO_DEPENDENCIES = {}; + + public IndependentAutoWiringAdapter(Class type) { + super(type, NO_DEPENDENCIES); + } + + /** + * This method implements AutoWiringAdapter.create() but throws + * a runtime exception if any parameters are passed, and uses + * the default (no parameter) constructor via Class.newInstance(); + * to generate the new instance. + */ + public Object create(Object[] parameters) throws IllegalAccessException, InstantiationException { + if (parameters != null && parameters.length > 0) + throw new IllegalArgumentException("Cannot pass any parameters to the creation of an independent component."); + return getType().newInstance(); + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredError.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredError.java new file mode 100644 index 0000000..a065d81 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredError.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +public class ComponentAlreadyRegisteredError extends RuntimeException { + + private static final long serialVersionUID = 7557424125890830358L; + + public ComponentAlreadyRegisteredError() { + super(); + } + + public ComponentAlreadyRegisteredError(String message) { + super(message); + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CouldNotCreateComponentError.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CouldNotCreateComponentError.java new file mode 100644 index 0000000..f8f9563 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CouldNotCreateComponentError.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + + +public class CouldNotCreateComponentError + extends RuntimeException { + + private static final long serialVersionUID = 398473685547742652L; + + public CouldNotCreateComponentError() { + super(); + } + + public CouldNotCreateComponentError(Throwable t) { + super(t); + } + + public CouldNotCreateComponentError(String message) { + super(message); + } + + public CouldNotCreateComponentError(String message, Throwable t) { + super(message,t); + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CyclicalDependencyError.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CyclicalDependencyError.java new file mode 100644 index 0000000..067e364 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CyclicalDependencyError.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +public class CyclicalDependencyError extends RuntimeException { + + private static final long serialVersionUID = 2260997982445143566L; + + public CyclicalDependencyError() { + super(); + } + + public CyclicalDependencyError(String message) { + super(message); + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/UnsatisfiedDependencyError.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/UnsatisfiedDependencyError.java new file mode 100644 index 0000000..3110fb9 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/UnsatisfiedDependencyError.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +public class UnsatisfiedDependencyError extends RuntimeException { + + private static final long serialVersionUID = 502309807798988770L; + + public UnsatisfiedDependencyError() { + super(); + } + + public UnsatisfiedDependencyError(String message) { + super(message); + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/CyclicalReferenceDetectionUtil.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/CyclicalReferenceDetectionUtil.java new file mode 100644 index 0000000..eb9f25c --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/CyclicalReferenceDetectionUtil.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.util; + +import java.util.Map; + +import net.israfil.foundation.container.AutoWiringAdapter; +import net.israfil.foundation.container.error.CyclicalDependencyError; + +/** + * A utility class that provides convenience methods for circular + * reference detection. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + */ +public class CyclicalReferenceDetectionUtil { + public static void detectCircularDependencies(Map registry, NonDuplicateStack nds, AutoWiringAdapter componentAdapter) { + Object[] deps = componentAdapter.dependencies(); + for (int i = 0; i < deps.length; i++) { + if (registry.containsKey(deps[i])) { + try { + nds.push(deps[i]); + } catch (IllegalArgumentException e) { + throw new CyclicalDependencyError("Item " + deps[i] + " is involved in a cyclic dependency. The full path is: " + nds); + } + detectCircularDependencies(registry, nds, (AutoWiringAdapter)registry.get(deps[i])); + nds.pop(); + } + } + } +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/NonDuplicateStack.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/NonDuplicateStack.java new file mode 100644 index 0000000..d253024 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/NonDuplicateStack.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.util; + +import java.util.Stack; + +/** + * A simple stack object which throws an IllegalArgumentException if an + * attempt is made to push an object already contained within the stack. + * + * Primarily used for circular reference detection. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + */ +public class NonDuplicateStack<T> extends Stack<T> { + + private static final long serialVersionUID = -5777711467165769847L; + + public T push(T item) { + if (contains(item)) throw new IllegalArgumentException("Duplicate item."); + return super.push(item); + } + +} diff --git a/israfil-foundation-container/src/site/apt/index.apt b/israfil-foundation-container/src/site/apt/index.apt new file mode 100755 index 0000000..10a0281 --- /dev/null +++ b/israfil-foundation-container/src/site/apt/index.apt @@ -0,0 +1,45 @@ + ------
+ Israfil Micro-Container
+ ------
+ Christian Edward Gruber
+ ------
+ May 2, 2007
+
+Overview
+
+ The micro-container is an extremely lightweight IoC container supporting
+ dependency injection. It is built with the principles in mind that
+ spawned {{{http://www.picocontainer.org/} pico-container}} but with the
+ explicit constraints to which J2ME applications centered around the
+ CLDC 1.1 are bound. This includes a complete absence of any constructor
+ or method lookup (reflection) or dynamic proxy support.
+
+ Like pico-container, Israfil's micro-container only handles the
+ registration and vending of components, not additional services such as
+ persistence, and the like.
+
+Isn't Micro bigger than Pico?
+
+ Yes, but micro-container wasn't as taken, and israfil-micro is a placeholder
+ for any further frameworks that might be developed in the J2ME footprint.
+ I briefly considered femto-container, but it was too obscure even for me.
+
+Can I use this in commercial or other software?
+
+ Yes. The micro-container, as with all Israfil Micro and Foundation libraries
+ are licensed under the terms of the BSD license, which provides you with a
+ license to distribute with or without modification, and to prepare derivative
+ works, with the sole exception that you retain the notice (specific terms
+ are available in the license page linked from the menu.) The short answer
+ is yes, go for it, it won't cost you a penny, and you won't be obliged to
+ show anyone your code.
+
+How do I use it?
+
+ I recommend looking at pico-container's site for really good theoretical
+ presentations of this kind of software. Tapestry5 also contains an ioc
+ framework par-excellence, and it has some ok docs. Some specific usage
+ documentation for this framework (around staging the container and getting
+ things set up in a practical application) are available in the usage page
+ linked from the menu.
+
\ No newline at end of file diff --git a/israfil-foundation-container/src/site/apt/lifecycle.apt b/israfil-foundation-container/src/site/apt/lifecycle.apt new file mode 100644 index 0000000..3a62be5 --- /dev/null +++ b/israfil-foundation-container/src/site/apt/lifecycle.apt @@ -0,0 +1,111 @@ + ------ + Israfil Micro-Container : Component Lifecycle + ------ + Christian Edward Gruber + ------ + May 2, 2007 + + + Since one bad pattern in java is to engage in all sorts of side behaviours + during construction, components can separate construction from initialization + by implementing the Startable interface. Startable components are started + before they are provided to any caller. + +%{toc} + +The Startable interface + + The Startable interface is quite simple: + +------------------- + +package net.israfil.micro.container; + +public interface Startable { + + public void start(); + + public boolean isRunning(); + +} + +------------------- + + Implementors should start whatever they need to in order to be ready to + accept calls, including marshalling any resources necessary, etc. + + Care should be taken to time-out appropriately, as the container offers + its thread to the component during this initialization, and faulty + initialization can lock the container. + +Registering components with dependencies + + Registration of components with dependencies is a bit more complicated, as it + requires an adapter: + +------------------- + +public void registerType(Object key, AutoWiringAdapter componentAdapter); + +------------------- + + AutoWiringAdapters can be created on the fly, for instance by using an anonymous + inner class that implements AutoWiringAdapter or extending AbstractAutoWiringAdapter: + +------------------- + +container.registerType(ComponentThree.class,new AbstractAutoWiringAdapter( + ComponentThree.class, new Object[] {ComponentOne.class} + ) { + public Object create(Object[] params) throws IllegalAccessException, InstantiationException { + return new ComponentThreeImpl((ComponentOne)params[0]); + } +}); + +------------------- + + Another option is to create a constant adapter on the component itself + +------------------- + +public class ComponentThreeImpl implements ComponentThree { + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + ComponentThree.class, new Object[] {ComponentOne.class} + ) { + public Object create(Object[] params) throws IllegalAccessException, InstantiationException { + return new ComponentThreeImpl((ComponentOne)params[0]); + } + }); + + private final ComponentOne one; + + public ComponentThreeImpl(ComponentOne one) { + this.one = one; + } + + public void doStuff() { one.whatever(); } +} + +------------------- + + Having created this adapter constant, you can then more easily register the + component in the following way: + +------------------- + +container.registerType(ComponentThree.class,ComponentThreeImpl.adapter); + +------------------- + +Retrieving components + + Retrieving components is quite simple, using the getComponent method. + +------------------- + +ComponentThree three = (ComponentThree)container.getComponent(ComponentThree.class); +three.doStuff(); + +------------------- + + diff --git a/israfil-foundation-container/src/site/apt/usage.apt b/israfil-foundation-container/src/site/apt/usage.apt new file mode 100644 index 0000000..54ce418 --- /dev/null +++ b/israfil-foundation-container/src/site/apt/usage.apt @@ -0,0 +1,106 @@ + ------ + Israfil Micro-Container : Usage + ------ + Christian Edward Gruber + ------ + May 2, 2007 + + + The default container is an auto-wiring container which allows for registration + of components quite simply, if they have no dependencies. Components with + dependencies require the use of an adapter which explicitly declares the + dependencies, and provides a builder method which receives the dependencies and + explicitly constructs the component, avoiding any use of reflection, which is + not supported in the CLDC 1.1 profile. + +%{toc} + +Setting up the auto-wiring container. + + Setting up the container should be done early in your entry-point code. + The default container auto-wires components on first use of the component, + unless configured to pre-initialize them. This allows for early creation + of the container and registration of components without incurring the + up-front performance cost. + + Registration for independent components works quite simply: + +------------------- + +AutoWiringAdaptableContainer container = new DefaultAutoWiringAdaptablecContainer(); +container.registerType(ComponentOne.class,ComponentOneImpl.class); +container.registerType(ComponentTwo.class,ComponentTwoImpl.class); + +------------------- + +Registering components with dependencies + + Registration of components with dependencies is a bit more complicated, as it + requires an adapter: + +------------------- + +public void registerType(Object key, AutoWiringAdapter componentAdapter); + +------------------- + + AutoWiringAdapters can be created on the fly, for instance by using an anonymous + inner class that implements AutoWiringAdapter or extending AbstractAutoWiringAdapter: + +------------------- + +container.registerType(ComponentThree.class,new AbstractAutoWiringAdapter( + ComponentThree.class, new Object[] {ComponentOne.class} + ) { + public Object create(Object[] params) throws IllegalAccessException, InstantiationException { + return new ComponentThreeImpl((ComponentOne)params[0]); + } +}); + +------------------- + + Another option is to create a constant adapter on the component itself + +------------------- + +public class ComponentThreeImpl implements ComponentThree { + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + ComponentThree.class, new Object[] {ComponentOne.class} + ) { + public Object create(Object[] params) throws IllegalAccessException, InstantiationException { + return new ComponentThreeImpl((ComponentOne)params[0]); + } + }); + + private final ComponentOne one; + + public ComponentThreeImpl(ComponentOne one) { + this.one = one; + } + + public void doStuff() { one.whatever(); } +} + +------------------- + + Having created this adapter constant, you can then more easily register the + component in the following way: + +------------------- + +container.registerType(ComponentThree.class,ComponentThreeImpl.adapter); + +------------------- + +Retrieving components + + Retrieving components is quite simple, using the getComponent method. + +------------------- + +ComponentThree three = (ComponentThree)container.getComponent(ComponentThree.class); +three.doStuff(); + +------------------- + + diff --git a/israfil-foundation-container/src/site/site.xml b/israfil-foundation-container/src/site/site.xml new file mode 100644 index 0000000..d580c65 --- /dev/null +++ b/israfil-foundation-container/src/site/site.xml @@ -0,0 +1,20 @@ +<project>
+ <body>
+ <menu name="Parent"> + <item name="${parent.name}" href="../index.html"/> + </menu> + <menu name="Overview">
+ <item name="Introduction" href="index.html"/>
+ <item name="Usage" href="usage.html"/> + <item name="Lifecycle" href="lifecycle.html"/> + <!-- <item name="FAQ" href="faq.html"/> -->
+ </menu> + <!--
+ <menu name="Examples">
+ <item name="Simple Flex app in a WAR project" href="examples/simple_war_project.html"/> + <item name="Flex app with extra params" href="examples/extra_parameters_project.html"/> + </menu> + -->
+ ${reports}
+ </body>
+</project>
\ No newline at end of file diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/ContainerTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/ContainerTest.java new file mode 100644 index 0000000..ab0e624 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/ContainerTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +import net.israfil.foundation.container.error.ComponentAlreadyRegisteredError; + +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +public class ContainerTest { + + AbstractContainer container = null; + AbstractContainer child = null; + + + @BeforeMethod(alwaysRun=true) + public void setUp() { + container = new AbstractContainer() { + public void start() { } + public Object getComponent(Object key) { return getStoredComponent(key); } + }; + child = new AbstractContainer(container) { + public void start() { } + public Object getComponent(Object key) { return getStoredComponent(key); } + }; + } + + @AfterMethod(alwaysRun=true) + public void tearDown() { + child = null; + container = null; + } + + @Test + public void testContainerWithSingleComponent() { + FakeComponent component = new FakeComponent1(); + container.store(FakeComponent.class, component); + Assert.assertSame(container.getComponent(FakeComponent.class), component); + } + + @Test + public void testContainerWithMultipleComponents() { + FakeComponent component = new FakeComponent1(); + FakeDependentComponent component2 = new FakeDependentComponent(component); + container.store(FakeComponent.class, component); + container.store(FakeDependentComponent.class, component2); + Assert.assertSame(container.getComponent(FakeComponent.class), component); + Assert.assertSame(container.getComponent(FakeDependentComponent.class), component2); + } + + @Test(expectedExceptions=ComponentAlreadyRegisteredError.class) + public void testContainerWithDuplicateComponents() { + FakeComponent component1 = new FakeComponent1(); + FakeComponent component2 = new FakeComponent2(); + container.store(FakeComponent.class,component1); + container.store(FakeComponent.class,component2); + } + + @Test + public void testContainerWithRepeatedRegistrationsOfTheSameComponent() { + FakeComponent component1 = new FakeComponent1(); + container.store(FakeComponent.class,component1); + container.store(FakeComponent.class,component1); + } + + @Test + public void testContainerWithParent() { + FakeComponent component1 = new FakeComponent1(); + container.store(FakeComponent.class,component1); + Assert.assertTrue(child.hasComponent(FakeComponent.class)); + Assert.assertSame(child.getComponent(FakeComponent.class), component1); + } + + @Test(expectedExceptions=ComponentAlreadyRegisteredError.class) + public void testDuplicateRegistrationWithFirstObjectInParent() { + FakeComponent component1 = new FakeComponent1(); + FakeComponent component2 = new FakeComponent2(); + container.store(FakeComponent.class,component1); + child.store(FakeComponent.class,component2); + } + + @Test + public void testDuplicateComponentsInPeerContainers() { + AbstractContainer child2 = new AbstractContainer(container) { + public void start() { } + public Object getComponent(Object key) { return getStoredComponent(key); } + }; + FakeComponent component1 = new FakeComponent1(); + FakeComponent component2 = new FakeComponent2(); + child.store(FakeComponent.class,component1); + child2.store(FakeComponent.class,component2); + Assert.assertTrue(child.hasComponent(FakeComponent.class)); + Assert.assertSame(child.getComponent(FakeComponent.class), component1); + Assert.assertNotSame(child2.getComponent(FakeComponent.class), component1); + Assert.assertTrue(child2.hasComponent(FakeComponent.class)); + Assert.assertSame(child2.getComponent(FakeComponent.class), component2); + Assert.assertNotSame(child2.getComponent(FakeComponent.class), component1); + Assert.assertFalse(container.hasComponent(FakeComponent.class)); + } + + public abstract class FakeComponent { + public abstract boolean isTrue(); + } + public class FakeComponent1 extends FakeComponent { + public boolean isTrue() { return false; } + } + public class FakeComponent2 extends FakeComponent { + public boolean isTrue() { return false; } + } + public class FakeDependentComponent { + private final FakeComponent fake; + public FakeDependentComponent(FakeComponent component) { + this.fake = component; + } + public boolean isTrue() { return fake.isTrue(); } + } +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/DefaultContainerTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/DefaultContainerTest.java new file mode 100644 index 0000000..1d108b0 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/DefaultContainerTest.java @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + + +import net.israfil.foundation.container.adapters.AbstractAutoWiringAdapter; +import net.israfil.foundation.container.adapters.IndependentAutoWiringAdapter; +import net.israfil.foundation.container.error.ComponentAlreadyRegisteredError; +import net.israfil.foundation.container.error.CouldNotCreateComponentError; +import net.israfil.foundation.container.error.UnsatisfiedDependencyError; + +import org.testng.Assert; +import org.testng.annotations.Test; + +public class DefaultContainerTest { + + + public DefaultContainer createContainer() { return new DefaultContainer(); } + public DefaultContainer createContainer(boolean tf) { return new DefaultContainer(tf); } + public DefaultContainer createContainer(Container c) { return new DefaultContainer(c); } + public DefaultContainer createContainer(Container c, boolean tf) { return new DefaultContainer(c,tf); } + public TestableContainer createTestableContainer() { return new TestableDefaultContainer(); } + + @Test + public void testAutoWiringContainer() { + TestableContainer container = createTestableContainer(); + container.registerType(A.class, A1.class); + container.registerType(B.class,B.adapter); + container.registerType(D.class,D.adapter); // out of order + container.registerType(C.class, new AbstractAutoWiringAdapter( + C.class, + new Object[] {A.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new C((A)param[0]); + } + }); + container.start(); + Assert.assertFalse(container.isStored(A.class)); + Assert.assertNotNull(container.getComponent(A.class)); + Assert.assertTrue(container.isStored(A.class)); + Assert.assertFalse(container.isStored(B.class)); + Assert.assertNotNull(container.getComponent(B.class)); + Assert.assertTrue(container.isStored(B.class)); + Assert.assertFalse(container.isStored(C.class)); + Assert.assertFalse(container.isStored(D.class)); + Assert.assertNotNull(container.getComponent(D.class)); + Assert.assertTrue(container.isStored(C.class)); + Assert.assertTrue(container.isStored(D.class)); + } + + @Test(expectedExceptions=UnsatisfiedDependencyError.class) + public void testMissingDependenciesFailingLate() { + AutoWiringAdaptableContainer container = createContainer(); + container.registerType(B.class,B.adapter); + container.start(); + Assert.assertTrue(container.isRunning()); + container.getComponent(B.class); + } + + @Test + public void testDelayedFailureWithMissingDependencies() { + AutoWiringAdaptableContainer container = createContainer(); + container.registerType(B.class,B.adapter); + container.start(); + } + + @Test(expectedExceptions=UnsatisfiedDependencyError.class) + public void testMissingDependenciesFailingEarly() { + AutoWiringAdaptableContainer container = createContainer(true); + container.registerType(B.class,B.adapter); + container.start(); + } + + @Test + public void testMultipleStartups() { + AutoWiringAdaptableContainer container = createContainer(true); + container.registerType(A.class,A1.class); + container.registerType(B.class,B.adapter); + container.start(); + Assert.assertTrue(container.isRunning()); + container.start(); // no error. + } + + @Test(expectedExceptions=RuntimeException.class) + public void testStartupWithUnstartedParent() { + AutoWiringAdaptableContainer parent = createContainer(); + AutoWiringAdaptableContainer child = createContainer(parent); + parent.registerType(A.class,A1.class); + child.registerType(B.class,B.adapter); + child.start(); // failed to start parent. + } + + @Test(expectedExceptions=ComponentAlreadyRegisteredError.class) + public void testDuplicateRegistration() { + AutoWiringAdaptableContainer container = createContainer(); + container.registerType(A.class,A1.class); + container.registerType(A.class,new AutoWiringAdapter() { + public Object create(Object[] parameters) throws IllegalAccessException, InstantiationException { + return null; + } + public Object[] dependencies() { return null; } + public Class getType() { return null; } + }); + } + + @Test(expectedExceptions=RuntimeException.class) + public void testRegistryFailureAfterStart() { + AutoWiringAdaptableContainer container = createContainer(); + container.registerType(A.class,A1.class); + container.registerType(B.class,B.adapter); + container.start(); + container.registerType(D.class,D.adapter); + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testIllegalAccessDuringConstruction() { + AutoWiringAdaptableContainer container = createContainer(true); + container.registerType(ComponentWithProtectedConstructor.class,ComponentWithProtectedConstructor.class); + container.start(); + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testInstantiationErrorDuringConstruction() { + AutoWiringAdaptableContainer container = createContainer(true); + container.registerType(A.class,A.class); + container.start(); + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testNullComponentCreation() { + AutoWiringAdaptableContainer container = createContainer(true); + container.registerType(A.class,new IndependentAutoWiringAdapter(A.class) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return null; + } + }); + container.start(); + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testArbitraryErrorInComponentCreation() { + AutoWiringAdaptableContainer container = createContainer(true); + container.registerType(A.class,new IndependentAutoWiringAdapter(A.class) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + throw new RuntimeException("Random error"); + } + }); + container.start(); + } + + + @Test + public void testAutowiringWithDependencyInParentContainerWithEarlyInstantiation() { + AutoWiringAdaptableContainer parent = createContainer(true); + AutoWiringAdaptableContainer child = createContainer(parent,true); + parent.registerType(A.class,A1.class); + child.registerType(B.class,B.adapter); + parent.start(); + child.start(); + Assert.assertNotNull(child.getComponent(B.class)); + } + + @Test + public void testAutowiringWithDependencyInParentContainerWithLateIntantiation() { + AutoWiringAdaptableContainer parent = createContainer(); + AutoWiringAdaptableContainer child = createContainer(parent); + parent.registerType(A.class,A1.class); + child.registerType(B.class,B.adapter); + parent.start(); + child.start(); + Assert.assertNotNull(child.getComponent(B.class)); + } + + public static abstract class A { + } + public static class A1 extends A { + } + public static class B { + private final A a; + public B(A a) { + if (a==null) throw new IllegalArgumentException("B cannot support null constructor arguments."); + this.a = a; + } + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + B.class, + new Object[] {A.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new B((A)param[0]); + } + }; + } + public static class C { + private final A a; + public C(A a) { + if (a==null) throw new IllegalArgumentException("C cannot support null constructor arguments."); + this.a = a; + } + } + public static class D { + private final C c; + public D(C c) { + if (c==null) throw new IllegalArgumentException("D cannot support null constructor arguments."); + this.c = c; + } + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + D.class, + new Object[] {C.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new D((C)param[0]); + } + }; + } + + public static class ComponentWithProtectedConstructor { + protected ComponentWithProtectedConstructor() {} + } + + public static interface TestableContainer extends AutoWiringAdaptableContainer { + public boolean isStored(Object key); + } + + public static class TestableDefaultContainer extends DefaultContainer implements TestableContainer { + public boolean isStored(Object key) { + return super.isStored(key); + } + } + + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LegacyContainerTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LegacyContainerTest.java new file mode 100644 index 0000000..4e69610 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LegacyContainerTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + + + +public class LegacyContainerTest extends DefaultContainerTest { + + public DefaultContainer createContainer() { return new DefaultAutoWiringAdaptableContainer(); } + public DefaultContainer createContainer(boolean tf) { return new DefaultAutoWiringAdaptableContainer(tf); } + public DefaultContainer createContainer(Container c) { return new DefaultAutoWiringAdaptableContainer(c); } + public DefaultContainer createContainer(Container c, boolean tf) { return new DefaultAutoWiringAdaptableContainer(c,tf); } + public TestableContainer createTestableContainer() { return new TestableLegacyContainer(); } + + public static class TestableLegacyContainer extends DefaultAutoWiringAdaptableContainer implements TestableContainer { + public boolean isStored(Object key) { + return super.isStored(key); + } + } + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LifecycleTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LifecycleTest.java new file mode 100644 index 0000000..920f17c --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LifecycleTest.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +import net.israfil.foundation.container.adapters.AbstractAutoWiringAdapter; +import net.israfil.foundation.container.adapters.IndependentAutoWiringAdapter; + +import org.testng.Assert; +import org.testng.annotations.Test; + + +public class LifecycleTest { + + @Test() + public void testAbstractStartable() { + Startable s = new AbstractStartable() {}; + Assert.assertFalse(s.isRunning()); + s.start(); + Assert.assertTrue(s.isRunning()); + } + + @Test() + public void testStartupOfSingleComponent() { + AutoWiringAdaptableContainer container = new DefaultContainer(); + final A1 a1 = new A1(); + container.registerType(A.class, new IndependentAutoWiringAdapter(A1.class) { + public Object create(Object[] args) { return a1; } + }); + Assert.assertFalse(a1.isRunning()); + container.start(); + container.getComponent(A.class); + Assert.assertTrue(a1.isRunning()); + } + + @Test() + public void testStartupOfStartedComponent() { + AutoWiringAdaptableContainer container = new DefaultContainer(); + final A2 a2 = new A2(); + a2.start(); + container.registerType(A.class, new IndependentAutoWiringAdapter(A.class) { + public Object create(Object[] args) { return a2; } + }); + container.start(); + container.getComponent(A.class); + Assert.assertEquals(a2.invoked,1); + } + + @Test() + public void testStartupOfMultipleComponents() { + AutoWiringAdaptableContainer container = new DefaultContainer(); + final A1 a1 = new A1(); + final C c = new C(a1); + container.registerType(A.class, new IndependentAutoWiringAdapter(A1.class) { + public Object create(Object[] args) { return a1; } + }); + container.registerType(B.class, B.adapter); + container.registerType(C.class, new AbstractAutoWiringAdapter( + C.class, + new Object[] {A.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return c; + } + }); + Assert.assertFalse(a1.isRunning()); + Assert.assertFalse(c.isRunning()); + container.start(); + container.getComponent(A.class); + Assert.assertFalse(c.isRunning()); + Assert.assertTrue(a1.isRunning()); + container.getComponent(C.class); + Assert.assertTrue(c.isRunning()); + Assert.assertTrue(a1.isRunning()); + } + + public static interface A { + } + + public static class A1 extends AbstractStartable implements A { + public void start() { super.start(); } + } + + public static class A2 extends AbstractStartable implements A { + public int invoked = 0; + public void start() { + super.start(); + invoked++; + } + } + + public static class B { + private final A a; + public B(A a) { + if (a==null) throw new IllegalArgumentException("B cannot support null constructor arguments."); + this.a = a; + } + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + B.class, + new Object[] {A.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new B((A)param[0]); + } + }; + } + public static class C extends AbstractStartable implements Startable{ + private final A a; + public C(A a) { + if (a==null) throw new IllegalArgumentException("C cannot support null constructor arguments."); + this.a = a; + } + public void start() { super.start(); } + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + C.class, + new Object[] {A.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new C((A)param[0]); + } + }; + } + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/MultiThreadedAutoWiringContainerTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/MultiThreadedAutoWiringContainerTest.java new file mode 100644 index 0000000..dabc119 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/MultiThreadedAutoWiringContainerTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +import net.israfil.foundation.container.adapters.AbstractAutoWiringAdapter; + +import org.testng.Assert; +import org.testng.annotations.Test; + + +public class MultiThreadedAutoWiringContainerTest { + + @Test() + public void testMissingDependenciesWiringEarly() { + AutoWiringAdaptableContainer container = new DefaultContainer(true); + container.registerType(A.class,A1.class); + container.registerType(B.class,B.adapter); + container.start(); + Assert.assertNotNull(container.getComponent(B.class)); + } + + public static abstract class A { + } + public static class A1 extends A { + } + public static class B { + private final A a; + public B(A a) { + if (a==null) throw new IllegalArgumentException("B cannot support null constructor arguments."); + this.a = a; + } + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + B.class, + new Object[] {A.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new B((A)param[0]); + } + }; + } + public static class C { + private final A a; + public C(A a) { + if (a==null) throw new IllegalArgumentException("C cannot support null constructor arguments."); + this.a = a; + } + } + public static class D { + private final C c; + public D(C c) { + if (c==null) throw new IllegalArgumentException("D cannot support null constructor arguments."); + this.c = c; + } + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + D.class, + new Object[] {C.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new D((C)param[0]); + } + }; + } + + public static class E { + protected E() {} + } + + public static class TestableAutoWiringAdaptableContainer extends DefaultContainer { + public boolean isStored(Object key) { + return super.isStored(key); + } + } +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/adapters/AdaptersTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/adapters/AdaptersTest.java new file mode 100644 index 0000000..62150ed --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/adapters/AdaptersTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.adapters; + +import net.israfil.foundation.container.AutoWiringAdapter; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * Tests + * @author cgruber + * + */ +public class AdaptersTest { + + @Test(expectedExceptions=IllegalArgumentException.class) + public void testIndependentAutoWiringAdapterWithNullType() { + new IndependentAutoWiringAdapter(null); + } + + @Test + public void testIndependentAutoWiringAdapterWithEmptyParamters() throws Exception { + AutoWiringAdapter awa = new IndependentAutoWiringAdapter(Fake.class); + Fake fake = (Fake)awa.create(new Object[0]); + Assert.assertNotNull(fake); + } + + @Test + public void testIndependentAutoWiringAdapterWithNullParamters() throws Exception { + AutoWiringAdapter awa = new IndependentAutoWiringAdapter(Fake.class); + Fake fake = (Fake)awa.create(null); + Assert.assertNotNull(fake); // should not reach this assert. + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void testIndependentAutoWiringAdapterWithNonEmptyParamters() throws Exception { + AutoWiringAdapter awa = new IndependentAutoWiringAdapter(Fake.class); + Object[] parameters = new Object[1]; + parameters[0] = "A"; + Fake fake = (Fake)awa.create(parameters); + Assert.assertNotNull(fake); // should not reach this assert. + } + + public static class Fake { + public Fake() {} + } +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredErrorTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredErrorTest.java new file mode 100644 index 0000000..fdaa7fa --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredErrorTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +import org.testng.annotations.Test; + + + +public class ComponentAlreadyRegisteredErrorTest { + + @Test(expectedExceptions=ComponentAlreadyRegisteredError.class) + public void testSimpleErrorThrow() throws Throwable { + Throwable error = new ComponentAlreadyRegisteredError(); + throw error; + } + + @Test(expectedExceptions=ComponentAlreadyRegisteredError.class) + public void testSimpleErrorThrowWithString() throws Throwable { + Throwable error = new ComponentAlreadyRegisteredError("test"); + throw error; + } + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CouldNotCreateComponentTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CouldNotCreateComponentTest.java new file mode 100644 index 0000000..87d43a4 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CouldNotCreateComponentTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +import org.testng.annotations.Test; + + + +public class CouldNotCreateComponentTest { + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testSimpleErrorThrow() throws Throwable { + Throwable error = new CouldNotCreateComponentError(); + throw error; + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testSimpleErrorThrowWithString() throws Throwable { + Throwable error = new CouldNotCreateComponentError("test"); + throw error; + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testSimpleErrorThrowWithThrowable() { + RuntimeException error = new CouldNotCreateComponentError( + new RuntimeException("test2") + ); + throw error; + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testSimpleErrorThrowWithStringAndThrowable() { + RuntimeException error = new CouldNotCreateComponentError( + "test", + new RuntimeException("test2") + ); + throw error; + } + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CyclicalDependencyErrorTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CyclicalDependencyErrorTest.java new file mode 100644 index 0000000..fc2fd93 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CyclicalDependencyErrorTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +import org.testng.annotations.Test; + + + +public class CyclicalDependencyErrorTest { + + @Test(expectedExceptions=CyclicalDependencyError.class) + public void testSimpleErrorThrow() throws Throwable { + Throwable error = new CyclicalDependencyError(); + throw error; + } + + @Test(expectedExceptions=CyclicalDependencyError.class) + public void testSimpleErrorThrowWithString() throws Throwable { + Throwable error = new CyclicalDependencyError("test"); + throw error; + } + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/UnsatisfiedDependencyErrorTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/UnsatisfiedDependencyErrorTest.java new file mode 100644 index 0000000..c668b5d --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/UnsatisfiedDependencyErrorTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +import org.testng.annotations.Test; + + + +public class UnsatisfiedDependencyErrorTest { + + @Test(expectedExceptions=UnsatisfiedDependencyError.class) + public void testSimpleErrorThrow() throws Throwable { + Throwable error = new UnsatisfiedDependencyError(); + throw error; + } + + @Test(expectedExceptions=UnsatisfiedDependencyError.class) + public void testSimpleErrorThrowWithString() throws Throwable { + Throwable error = new UnsatisfiedDependencyError("test"); + throw error; + } + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/CyclicalDependencyDetectionTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/CyclicalDependencyDetectionTest.java new file mode 100644 index 0000000..781ad92 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/CyclicalDependencyDetectionTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.util; + +import java.util.HashMap; +import java.util.Map; + +import net.israfil.foundation.container.AutoWiringAdapter; +import net.israfil.foundation.container.adapters.AbstractAutoWiringAdapter; +import net.israfil.foundation.container.adapters.IndependentAutoWiringAdapter; +import net.israfil.foundation.container.error.CyclicalDependencyError; + +import org.testng.annotations.Test; + + +public class CyclicalDependencyDetectionTest { + + @Test() + public void testCircularDependencyCheckWithNonCyclicGraph() { + // setup non-circular graph. + Map<Object,Object> registry = new HashMap<Object,Object>(); + registry.put("a", new FakeAutoWireAdapter(new Object[]{"b","e","d"})); + registry.put("b", new FakeAutoWireAdapter(new Object[]{"f","c"})); + registry.put("c", new IndependentAutoWiringAdapter(Object.class)); + registry.put("d", new FakeAutoWireAdapter(new Object[]{"e"})); + registry.put("e", new FakeAutoWireAdapter(new Object[]{"c"})); + registry.put("f", new IndependentAutoWiringAdapter(Object.class)); + NonDuplicateStack<Object> nds = new NonDuplicateStack<Object>(); + for (Object key : registry.keySet()) { + nds.push(key); + CyclicalReferenceDetectionUtil.detectCircularDependencies(registry, nds, (AutoWiringAdapter)registry.get(key)); + nds.pop(); + } + } + + @Test(expectedExceptions=CyclicalDependencyError.class) + public void testCircularDependencyCheckWithCyclicalGraph() { + // setup circular graph. + Map<Object,Object> registry = new HashMap<Object,Object>(); + registry.put("a", new FakeAutoWireAdapter(new Object[]{"b","e","d"})); + registry.put("b", new FakeAutoWireAdapter(new Object[]{"f","c"})); + registry.put("c", new FakeAutoWireAdapter(new Object[]{"d"})); + registry.put("d", new FakeAutoWireAdapter(new Object[]{"e"})); + registry.put("e", new FakeAutoWireAdapter(new Object[]{"c"})); + registry.put("f", new IndependentAutoWiringAdapter(Object.class)); + NonDuplicateStack<Object> nds = new NonDuplicateStack<Object>(); + for (Object key : registry.keySet()) { + nds.push(key); + CyclicalReferenceDetectionUtil.detectCircularDependencies(registry, nds, (AutoWiringAdapter)registry.get(key)); + nds.pop(); + } + } + + + public static class FakeAutoWireAdapter extends AbstractAutoWiringAdapter { + public FakeAutoWireAdapter(Object[] dependencies) { + super(Object.class, dependencies); + } + public Object create(Object[] parameters) throws IllegalAccessException, InstantiationException { + return null; + } + } +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/NonDuplicateStackTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/NonDuplicateStackTest.java new file mode 100644 index 0000000..a67afb0 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/NonDuplicateStackTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.util; + +import java.util.Stack; + +import org.testng.Assert; +import org.testng.annotations.Test; + + +public class NonDuplicateStackTest { + + @Test() + public void testBasicStackBehaviour() { + String s1 = "Hi."; + String s2 = "Hi"; + String s3 = "Bye."; + Stack<Object> stack = new NonDuplicateStack<Object>(); + stack.push(s1); + stack.push(s2); + stack.push(s3); + Assert.assertSame(stack.pop(),s3); + Assert.assertSame(stack.pop(),s2); + Assert.assertSame(stack.pop(),s1); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void testDuplicateHandlingByObjectRef() { + Object o1 = new Object(); + Object o2 = new Object(); + Object o3 = new Object(); + Stack<Object> stack = new NonDuplicateStack<Object>(); + stack.push(o1); + stack.push(o2); + stack.push(o3); + stack.push(o2); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void testDuplicateHandlingByValue() { + String s1 = "Hi."; + String s2 = "Hi"; + String s3 = "Bye."; + String s4 = "Hi"; + Stack<Object> stack = new NonDuplicateStack<Object>(); + stack.push(s1); + stack.push(s2); + stack.push(s3); + stack.push(s4); + } + +} |
