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/06/15 14:32:12 UTC
svn commit: r954852 - 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: Tue Jun 15 12:32:11 2010
New Revision: 954852
URL: http://svn.apache.org/viewvc?rev=954852&view=rev
Log:
Fixing DI scope event handling
* a generic scope implementation that can be used for any user-managed scope
* unregistering scoped objects at the end of the scope
Added:
cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/BeforeScopeEnd.java
- copied, changed from r954823, cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/OnScopeEnd.java
cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/AfterScopeEnd.java
- copied, changed from r954823, cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/SingletonScope.java
cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultScope.java
cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultScopeProvider.java
- copied, changed from r954823, cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/SingletonProvider.java
Removed:
cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/OnScopeEnd.java
cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/EventfulScope.java
cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/SingletonProvider.java
cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/SingletonScope.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/UnitTestScope.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/UnitTestScopedProvider.java
Modified:
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/main/java/org/apache/cayenne/di/spi/FieldInjectingProvider.java
cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/ScopeEventBinding.java
cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_EventAnnotations.java
cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_EventAnnotationsBase.java
cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorScopeTest.java
cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorTest.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/event/DefaultEventManager.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/DICaseSelfTest.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/DefaultUnitTestLifecycleManager.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/CachingServerRuntimeFactory.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/ServerCase.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseLifecycleManager.java
Copied: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/BeforeScopeEnd.java (from r954823, cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/OnScopeEnd.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/BeforeScopeEnd.java?p2=cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/BeforeScopeEnd.java&p1=cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/OnScopeEnd.java&r1=954823&r2=954852&rev=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/OnScopeEnd.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/BeforeScopeEnd.java Tue Jun 15 12:32:11 2010
@@ -36,6 +36,6 @@ import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
-public @interface OnScopeEnd {
+public @interface BeforeScopeEnd {
}
Copied: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/AfterScopeEnd.java (from r954823, cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/SingletonScope.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/AfterScopeEnd.java?p2=cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/AfterScopeEnd.java&p1=cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/SingletonScope.java&r1=954823&r2=954852&rev=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/SingletonScope.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/AfterScopeEnd.java Tue Jun 15 12:32:11 2010
@@ -18,20 +18,22 @@
****************************************************************/
package org.apache.cayenne.di.spi;
-import org.apache.cayenne.di.OnScopeEnd;
-import org.apache.cayenne.di.Provider;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
/**
+ * A non-public event annotation used by scope object providers to unregister objects
+ * created within a scope. Registry objects within a given scope will never be able to
+ * receive this event, so never annotate custom objects with this.
+ *
* @since 3.1
*/
-class SingletonScope extends EventfulScope {
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@interface AfterScopeEnd {
- SingletonScope() {
- addEventAnnotation(OnScopeEnd.class);
- }
-
- @Override
- public <T> Provider<T> scope(Provider<T> unscoped) {
- return new SingletonProvider<T>(this, unscoped);
- }
}
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=954852&r1=954851&r2=954852&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 Tue Jun 15 12:32:11 2010
@@ -43,10 +43,7 @@ class DefaultBindingBuilder<T> implement
Provider<T> provider0 = new ConstructorInjectingProvider<T>(
implementation,
injector);
- Provider<T> provider1 = new FieldInjectingProvider<T>(
- provider0,
- injector,
- bindingKey);
+ Provider<T> provider1 = new FieldInjectingProvider<T>(provider0, injector);
injector.putBinding(bindingKey, provider1);
return this;
@@ -54,10 +51,7 @@ class DefaultBindingBuilder<T> implement
public BindingBuilder<T> toInstance(T instance) throws ConfigurationException {
Provider<T> provider0 = new InstanceProvider<T>(instance);
- Provider<T> provider1 = new FieldInjectingProvider<T>(
- provider0,
- injector,
- bindingKey);
+ Provider<T> provider1 = new FieldInjectingProvider<T>(provider0, injector);
injector.putBinding(bindingKey, provider1);
return this;
};
@@ -70,14 +64,10 @@ class DefaultBindingBuilder<T> implement
injector);
Provider<Provider<? extends T>> provider1 = new FieldInjectingProvider<Provider<? extends T>>(
provider0,
- injector,
- bindingKey);
+ injector);
Provider<T> provider2 = new CustomProvidersProvider<T>(provider1);
- Provider<T> provider3 = new FieldInjectingProvider<T>(
- provider2,
- injector,
- bindingKey);
+ Provider<T> provider3 = new FieldInjectingProvider<T>(provider2, injector);
injector.putBinding(bindingKey, provider3);
return this;
@@ -89,14 +79,10 @@ class DefaultBindingBuilder<T> implement
provider);
Provider<Provider<? extends T>> provider1 = new FieldInjectingProvider<Provider<? extends T>>(
provider0,
- injector,
- bindingKey);
+ injector);
Provider<T> provider2 = new CustomProvidersProvider<T>(provider1);
- Provider<T> provider3 = new FieldInjectingProvider<T>(
- provider2,
- injector,
- bindingKey);
+ Provider<T> provider3 = new FieldInjectingProvider<T>(provider2, injector);
injector.putBinding(bindingKey, provider3);
return this;
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=954852&r1=954851&r2=954852&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 Tue Jun 15 12:32:11 2010
@@ -25,7 +25,6 @@ import org.apache.cayenne.ConfigurationE
import org.apache.cayenne.di.Injector;
import org.apache.cayenne.di.Key;
import org.apache.cayenne.di.Module;
-import org.apache.cayenne.di.OnScopeEnd;
import org.apache.cayenne.di.Provider;
import org.apache.cayenne.di.Scope;
@@ -36,7 +35,7 @@ import org.apache.cayenne.di.Scope;
*/
public class DefaultInjector implements Injector {
- private SingletonScope singletonScope;
+ private DefaultScope singletonScope;
private Scope noScope;
private Map<Key<?>, Binding<?>> bindings;
@@ -45,7 +44,7 @@ public class DefaultInjector implements
public DefaultInjector(Module... modules) throws ConfigurationException {
- this.singletonScope = new SingletonScope();
+ this.singletonScope = new DefaultScope();
this.noScope = NoScope.SINGLETON;
// this is intentionally hardcoded and is not configurable
@@ -131,18 +130,15 @@ public class DefaultInjector implements
public void injectMembers(Object object) {
Provider<Object> provider0 = new InstanceProvider<Object>(object);
- Provider<Object> provider1 = new FieldInjectingProvider<Object>(
- provider0,
- this,
- Key.get(object.getClass()));
+ Provider<Object> provider1 = new FieldInjectingProvider<Object>(provider0, this);
provider1.get();
}
public void shutdown() {
- singletonScope.postScopeEvent(OnScopeEnd.class);
- };
+ singletonScope.shutdown();
+ }
- SingletonScope getSingletonScope() {
+ DefaultScope getSingletonScope() {
return singletonScope;
}
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=954852&r1=954851&r2=954852&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 Tue Jun 15 12:32:11 2010
@@ -53,10 +53,7 @@ class DefaultListBuilder<T> implements L
public ListBuilder<T> add(T value) throws ConfigurationException {
Provider<T> provider0 = new InstanceProvider<T>(value);
- Provider<T> provider1 = new FieldInjectingProvider<T>(
- provider0,
- injector,
- bindingKey);
+ Provider<T> provider1 = new FieldInjectingProvider<T>(provider0, injector);
getListProvider().add(provider1);
return this;
@@ -68,10 +65,7 @@ class DefaultListBuilder<T> implements L
for (T value : values) {
Provider<T> provider0 = new InstanceProvider<T>(value);
- Provider<T> provider1 = new FieldInjectingProvider<T>(
- provider0,
- injector,
- bindingKey);
+ Provider<T> provider1 = new FieldInjectingProvider<T>(provider0, injector);
listProvider.add(provider1);
}
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=954852&r1=954851&r2=954852&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 Tue Jun 15 12:32:11 2010
@@ -55,10 +55,7 @@ class DefaultMapBuilder<T> implements Ma
public MapBuilder<T> put(String key, T value) throws ConfigurationException {
Provider<T> provider0 = new InstanceProvider<T>(value);
- Provider<T> provider1 = new FieldInjectingProvider<T>(
- provider0,
- injector,
- bindingKey);
+ Provider<T> provider1 = new FieldInjectingProvider<T>(provider0, injector);
// TODO: andrus 11/15/2009 - report overriding the key??
getMapProvider().put(key, provider1);
@@ -72,10 +69,7 @@ class DefaultMapBuilder<T> implements Ma
for (Entry<String, T> entry : map.entrySet()) {
Provider<T> provider0 = new InstanceProvider<T>(entry.getValue());
- Provider<T> provider1 = new FieldInjectingProvider<T>(
- provider0,
- injector,
- bindingKey);
+ Provider<T> provider1 = new FieldInjectingProvider<T>(provider0, injector);
provider.put(entry.getKey(), provider1);
}
Added: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultScope.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultScope.java?rev=954852&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultScope.java (added)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultScope.java Tue Jun 15 12:32:11 2010
@@ -0,0 +1,151 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.di.spi;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.cayenne.di.BeforeScopeEnd;
+import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.di.Scope;
+
+/**
+ * An implementation of a DI scopes with support scope events.
+ *
+ * @since 3.1
+ */
+public class DefaultScope implements Scope {
+
+ protected Collection<Class<? extends Annotation>> eventTypes;
+ protected ConcurrentMap<String, Collection<ScopeEventBinding>> listeners;
+
+ private static final String SPECIAL_EVENT = AfterScopeEnd.class.getName();
+
+ public DefaultScope(Class<? extends Annotation>... customEventTypes) {
+ this.listeners = new ConcurrentHashMap<String, Collection<ScopeEventBinding>>();
+ this.eventTypes = new HashSet<Class<? extends Annotation>>();
+
+ // initialize the event listener data structures in constructor to avoid
+ // synchronization concerns on everything but per-event lists.
+
+ // standard event types
+ eventTypes.add(BeforeScopeEnd.class);
+ eventTypes.add(AfterScopeEnd.class);
+
+ // custom event types
+ if (customEventTypes != null) {
+ for (Class<? extends Annotation> type : customEventTypes) {
+ eventTypes.add(type);
+ }
+ }
+
+ for (Class<? extends Annotation> type : eventTypes) {
+ listeners.put(type.getName(), new ConcurrentLinkedQueue<ScopeEventBinding>());
+ }
+ }
+
+ /**
+ * Shuts down this scope, posting {@link BeforeScopeEnd} and {@link AfterScopeEnd}
+ * events.
+ */
+ public void shutdown() {
+ postScopeEvent(BeforeScopeEnd.class);
+
+ // this will notify providers that they should reset their state and unregister
+ // object event listeners that just went out of scope
+ postScopeEvent(AfterScopeEnd.class);
+ }
+
+ /**
+ * Registers annotated methods of an arbitrary object for this scope lifecycle events.
+ */
+ public void addScopeEventListener(Object object) {
+
+ // TODO: cache metadata for non-singletons scopes for performance
+
+ // 'getMethods' grabs public method from the class and its superclasses...
+ for (Method method : object.getClass().getMethods()) {
+
+ for (Class<? extends Annotation> annotationType : eventTypes) {
+
+ if (method.isAnnotationPresent(annotationType)) {
+ String typeName = annotationType.getName();
+
+ Collection<ScopeEventBinding> eventListeners = listeners
+ .get(typeName);
+ eventListeners.add(new ScopeEventBinding(object, method));
+ }
+ }
+ }
+ }
+
+ public void removeScopeEventListener(Object object) {
+
+ for (Entry<String, Collection<ScopeEventBinding>> entry : listeners.entrySet()) {
+
+ if (SPECIAL_EVENT.equals(entry.getKey())) {
+ // no scanning and removal of Scope providers ...
+ // for faster scan skip those
+ continue;
+ }
+
+ Iterator<ScopeEventBinding> it = entry.getValue().iterator();
+ while (it.hasNext()) {
+ ScopeEventBinding binding = it.next();
+ if (binding.getObject() == object) {
+ it.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * Posts a scope event to all registered listeners. There's no predetermined order of
+ * event dispatching. An exception thrown by any of the listeners stops further event
+ * processing and is rethrown.
+ */
+ public void postScopeEvent(
+ Class<? extends Annotation> type,
+ Object... eventParameters) {
+
+ Collection<ScopeEventBinding> eventListeners = listeners.get(type.getName());
+
+ if (eventListeners != null) {
+ Iterator<ScopeEventBinding> it = eventListeners.iterator();
+ while (it.hasNext()) {
+ ScopeEventBinding listener = it.next();
+ if (!listener.onScopeEvent(eventParameters)) {
+ // remove listeners that were garbage collected
+ it.remove();
+ }
+ }
+ }
+ }
+
+ public <T> Provider<T> scope(Provider<T> unscoped) {
+ return new DefaultScopeProvider<T>(this, unscoped);
+ }
+}
Copied: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultScopeProvider.java (from r954823, cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/SingletonProvider.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultScopeProvider.java?p2=cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultScopeProvider.java&p1=cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/SingletonProvider.java&r1=954823&r2=954852&rev=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/SingletonProvider.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/DefaultScopeProvider.java Tue Jun 15 12:32:11 2010
@@ -22,19 +22,23 @@ import org.apache.cayenne.ConfigurationE
import org.apache.cayenne.di.Provider;
/**
+ * A provider that provides scoping for other provoders.
+ *
* @since 3.1
*/
-class SingletonProvider<T> implements Provider<T> {
+public class DefaultScopeProvider<T> implements Provider<T> {
private Provider<T> delegate;
- private SingletonScope scope;
+ private DefaultScope scope;
// presumably "volatile" works in Java 5 and newer to prevent double-checked locking
private volatile T instance;
- public SingletonProvider(SingletonScope scope, Provider<T> delegate) {
+ public DefaultScopeProvider(DefaultScope scope, Provider<T> delegate) {
this.scope = scope;
this.delegate = delegate;
+
+ scope.addScopeEventListener(this);
}
public T get() {
@@ -58,4 +62,13 @@ class SingletonProvider<T> implements Pr
return instance;
}
+ @AfterScopeEnd
+ public void afterScopeEnd() throws Exception {
+ Object localInstance = instance;
+
+ if (localInstance != null) {
+ instance = null;
+ scope.removeScopeEventListener(localInstance);
+ }
+ }
}
Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/FieldInjectingProvider.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/FieldInjectingProvider.java?rev=954852&r1=954851&r2=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/FieldInjectingProvider.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/FieldInjectingProvider.java Tue Jun 15 12:32:11 2010
@@ -30,15 +30,12 @@ import org.apache.cayenne.di.Provider;
*/
class FieldInjectingProvider<T> implements Provider<T> {
- private Key<?> bindingKey;
private DefaultInjector injector;
private Provider<T> delegate;
- FieldInjectingProvider(Provider<T> delegate, DefaultInjector injector,
- Key<?> bindingKey) {
+ FieldInjectingProvider(Provider<T> delegate, DefaultInjector injector) {
this.delegate = delegate;
this.injector = injector;
- this.bindingKey = bindingKey;
}
public T get() throws ConfigurationException {
@@ -88,9 +85,9 @@ class FieldInjectingProvider<T> implemen
value = injector.getProvider(Key.get(objectClass, bindingName));
}
else {
-
+
Key<?> key = Key.get(fieldType, bindingName);
-
+
stack.push(key);
try {
value = injector.getInstance(key);
Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/ScopeEventBinding.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/ScopeEventBinding.java?rev=954852&r1=954851&r2=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/ScopeEventBinding.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/main/java/org/apache/cayenne/di/spi/ScopeEventBinding.java Tue Jun 15 12:32:11 2010
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.cayenne.di.spi;
+import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import org.apache.cayenne.CayenneRuntimeException;
@@ -27,14 +28,17 @@ import org.apache.cayenne.CayenneRuntime
*
* @since 3.1
*/
-class ScopeEventBinding {
+public class ScopeEventBinding {
- private Object object;
+ private WeakReference<Object> objectReference;
private Method eventHandlerMethod;
private int argWidth;
- ScopeEventBinding(Object object, Method eventHandlerMethod) {
- this.object = object;
+ public ScopeEventBinding(Object object, Method eventHandlerMethod) {
+
+ // store weak references for objects to avoid retaining them when they go out of
+ // scope
+ this.objectReference = new WeakReference<Object>(object);
this.eventHandlerMethod = eventHandlerMethod;
this.argWidth = eventHandlerMethod.getParameterTypes().length;
@@ -42,7 +46,16 @@ class ScopeEventBinding {
eventHandlerMethod.setAccessible(true);
}
- void onScopeEvent(Object... eventArgs) {
+ public Object getObject() {
+ return objectReference.get();
+ }
+
+ public boolean onScopeEvent(Object... eventArgs) {
+
+ Object object = objectReference.get();
+ if (object == null) {
+ return false;
+ }
try {
eventHandlerMethod.invoke(object, invocationArguments(eventArgs));
@@ -53,6 +66,8 @@ class ScopeEventBinding {
e,
eventHandlerMethod.getName());
}
+
+ return true;
}
private Object[] invocationArguments(Object[] eventArgs) {
Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_EventAnnotations.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_EventAnnotations.java?rev=954852&r1=954851&r2=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_EventAnnotations.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_EventAnnotations.java Tue Jun 15 12:32:11 2010
@@ -18,7 +18,7 @@
****************************************************************/
package org.apache.cayenne.di.mock;
-import org.apache.cayenne.di.OnScopeEnd;
+import org.apache.cayenne.di.BeforeScopeEnd;
public class MockImplementation1_EventAnnotations extends
MockImplementation1_EventAnnotationsBase implements MockInterface1 {
@@ -27,12 +27,12 @@ public class MockImplementation1_EventAn
return "XuI";
}
- @OnScopeEnd
+ @BeforeScopeEnd
public void onShutdown1() {
shutdown1 = true;
}
- @OnScopeEnd
+ @BeforeScopeEnd
public void onShutdown2() {
shutdown2 = true;
}
Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_EventAnnotationsBase.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_EventAnnotationsBase.java?rev=954852&r1=954851&r2=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_EventAnnotationsBase.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/mock/MockImplementation1_EventAnnotationsBase.java Tue Jun 15 12:32:11 2010
@@ -18,7 +18,7 @@
****************************************************************/
package org.apache.cayenne.di.mock;
-import org.apache.cayenne.di.OnScopeEnd;
+import org.apache.cayenne.di.BeforeScopeEnd;
public class MockImplementation1_EventAnnotationsBase {
@@ -32,7 +32,7 @@ public class MockImplementation1_EventAn
shutdown3 = false;
}
- @OnScopeEnd
+ @BeforeScopeEnd
public void onShutdown3() {
shutdown3 = true;
}
Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorScopeTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorScopeTest.java?rev=954852&r1=954851&r2=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorScopeTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorScopeTest.java Tue Jun 15 12:32:11 2010
@@ -22,7 +22,7 @@ import junit.framework.TestCase;
import org.apache.cayenne.di.Binder;
import org.apache.cayenne.di.Module;
-import org.apache.cayenne.di.OnScopeEnd;
+import org.apache.cayenne.di.BeforeScopeEnd;
import org.apache.cayenne.di.mock.MockImplementation1;
import org.apache.cayenne.di.mock.MockImplementation1_EventAnnotations;
import org.apache.cayenne.di.mock.MockImplementation1_Provider;
@@ -127,7 +127,7 @@ public class DefaultInjectorScopeTest ex
assertFalse(MockImplementation1_EventAnnotations.shutdown2);
assertFalse(MockImplementation1_EventAnnotations.shutdown3);
- injector.getSingletonScope().postScopeEvent(OnScopeEnd.class);
+ injector.getSingletonScope().postScopeEvent(BeforeScopeEnd.class);
assertTrue(MockImplementation1_EventAnnotations.shutdown1);
assertTrue(MockImplementation1_EventAnnotations.shutdown2);
Modified: cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorTest.java?rev=954852&r1=954851&r2=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-di-unpublished/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorTest.java Tue Jun 15 12:32:11 2010
@@ -22,7 +22,7 @@ import junit.framework.TestCase;
import org.apache.cayenne.di.Binder;
import org.apache.cayenne.di.Module;
-import org.apache.cayenne.di.OnScopeEnd;
+import org.apache.cayenne.di.BeforeScopeEnd;
import org.apache.cayenne.di.mock.MockImplementation1_EventAnnotations;
import org.apache.cayenne.di.mock.MockInterface1;
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/event/DefaultEventManager.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/event/DefaultEventManager.java?rev=954852&r1=954851&r2=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/event/DefaultEventManager.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/event/DefaultEventManager.java Tue Jun 15 12:32:11 2010
@@ -27,7 +27,7 @@ import java.util.Map;
import java.util.WeakHashMap;
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.di.OnScopeEnd;
+import org.apache.cayenne.di.BeforeScopeEnd;
import org.apache.cayenne.util.Invocation;
/**
@@ -107,7 +107,7 @@ public class DefaultEventManager impleme
*
* @since 3.0
*/
- @OnScopeEnd
+ @BeforeScopeEnd
public void shutdown() {
if (!stopped) {
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/DICaseSelfTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/DICaseSelfTest.java?rev=954852&r1=954851&r2=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/DICaseSelfTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/DICaseSelfTest.java Tue Jun 15 12:32:11 2010
@@ -24,6 +24,7 @@ import org.apache.cayenne.di.Inject;
import org.apache.cayenne.di.Injector;
import org.apache.cayenne.di.Key;
import org.apache.cayenne.di.Module;
+import org.apache.cayenne.di.spi.DefaultScope;
public class DICaseSelfTest extends DICase {
@@ -33,7 +34,7 @@ public class DICaseSelfTest extends DICa
Module selfTestModule = new Module() {
public void configure(Binder binder) {
- UnitTestScope testScope = new UnitTestScope();
+ DefaultScope testScope = new DefaultScope();
binder.bind(UnitTestLifecycleManager.class).toInstance(
new DefaultUnitTestLifecycleManager(testScope));
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/DefaultUnitTestLifecycleManager.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/DefaultUnitTestLifecycleManager.java?rev=954852&r1=954851&r2=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/DefaultUnitTestLifecycleManager.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/DefaultUnitTestLifecycleManager.java Tue Jun 15 12:32:11 2010
@@ -20,18 +20,19 @@ package org.apache.cayenne.unit.di;
import junit.framework.TestCase;
+import org.apache.cayenne.di.BeforeScopeEnd;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.di.OnScopeEnd;
+import org.apache.cayenne.di.spi.DefaultScope;
public class DefaultUnitTestLifecycleManager implements UnitTestLifecycleManager {
@Inject
protected Injector injector;
- protected UnitTestScope scope;
+ protected DefaultScope scope;
- public DefaultUnitTestLifecycleManager(UnitTestScope scope) {
+ public DefaultUnitTestLifecycleManager(DefaultScope scope) {
this.scope = scope;
}
@@ -39,8 +40,8 @@ public class DefaultUnitTestLifecycleMan
injector.injectMembers(testCase);
}
- @OnScopeEnd
+ @BeforeScopeEnd
public <T extends TestCase> void tearDown(T testCase) {
- scope.postScopeEvent(OnScopeEnd.class);
+ scope.shutdown();
}
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/CachingServerRuntimeFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/CachingServerRuntimeFactory.java?rev=954852&r1=954851&r2=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/CachingServerRuntimeFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/CachingServerRuntimeFactory.java Tue Jun 15 12:32:11 2010
@@ -28,27 +28,27 @@ import org.apache.cayenne.configuration.
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.di.Binder;
import org.apache.cayenne.di.Module;
+import org.apache.cayenne.di.spi.DefaultScope;
import org.apache.cayenne.unit.CayenneResources;
-import org.apache.cayenne.unit.di.UnitTestScope;
public class CachingServerRuntimeFactory implements ServerRuntimeFactory {
protected CayenneResources resources;
- protected UnitTestScope testScope;
+ protected DefaultScope testScope;
protected Map<String, ServerRuntime> cache;
- public CachingServerRuntimeFactory(CayenneResources resources, UnitTestScope testScope) {
+ public CachingServerRuntimeFactory(CayenneResources resources, DefaultScope testScope) {
this.resources = resources;
this.testScope = testScope;
this.cache = new HashMap<String, ServerRuntime>();
}
public ServerRuntime get(String configurationLocation) {
-
+
if (configurationLocation == null) {
throw new NullPointerException("Null 'configurationLocation'");
}
-
+
ServerRuntime runtime = cache.get(configurationLocation);
if (runtime == null) {
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/ServerCase.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/ServerCase.java?rev=954852&r1=954851&r2=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/ServerCase.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/ServerCase.java Tue Jun 15 12:32:11 2010
@@ -27,12 +27,12 @@ import org.apache.cayenne.di.Binder;
import org.apache.cayenne.di.DIBootstrap;
import org.apache.cayenne.di.Injector;
import org.apache.cayenne.di.Module;
+import org.apache.cayenne.di.spi.DefaultScope;
import org.apache.cayenne.test.jdbc.DBHelper;
import org.apache.cayenne.unit.AccessStackAdapter;
import org.apache.cayenne.unit.CayenneResources;
import org.apache.cayenne.unit.di.DICase;
import org.apache.cayenne.unit.di.UnitTestLifecycleManager;
-import org.apache.cayenne.unit.di.UnitTestScope;
public class ServerCase extends DICase {
@@ -54,7 +54,7 @@ public class ServerCase extends DICase {
Module module = new Module() {
public void configure(Binder binder) {
- UnitTestScope testScope = new UnitTestScope();
+ DefaultScope testScope = new DefaultScope();
// these are the objects injectable in unit tests that subclass from
// ServerCase. Server runtime extensions are configured in
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseLifecycleManager.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseLifecycleManager.java?rev=954852&r1=954851&r2=954852&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseLifecycleManager.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseLifecycleManager.java Tue Jun 15 12:32:11 2010
@@ -23,8 +23,8 @@ import junit.framework.TestCase;
import org.apache.cayenne.access.DataDomain;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.di.spi.DefaultScope;
import org.apache.cayenne.unit.di.DefaultUnitTestLifecycleManager;
-import org.apache.cayenne.unit.di.UnitTestScope;
public class ServerCaseLifecycleManager extends DefaultUnitTestLifecycleManager {
@@ -34,7 +34,7 @@ public class ServerCaseLifecycleManager
@Inject
protected ServerRuntimeFactory runtimeFactory;
- public ServerCaseLifecycleManager(UnitTestScope scope) {
+ public ServerCaseLifecycleManager(DefaultScope scope) {
super(scope);
}