diff options
Diffstat (limited to 'israfil-foundation-container/src/main/java')
16 files changed, 1147 insertions, 0 deletions
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); + } + +} |
