You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2010/05/01 10:55:15 UTC

svn commit: r939948 - in /cayenne/main/trunk/framework: cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/ cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/ cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/ cayenne...

Author: aadamchik
Date: Sat May  1 08:55:15 2010
New Revision: 939948

URL: http://svn.apache.org/viewvc?rev=939948&view=rev
Log:
CAY-1424 DI: support for named service injection and flexible map/list binding

* javadocs
* reimplementing Map/List bindings as named bindings
* fixing scope handling logic. now scopes can be reset as many times as needed
  and default scope can be easily changed if we decide that SINGLETON is a better default.

Added:
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/Binding.java
      - copied, changed from r939928, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultRuntimeProperties.java
Modified:
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Binder.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Injector.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Key.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/ListBuilder.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/MapBuilder.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/ConstructorInjectingProvider.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultBinder.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultBindingBuilder.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultInjector.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultListBuilder.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultMapBuilder.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_ListConfiguration.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_MapConfiguration.java
    cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorInjectionTest.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultRuntimeProperties.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/server/CayenneServerModule.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactory.java

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Binder.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Binder.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Binder.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Binder.java Sat May  1 08:55:15 2010
@@ -41,18 +41,18 @@ public interface Binder {
     <T> BindingBuilder<T> bind(Key<T> key);
 
     /**
-     * Starts a binding of a map "configuration" that will be injected into an
-     * implementation class for the specified "interfaceType" parameter. Configurations
-     * can only be injected via a constructor. An object can take at most one
-     * configuration object via a constructor.
+     * Starts a binding of a java.util.Map<String, ?> distinguished by its binding name.
+     * Map binding should continue using returned MapBuilder. This is somewhat equivalent
+     * of using "bind(Map.class, bindingName)", however returned MapBuilder provides extra
+     * DI capabilities.
      */
-    <T> MapBuilder<T> bindMap(Class<T> interfaceType);
+    <T> MapBuilder<T> bindMap(String bindingName);
 
     /**
-     * Starts a binding of a list "configuration" that will be injected into an
-     * implementation class for the specified "interfaceType" parameter. Configurations
-     * can only be injected via a constructor. An object can take at most one
-     * configuration object via a constructor.
+     * Starts a binding of a java.util.List<?> distinguished by its binding name. List
+     * binding should continue using returned ListBuilder. This is somewhat equivalent of
+     * using "bind(List.class, bindingName)", however returned ListBuilder provides extra
+     * DI capabilities.
      */
-    <T> ListBuilder<T> bindList(Class<T> interfaceType);
+    <T> ListBuilder<T> bindList(String bindingName);
 }

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Injector.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Injector.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Injector.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Injector.java Sat May  1 08:55:15 2010
@@ -18,9 +18,6 @@
  ****************************************************************/
 package org.apache.cayenne.di;
 
-import java.util.List;
-import java.util.Map;
-
 import org.apache.cayenne.ConfigurationException;
 
 /**
@@ -48,10 +45,6 @@ public interface Injector {
 
     <T> Provider<T> getProvider(Key<T> key) throws ConfigurationException;
 
-    <T> Map<String, ?> getMapConfiguration(Class<T> type) throws ConfigurationException;
-
-    <T> List<?> getListConfiguration(Class<T> type) throws ConfigurationException;
-
     /**
      * Performs field injection on a given object, ignoring constructor injection. Since
      * Cayenne DI injector returns fully injected objects, this method is rarely used

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Key.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Key.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Key.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/Key.java Sat May  1 08:55:15 2010
@@ -30,10 +30,18 @@ public class Key<T> {
     protected String typeName;
     protected String bindingName;
 
+    /**
+     * Creates a key for a nameless binding of a given type.
+     */
     public static <T> Key<T> get(Class<T> type) {
         return new Key<T>(type, null);
     }
 
+    /**
+     * Creates a key for a named binding of a given type. 'bindingName' that is an empty
+     * String is treated the same way as a null 'bindingName'. In both cases a nameless
+     * binding key is created.
+     */
     public static <T> Key<T> get(Class<T> type, String bindingName) {
         return new Key<T>(type, bindingName);
     }
@@ -59,6 +67,14 @@ public class Key<T> {
         return type;
     }
 
+    /**
+     * Returns an optional name of the binding used to distinguish multiple bindings of
+     * the same object type.
+     */
+    public String getBindingName() {
+        return bindingName;
+    }
+
     @Override
     public boolean equals(Object object) {
 

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/ListBuilder.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/ListBuilder.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/ListBuilder.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/ListBuilder.java Sat May  1 08:55:15 2010
@@ -23,12 +23,14 @@ import org.apache.cayenne.ConfigurationE
 /**
  * A binding builder for list configurations.
  * 
- * @param <T> A type of the service for which the configuration is created.
+ * @param <T> A type of list values.
  * @since 3.1
  */
 public interface ListBuilder<T> {
 
-    <E> ListBuilder<T> add(Class<? extends E> interfaceType) throws ConfigurationException;
+    ListBuilder<T> add(Class<? extends T> interfaceType) throws ConfigurationException;
 
-    <E> ListBuilder<T> add(E value) throws ConfigurationException;
+    ListBuilder<T> add(T value) throws ConfigurationException;
+
+    void in(Scope scope);
 }

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/MapBuilder.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/MapBuilder.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/MapBuilder.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/MapBuilder.java Sat May  1 08:55:15 2010
@@ -21,15 +21,18 @@ package org.apache.cayenne.di;
 import org.apache.cayenne.ConfigurationException;
 
 /**
- * A binding builder for map configurations.
+ * A binding builder for map configurations. Creates a parameterized map of type <String,
+ * T>.
  * 
- * @param <T> A type of the service for which the configuration is created.
+ * @param <T> A type of the map values.
  * @since 3.1
  */
 public interface MapBuilder<T> {
 
-    <E> MapBuilder<T> put(String key, Class<? extends E> interfaceType)
+    MapBuilder<T> put(String key, Class<? extends T> interfaceType)
             throws ConfigurationException;
 
-    <E> MapBuilder<T> put(String key, E value) throws ConfigurationException;
+    MapBuilder<T> put(String key, T value) throws ConfigurationException;
+    
+    void in(Scope scope);
 }

Copied: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/Binding.java (from r939928, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultRuntimeProperties.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/Binding.java?p2=cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/Binding.java&p1=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultRuntimeProperties.java&r1=939928&r2=939948&rev=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultRuntimeProperties.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/Binding.java Sat May  1 08:55:15 2010
@@ -16,35 +16,41 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
-package org.apache.cayenne.configuration;
+package org.apache.cayenne.di.spi;
 
-import java.util.Map;
-
-import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.di.Scope;
+import org.apache.cayenne.di.Scopes;
 
 /**
- * An implementation of {@link RuntimeProperties} that returns properties that were
- * injected via a map in constructor. Each property can be overridden via -D command line
- * option.
+ * A binding encapsulates DI provider scoping settings and allows to change them as many
+ * times as needed.
  * 
  * @since 3.1
  */
-public class DefaultRuntimeProperties implements RuntimeProperties {
+class Binding<T> {
 
-    protected Map<String, String> properties;
+    private Provider<T> unscoped;
+    private Provider<T> scoped;
 
-    public DefaultRuntimeProperties(@Inject Map<String, String> properties) {
-        this.properties = properties;
+    Binding(Provider<T> provider) {
+        this.unscoped = provider;
+        this.scoped = provider;
     }
 
-    public String get(String key) {
+    void changeScope(Scope scope) {
+        if (scope == null) {
+            scope = Scopes.NO_SCOPE;
+        }
 
-        String property = System.getProperty(key);
+        scoped = scope.scope(unscoped);
+    }
 
-        if (property != null) {
-            return property;
-        }
+    Provider<T> getUnscoped() {
+        return unscoped;
+    }
 
-        return properties.get(key);
+    Provider<T> getScoped() {
+        return scoped;
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/ConstructorInjectingProvider.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/ConstructorInjectingProvider.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/ConstructorInjectingProvider.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/ConstructorInjectingProvider.java Sat May  1 08:55:15 2010
@@ -21,8 +21,6 @@ package org.apache.cayenne.di.spi;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Type;
-import java.util.List;
-import java.util.Map;
 
 import org.apache.cayenne.ConfigurationException;
 import org.apache.cayenne.di.Inject;
@@ -34,13 +32,12 @@ import org.apache.cayenne.di.Provider;
  */
 class ConstructorInjectingProvider<T> implements Provider<T> {
 
-    private Class<T> interfaceType;
     private Constructor<? extends T> constructor;
     private DefaultInjector injector;
     private String[] bindingNames;
 
-    ConstructorInjectingProvider(Class<T> interfaceType,
-            Class<? extends T> implementation, DefaultInjector injector) {
+    ConstructorInjectingProvider(Class<? extends T> implementation,
+            DefaultInjector injector) {
 
         initConstructor(implementation);
 
@@ -52,7 +49,6 @@ class ConstructorInjectingProvider<T> im
 
         this.constructor.setAccessible(true);
         this.injector = injector;
-        this.interfaceType = interfaceType;
     }
 
     private void initConstructor(Class<? extends T> implementation) {
@@ -135,19 +131,7 @@ class ConstructorInjectingProvider<T> im
 
             Class<?> parameter = constructorParameters[i];
 
-            // parameter must be declared as "java.util.Map". Use of specific map
-            // implementations in the declaration will make the injection much more
-            // complicated
-            if (Map.class.equals(parameter)) {
-                args[i] = injector.getMapConfiguration(interfaceType);
-            }
-            // parameter must be declared as "java.util.List". Use of specific list
-            // implementations in the declaration will make the injection much more
-            // complicated
-            else if (List.class.equals(parameter)) {
-                args[i] = injector.getListConfiguration(interfaceType);
-            }
-            else if (Provider.class.equals(parameter)) {
+            if (Provider.class.equals(parameter)) {
 
                 Class<?> objectClass = DIUtil.parameterClass(genericTypes[i]);
 

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultBinder.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultBinder.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultBinder.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultBinder.java Sat May  1 08:55:15 2010
@@ -18,6 +18,9 @@
  ****************************************************************/
 package org.apache.cayenne.di.spi;
 
+import java.util.List;
+import java.util.Map;
+
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.BindingBuilder;
 import org.apache.cayenne.di.Key;
@@ -43,12 +46,18 @@ class DefaultBinder implements Binder {
         return new DefaultBindingBuilder<T>(key, injector);
     }
 
-    public <T> ListBuilder<T> bindList(Class<T> implementationType) {
-        return new DefaultListBuilder<T>(implementationType, injector);
+    public <T> ListBuilder<T> bindList(String bindingName) {
+        Class<?> listClass = List.class;
+        return new DefaultListBuilder<T>(
+                Key.get((Class<List<?>>) listClass, bindingName),
+                injector);
     }
 
-    public <T> MapBuilder<T> bindMap(Class<T> implementationType) {
-        return new DefaultMapBuilder<T>(implementationType, injector);
+    public <T> MapBuilder<T> bindMap(String bindingName) {
+        Class<?> mapClass = Map.class;
+        return new DefaultMapBuilder<T>(Key.get(
+                (Class<Map<String, ?>>) mapClass,
+                bindingName), injector);
     }
 
 }

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultBindingBuilder.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultBindingBuilder.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultBindingBuilder.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultBindingBuilder.java Sat May  1 08:55:15 2010
@@ -23,16 +23,14 @@ import org.apache.cayenne.di.BindingBuil
 import org.apache.cayenne.di.Key;
 import org.apache.cayenne.di.Provider;
 import org.apache.cayenne.di.Scope;
-import org.apache.cayenne.di.Scopes;
 
 /**
  * @since 3.1
  */
 class DefaultBindingBuilder<T> implements BindingBuilder<T> {
 
-    private DefaultInjector injector;
-    private Scope scope;
-    private Key<T> bindingKey;
+    protected DefaultInjector injector;
+    protected Key<T> bindingKey;
 
     DefaultBindingBuilder(Key<T> bindingKey, DefaultInjector injector) {
         this.injector = injector;
@@ -43,14 +41,15 @@ class DefaultBindingBuilder<T> implement
             throws ConfigurationException {
 
         Provider<T> provider0 = new ConstructorInjectingProvider<T>(
-                bindingKey.getType(),
                 implementation,
                 injector);
         Provider<T> provider1 = new FieldInjectingProvider<T>(
                 provider0,
                 injector,
                 bindingKey);
-        return bindInScope(provider1);
+
+        injector.putBinding(bindingKey, provider1);
+        return this;
     }
 
     public BindingBuilder<T> toInstance(T instance) throws ConfigurationException {
@@ -59,7 +58,8 @@ class DefaultBindingBuilder<T> implement
                 provider0,
                 injector,
                 bindingKey);
-        return bindInScope(provider1);
+        injector.putBinding(bindingKey, provider1);
+        return this;
     };
 
     public BindingBuilder<T> toProvider(
@@ -78,7 +78,8 @@ class DefaultBindingBuilder<T> implement
                 injector,
                 bindingKey);
 
-        return bindInScope(provider3);
+        injector.putBinding(bindingKey, provider3);
+        return this;
     }
 
     public BindingBuilder<T> toProviderInstance(Provider<? extends T> provider) {
@@ -96,33 +97,11 @@ class DefaultBindingBuilder<T> implement
                 injector,
                 bindingKey);
 
-        return bindInScope(provider3);
+        injector.putBinding(bindingKey, provider3);
+        return this;
     }
 
     public void in(Scope scope) {
-
-        if (this.scope != scope) {
-
-            if (this.scope != null) {
-                throw new IllegalStateException(
-                        "Can't change binding scope. It is already set to " + this.scope);
-            }
-
-            this.scope = scope;
-
-            if (bindingKey != null) {
-                Provider<?> provider = injector.getBindings().get(bindingKey);
-                injector.getBindings().put(bindingKey, scope.scope(provider));
-            }
-        }
-    }
-
-    private BindingBuilder<T> bindInScope(Provider<T> provider) {
-
-        Scope scope = this.scope != null ? this.scope : Scopes.NO_SCOPE;
-
-        // TODO: andrus 11/15/2009 - report overriding existing binding??
-        injector.getBindings().put(bindingKey, scope.scope(provider));
-        return this;
+        injector.changeBindingScope(bindingKey, scope);
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultInjector.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultInjector.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultInjector.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultInjector.java Sat May  1 08:55:15 2010
@@ -19,7 +19,6 @@
 package org.apache.cayenne.di.spi;
 
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.cayenne.ConfigurationException;
@@ -27,6 +26,8 @@ import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.di.Key;
 import org.apache.cayenne.di.Module;
 import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.di.Scope;
+import org.apache.cayenne.di.Scopes;
 
 /**
  * A default Cayenne implementations of a DI injector.
@@ -35,16 +36,12 @@ import org.apache.cayenne.di.Provider;
  */
 public class DefaultInjector implements Injector {
 
-    private Map<Key<?>, Provider<?>> bindings;
-    private Map<Key<?>, MapProvider> mapConfigurations;
-    private Map<Key<?>, ListProvider> listConfigurations;
+    private Map<Key<?>, Binding<?>> bindings;
     private InjectionStack injectionStack;
 
     public DefaultInjector(Module... modules) throws ConfigurationException {
 
-        this.bindings = new HashMap<Key<?>, Provider<?>>();
-        this.mapConfigurations = new HashMap<Key<?>, MapProvider>();
-        this.listConfigurations = new HashMap<Key<?>, ListProvider>();
+        this.bindings = new HashMap<Key<?>, Binding<?>>();
         this.injectionStack = new InjectionStack();
 
         DefaultBinder binder = new DefaultBinder(this);
@@ -65,60 +62,40 @@ public class DefaultInjector implements 
         return injectionStack;
     }
 
-    Map<Key<?>, Provider<?>> getBindings() {
-        return bindings;
-    }
-
-    Map<Key<?>, MapProvider> getMapConfigurations() {
-        return mapConfigurations;
-    }
+    <T> Binding<T> getBinding(Key<T> key) throws ConfigurationException {
 
-    Map<Key<?>, ListProvider> getListConfigurations() {
-        return listConfigurations;
-    }
+        if (key == null) {
+            throw new NullPointerException("Null key");
+        }
 
-    public <T> T getInstance(Class<T> type) throws ConfigurationException {
-        return getProvider(type).get();
+        // may return null - this is intentionally allowed in this non-public method
+        return (Binding<T>) bindings.get(key);
     }
 
-    public <T> T getInstance(Key<T> key) throws ConfigurationException {
-        return getProvider(key).get();
+    <T> void putBinding(Key<T> bindingKey, Provider<T> provider) {
+        // TODO: andrus 11/15/2009 - report overriding existing binding??
+        bindings.put(bindingKey, new Binding<T>(provider));
     }
 
-    public <T> List<?> getListConfiguration(Class<T> type) {
-        if (type == null) {
-            throw new NullPointerException("Null type");
+    <T> void changeBindingScope(Key<T> bindingKey, Scope scope) {
+        if (scope == null) {
+            scope = Scopes.NO_SCOPE;
         }
 
-        ListProvider provider = listConfigurations.get(Key.get(type));
-
-        if (provider == null) {
-            throw new ConfigurationException(
-                    "Type '%s' has no bound list configuration in the DI container."
-                            + " Injection stack: %s",
-                    type.getName(),
-                    injectionStack);
+        Binding<?> binding = bindings.get(bindingKey);
+        if (binding == null) {
+            throw new ConfigurationException("No existing binding for key " + bindingKey);
         }
 
-        return provider.get();
+        binding.changeScope(scope);
     }
 
-    public <T> Map<String, ?> getMapConfiguration(Class<T> type) {
-        if (type == null) {
-            throw new NullPointerException("Null type");
-        }
-
-        MapProvider provider = mapConfigurations.get(Key.get(type));
-
-        if (provider == null) {
-            throw new ConfigurationException(
-                    "Type '%s' has no bound map configuration in the DI container."
-                            + " Injection stack: %s",
-                    type.getName(),
-                    injectionStack);
-        }
+    public <T> T getInstance(Class<T> type) throws ConfigurationException {
+        return getProvider(type).get();
+    }
 
-        return provider.get();
+    public <T> T getInstance(Key<T> key) throws ConfigurationException {
+        return getProvider(key).get();
     }
 
     public <T> Provider<T> getProvider(Class<T> type) throws ConfigurationException {
@@ -131,15 +108,15 @@ public class DefaultInjector implements 
             throw new NullPointerException("Null key");
         }
 
-        Provider<T> provider = (Provider<T>) bindings.get(key);
+        Binding<T> binding = (Binding<T>) bindings.get(key);
 
-        if (provider == null) {
+        if (binding == null) {
             throw new ConfigurationException(
                     "DI container has no binding for key %s",
                     key);
         }
 
-        return provider;
+        return binding.getScoped();
     }
 
     public void injectMembers(Object object) {
@@ -150,5 +127,4 @@ public class DefaultInjector implements 
                 Key.get(object.getClass()));
         provider1.get();
     }
-
 }

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultListBuilder.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultListBuilder.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultListBuilder.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultListBuilder.java Sat May  1 08:55:15 2010
@@ -18,50 +18,62 @@
  ****************************************************************/
 package org.apache.cayenne.di.spi;
 
+import java.util.List;
+
 import org.apache.cayenne.ConfigurationException;
 import org.apache.cayenne.di.Key;
 import org.apache.cayenne.di.ListBuilder;
+import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.di.Scope;
 
 /**
  * @since 3.1
  */
 class DefaultListBuilder<T> implements ListBuilder<T> {
 
-    private DefaultInjector injector;
-    private Key<T> implementationTypeKey;
+    protected DefaultInjector injector;
+    protected Key<List<?>> bindingKey;
 
-    DefaultListBuilder(Class<T> implementationType, DefaultInjector injector) {
+    DefaultListBuilder(Key<List<?>> bindingKey, DefaultInjector injector) {
         this.injector = injector;
-        this.implementationTypeKey = Key.get(implementationType);
+        this.bindingKey = bindingKey;
     }
 
-    public <E> ListBuilder<T> add(Class<? extends E> interfaceType)
+    public ListBuilder<T> add(Class<? extends T> interfaceType)
             throws ConfigurationException {
+        getListProvider().add(injector.getProvider(interfaceType));
+        return this;
+    }
 
-        ListProvider listProvider = injector.getListConfigurations().get(
-                implementationTypeKey);
-        if (listProvider == null) {
-            listProvider = new ListProvider();
-            injector.getListConfigurations().put(implementationTypeKey, listProvider);
-        }
+    public ListBuilder<T> add(T value) throws ConfigurationException {
 
-        listProvider.add(injector.getProvider(interfaceType));
+        Provider<T> provider0 = new InstanceProvider<T>(value);
+        Provider<T> provider1 = new FieldInjectingProvider<T>(
+                provider0,
+                injector,
+                bindingKey);
+
+        getListProvider().add(provider1);
         return this;
     }
 
-    public <E> ListBuilder<T> add(E value) throws ConfigurationException {
+    private ListProvider getListProvider() {
 
-        InstanceProvider<E> provider = new InstanceProvider<E>(value);
+        ListProvider provider = null;
 
-        ListProvider listProvider = injector.getListConfigurations().get(
-                implementationTypeKey);
-        if (listProvider == null) {
-            listProvider = new ListProvider();
-            injector.getListConfigurations().put(implementationTypeKey, listProvider);
+        Binding<List<?>> binding = injector.getBinding(bindingKey);
+        if (binding == null) {
+            provider = new ListProvider();
+            injector.putBinding(bindingKey, provider);
+        }
+        else {
+            provider = (ListProvider) binding.getUnscoped();
         }
 
-        listProvider.add(provider);
-        return this;
+        return provider;
     }
 
+    public void in(Scope scope) {
+        injector.changeBindingScope(bindingKey, scope);
+    }
 }

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultMapBuilder.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultMapBuilder.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultMapBuilder.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultMapBuilder.java Sat May  1 08:55:15 2010
@@ -18,9 +18,13 @@
  ****************************************************************/
 package org.apache.cayenne.di.spi;
 
+import java.util.Map;
+
 import org.apache.cayenne.ConfigurationException;
 import org.apache.cayenne.di.Key;
 import org.apache.cayenne.di.MapBuilder;
+import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.di.Scope;
 
 /**
  * @since 3.1
@@ -28,41 +32,50 @@ import org.apache.cayenne.di.MapBuilder;
 class DefaultMapBuilder<T> implements MapBuilder<T> {
 
     private DefaultInjector injector;
-    private Key<T> implementationTypeKey;
+    private Key<Map<String, ?>> bindingKey;
 
-    DefaultMapBuilder(Class<T> implementationType, DefaultInjector injector) {
+    DefaultMapBuilder(Key<Map<String, ?>> bindingKey, DefaultInjector injector) {
         this.injector = injector;
-        implementationTypeKey = Key.get(implementationType);
+        this.bindingKey = bindingKey;
     }
 
-    public <E> MapBuilder<T> put(String key, Class<? extends E> interfaceType)
+    public MapBuilder<T> put(String key, Class<? extends T> interfaceType)
             throws ConfigurationException {
 
-        MapProvider mapProvider = injector.getMapConfigurations().get(
-                implementationTypeKey);
-        if (mapProvider == null) {
-            mapProvider = new MapProvider();
-            injector.getMapConfigurations().put(implementationTypeKey, mapProvider);
-        }
-
         // TODO: andrus 11/15/2009 - report overriding the key??
-        mapProvider.put(key, injector.getProvider(interfaceType));
+        getMapProvider().put(key, injector.getProvider(interfaceType));
         return this;
     }
 
-    public <E> MapBuilder<T> put(String key, E value) throws ConfigurationException {
+    public MapBuilder<T> put(String key, T value) throws ConfigurationException {
 
-        InstanceProvider<E> provider = new InstanceProvider<E>(value);
-
-        MapProvider mapProvider = injector.getMapConfigurations().get(
-                implementationTypeKey);
-        if (mapProvider == null) {
-            mapProvider = new MapProvider();
-            injector.getMapConfigurations().put(implementationTypeKey, mapProvider);
-        }
+        Provider<T> provider0 = new InstanceProvider<T>(value);
+        Provider<T> provider1 = new FieldInjectingProvider<T>(
+                provider0,
+                injector,
+                bindingKey);
 
         // TODO: andrus 11/15/2009 - report overriding the key??
-        mapProvider.put(key, provider);
+        getMapProvider().put(key, provider1);
         return this;
     }
+
+    private MapProvider getMapProvider() {
+        MapProvider provider = null;
+
+        Binding<Map<String, ?>> binding = injector.getBinding(bindingKey);
+        if (binding == null) {
+            provider = new MapProvider();
+            injector.putBinding(bindingKey, provider);
+        }
+        else {
+            provider = (MapProvider) binding.getUnscoped();
+        }
+
+        return provider;
+    }
+
+    public void in(Scope scope) {
+        injector.changeBindingScope(bindingKey, scope);
+    }
 }

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_ListConfiguration.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_ListConfiguration.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_ListConfiguration.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_ListConfiguration.java Sat May  1 08:55:15 2010
@@ -26,7 +26,7 @@ public class MockImplementation1_ListCon
 
     private List<Object> configuration;
 
-    public MockImplementation1_ListConfiguration(@Inject List<Object> configuration) {
+    public MockImplementation1_ListConfiguration(@Inject("xyz") List<Object> configuration) {
         this.configuration = configuration;
     }
 

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_MapConfiguration.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_MapConfiguration.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_MapConfiguration.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_MapConfiguration.java Sat May  1 08:55:15 2010
@@ -29,7 +29,8 @@ public class MockImplementation1_MapConf
 
     private Map<String, Object> configuration;
 
-    public MockImplementation1_MapConfiguration(@Inject Map<String, Object> configuration) {
+    public MockImplementation1_MapConfiguration(
+            @Inject("xyz") Map<String, Object> configuration) {
         this.configuration = configuration;
     }
 

Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorInjectionTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorInjectionTest.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorInjectionTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorInjectionTest.java Sat May  1 08:55:15 2010
@@ -163,11 +163,9 @@ public class DefaultInjectorInjectionTes
                 binder.bind(MockInterface1.class).to(
                         MockImplementation1_MapConfiguration.class);
 
-                binder
-                        .bindMap(MockInterface1.class)
-                        .put("x", "xvalue")
-                        .put("y", "yvalue")
-                        .put("x", "xvalue1");
+                binder.bindMap("xyz").put("x", "xvalue").put("y", "yvalue").put(
+                        "x",
+                        "xvalue1");
             }
         };
 
@@ -185,7 +183,7 @@ public class DefaultInjectorInjectionTes
                 binder.bind(MockInterface1.class).to(
                         MockImplementation1_ListConfiguration.class);
 
-                binder.bindList(MockInterface1.class).add("xvalue").add("yvalue");
+                binder.bindList("xyz").add("xvalue").add("yvalue");
             }
         };
 
@@ -205,8 +203,7 @@ public class DefaultInjectorInjectionTes
                 binder.bind(MockInterface1.class).to(
                         MockImplementation1_ListConfiguration.class);
 
-                binder.bindList(MockInterface1.class).add(MockInterface5.class).add(
-                        "yvalue");
+                binder.bindList("xyz").add(MockInterface5.class).add("yvalue");
             }
         };
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultRuntimeProperties.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultRuntimeProperties.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultRuntimeProperties.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultRuntimeProperties.java Sat May  1 08:55:15 2010
@@ -31,9 +31,11 @@ import org.apache.cayenne.di.Inject;
  */
 public class DefaultRuntimeProperties implements RuntimeProperties {
 
+    public static final String PROPERTIES_MAP = "org.apache.cayenne.configuration.DefaultRuntimeProperties.properties";
+
     protected Map<String, String> properties;
 
-    public DefaultRuntimeProperties(@Inject Map<String, String> properties) {
+    public DefaultRuntimeProperties(@Inject(PROPERTIES_MAP) Map<String, String> properties) {
         this.properties = properties;
     }
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/server/CayenneServerModule.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/server/CayenneServerModule.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/server/CayenneServerModule.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/server/CayenneServerModule.java Sat May  1 08:55:15 2010
@@ -72,14 +72,14 @@ public class CayenneServerModule impleme
     public void configure(Binder binder) {
 
         // configure global stack properties
-        binder.bindMap(RuntimeProperties.class).put(
+        binder.bindMap(DefaultRuntimeProperties.PROPERTIES_MAP).put(
                 RuntimeProperties.CONFIGURATION_LOCATION,
                 configurationLocation);
 
         // configure known DbAdapter detectors in reverse order of popularity. Users can
         // add their own to install custom adapters automatically
         binder
-                .bindList(DbAdapterFactory.class)
+                .bindList(DefaultDbAdapterFactory.DETECTORS_LIST)
                 .add(new OpenBaseSniffer())
                 .add(new FrontBaseSniffer())
                 .add(new IngresSniffer())

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactory.java?rev=939948&r1=939947&r2=939948&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactory.java Sat May  1 08:55:15 2010
@@ -43,11 +43,14 @@ import org.apache.cayenne.di.Provider;
  */
 public class DefaultDbAdapterFactory implements DbAdapterFactory {
 
+    public static final String DETECTORS_LIST = "org.apache.cayenne.configuration.server.DefaultDbAdapterFactory.detectors";
+
     @Inject
     protected AdhocObjectFactory objectFactory;
     protected List<DbAdapterDetector> detectors;
 
-    public DefaultDbAdapterFactory(@Inject List<DbAdapterDetector> detectors) {
+    public DefaultDbAdapterFactory(
+            @Inject(DETECTORS_LIST) List<DbAdapterDetector> detectors) {
         if (detectors == null) {
             throw new NullPointerException("Null detectors list");
         }