MentaContainer

Compare Revisions

Ignore whitespace Rev 71 → Rev 70

/trunk/src/main/java/org/mentacontainer/impl/MentaContainer.java
1,11 → 1,8
package org.mentacontainer.impl;
 
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
25,80 → 22,62
*/
public class MentaContainer implements Container {
 
private Map<String, Component> beans = new Hashtable<String, Component>();
private Map<String, Component> beans = new HashMap<String, Component>();
private Map<String, Scope> scopes = new Hashtable<String, Scope>();
private Map<String, Scope> scopes = new HashMap<String, Scope>();
private Map<String, Object> singletonsCache = new Hashtable<String, Object>();
private Map<String, Object> singletonsCache = new HashMap<String, Object>();
private Map<String, ThreadLocal<Object>> threadLocalsCache = new Hashtable<String, ThreadLocal<Object>>();
private Map<String, ThreadLocal<Object>> threadLocalsCache = new HashMap<String, ThreadLocal<Object>>();
 
private Set<Dependency> dependencies = Collections.synchronizedSet(new HashSet<Dependency>());
private Set<Dependency> dependencies = new HashSet<Dependency>();
public void clear(Scope scope) {
public synchronized void clear(Scope scope) {
if (scope == Scope.SINGLETON) {
List<ClearablePair> listToClear = new LinkedList<ClearablePair>();
synchronized(this) {
for(String key : singletonsCache.keySet()) {
Component comp = beans.get(key);
if (comp instanceof Clearable) {
Clearable<Object> c = (Clearable<Object>) comp;
Object value = singletonsCache.get(key);
listToClear.add(new ClearablePair(c, value));
}
}
singletonsCache.clear();
for(String key : singletonsCache.keySet()) {
Component comp = beans.get(key);
if (comp instanceof Clearable) {
Clearable<Object> c = (Clearable<Object>) comp;
Object value = singletonsCache.get(key);
c.onCleared(value);
}
}
// clear everything inside a non-synchronized block...
singletonsCache.clear();
for(ClearablePair cp : listToClear) cp.c.onCleared(cp.value);
} else if (scope == Scope.THREAD) {
List<ClearablePair> listToClear = new LinkedList<ClearablePair>();
synchronized(this) {
for(String key : threadLocalsCache.keySet()) {
Component comp = beans.get(key);
if (comp instanceof Clearable) {
Clearable<Object> c = (Clearable<Object>) comp;
ThreadLocal<Object> t = threadLocalsCache.get(key);
Object value = t.get();
if (value != null) listToClear.add(new ClearablePair(c, value));
}
}
for(ThreadLocal<Object> t : threadLocalsCache.values()) {
t.set(null);
}
for(String key : threadLocalsCache.keySet()) {
Component comp = beans.get(key);
if (comp instanceof Clearable) {
Clearable<Object> c = (Clearable<Object>) comp;
ThreadLocal<Object> t = threadLocalsCache.get(key);
Object value = t.get();
if (value != null) c.onCleared(value);
}
}
// clear everything inside a non-synchronized block...
for(ClearablePair cp : listToClear) cp.c.onCleared(cp.value);
for(ThreadLocal<Object> t : threadLocalsCache.values()) {
t.set(null);
}
}
}
public <T> T clear(String key) {
public synchronized <T> T clear(String key) {
if (!beans.containsKey(key)) return null;
106,66 → 85,48
if (scope == Scope.SINGLETON) {
ClearablePair cp = null;
Object value = singletonsCache.remove(key);
Object value = null;
synchronized(this) {
value = singletonsCache.remove(key);
if (value != null) {
Component comp = beans.get(key);
if (comp instanceof Clearable) {
Clearable<Object> c = (Clearable<Object>) comp;
cp = new ClearablePair(c, value);
}
}
if (value != null) {
Component comp = beans.get(key);
if (comp instanceof Clearable) {
Clearable<Object> c = (Clearable<Object>) comp;
c.onCleared(value);
}
}
if (cp != null) cp.c.onCleared(cp.value);
return (T) value;
} else if (scope == Scope.THREAD) {
ClearablePair cp = null;
ThreadLocal<Object> t = threadLocalsCache.get(key);
Object retVal = null;
synchronized(this) {
ThreadLocal<Object> t = threadLocalsCache.get(key);
if (t != null) {
Object o = t.get();
if (o != null) {
Component comp = beans.get(key);
if (comp instanceof Clearable) {
Clearable<Object> c = (Clearable<Object>) comp;
cp = new ClearablePair(c, o);
}
t.set(null);
retVal = o;
}
}
if (t != null) {
Object o = t.get();
if (o != null) {
Component comp = beans.get(key);
if (comp instanceof Clearable) {
Clearable<Object> c = (Clearable<Object>) comp;
c.onCleared(o);
}
t.set(null);
return (T) o;
}
}
if (cp != null) cp.c.onCleared(cp.value);
return (T) retVal;
return null;
} else if (scope == Scope.NONE) {
177,7 → 138,7
}
}
 
public <T> T get(String key) {
public synchronized <T> T get(String key) {
 
if (!beans.containsKey(key)) return null;
 
190,90 → 151,53
try {
 
if (scope == Scope.SINGLETON) {
boolean needsToCreate = false;
synchronized(this) {
 
if (singletonsCache.containsKey(key)) {
target = singletonsCache.get(key);
return (T) target; // no need to wire again...
} else {
needsToCreate = true;
}
}
if (needsToCreate) {
// getInstance needs to be in a non-synchronized block
if (singletonsCache.containsKey(key)) {
 
target = singletonsCache.get(key);
 
return (T) target; // no need to wire again...
 
} else {
 
target = c.getInstance();
synchronized(this) {
 
singletonsCache.put(key, target);
}
singletonsCache.put(key, target);
}
} else if (scope == Scope.THREAD) {
boolean needsToCreate = false;
boolean needsToAddToCache = false;
ThreadLocal<Object> t = null;
synchronized(this) {
if (threadLocalsCache.containsKey(key)) {
t = threadLocalsCache.get(key);
target = t.get();
if (target == null) { // different thread...
needsToCreate = true;
// don't return... let it be wired...
} else {
return (T) target; // no need to wire again...
}
} else {
t = new ThreadLocal<Object>();
needsToCreate = true;
needsToAddToCache = true;
// let it be wired...
}
}
if (needsToCreate) {
if (threadLocalsCache.containsKey(key)) {
// getInstance needs to be in a non-synchronized block
ThreadLocal<Object> t = threadLocalsCache.get(key);
target = t.get();
if (target == null) { // different thread...
target = c.getInstance();
t.set(target);
// don't return... let it be wired...
} else {
return (T) target; // no need to wire again...
}
} else {
ThreadLocal<Object> t = new ThreadLocal<Object>();
target = c.getInstance();
t.set(target);
}
if (needsToAddToCache) {
synchronized(this) {
threadLocalsCache.put(key, t);
threadLocalsCache.put(key, t);
}
// let it be wired...
}
} else if (scope == Scope.NONE) {
446,16 → 370,4
throw new UnsupportedOperationException("This scope is not supported: " + scope);
}
}
private static class ClearablePair {
public ClearablePair(Clearable<Object> c, Object value) {
this.c = c;
this.value = value;
}
Clearable<Object> c;
Object value;
}
}