Author: nfilotto
Date: 2010-05-06 09:21:54 -0400 (Thu, 06 May 2010)
New Revision: 2352
Added:
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ConcurrentPicoContainer.java
kernel/trunk/exo.kernel.container/src/test/resources/org/exoplatform/container/empty-config.xml
Modified:
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/CachingContainer.java
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/mc/MCIntegrationContainer.java
kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/TestExoContainer.java
Log:
EXOJCR-715: Implementation of a MutablePicoContainer based on java.util.concurrent
collections
Modified:
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/CachingContainer.java
===================================================================
---
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/CachingContainer.java 2010-05-06
11:53:08 UTC (rev 2351)
+++
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/CachingContainer.java 2010-05-06
13:21:54 UTC (rev 2352)
@@ -25,7 +25,6 @@
import org.picocontainer.PicoException;
import org.picocontainer.PicoRegistrationException;
import org.picocontainer.PicoVisitor;
-import org.picocontainer.defaults.AbstractPicoVisitor;
import org.picocontainer.defaults.ComponentAdapterFactory;
import org.picocontainer.defaults.DuplicateComponentKeyRegistrationException;
@@ -146,7 +145,7 @@
return instance;
}
- private static final PicoVisitor invalidator = new AbstractPicoVisitor()
+ private static final PicoVisitor invalidator = new ContainerVisitor()
{
public void visitContainer(PicoContainer pico)
{
@@ -160,14 +159,6 @@
caching.instancesByType.clear();
}
}
-
- public void visitComponentAdapter(ComponentAdapter componentAdapter)
- {
- }
-
- public void visitParameter(Parameter parameter)
- {
- }
};
private void invalidate()
@@ -177,69 +168,65 @@
//
- public synchronized ComponentAdapter registerComponent(ComponentAdapter
componentAdapter)
+ public ComponentAdapter registerComponent(ComponentAdapter componentAdapter)
throws DuplicateComponentKeyRegistrationException
{
+ ComponentAdapter adapter = super.registerComponent(componentAdapter);
invalidate();
- return super.registerComponent(componentAdapter);
+ return adapter;
}
- public synchronized ComponentAdapter unregisterComponent(Object componentKey)
+ public ComponentAdapter unregisterComponent(Object componentKey)
{
+ ComponentAdapter adapter = super.unregisterComponent(componentKey);
invalidate();
- return super.unregisterComponent(componentKey);
+ return adapter;
}
- public synchronized ComponentAdapter registerComponentInstance(Object component)
throws PicoRegistrationException
+ public ComponentAdapter registerComponentInstance(Object component) throws
PicoRegistrationException
{
+ ComponentAdapter adapter = super.registerComponentInstance(component);
invalidate();
- return super.registerComponentInstance(component);
+ return adapter;
}
- public synchronized ComponentAdapter registerComponentInstance(Object componentKey,
Object componentInstance)
+ public ComponentAdapter registerComponentInstance(Object componentKey, Object
componentInstance)
throws PicoRegistrationException
{
+ ComponentAdapter adapter = super.registerComponentInstance(componentKey,
componentInstance);
invalidate();
- return super.registerComponentInstance(componentKey, componentInstance);
+ return adapter;
}
- public synchronized ComponentAdapter registerComponentImplementation(Class
componentImplementation)
+ public ComponentAdapter registerComponentImplementation(Class
componentImplementation)
throws PicoRegistrationException
{
+ ComponentAdapter adapter =
super.registerComponentImplementation(componentImplementation);
invalidate();
- return super.registerComponentImplementation(componentImplementation);
+ return adapter;
}
- public synchronized ComponentAdapter registerComponentImplementation(Object
componentKey, Class componentImplementation)
+ public ComponentAdapter registerComponentImplementation(Object componentKey, Class
componentImplementation)
throws PicoRegistrationException
{
+ ComponentAdapter adapter = super.registerComponentImplementation(componentKey,
componentImplementation);
invalidate();
- return super.registerComponentImplementation(componentKey,
componentImplementation);
+ return adapter;
}
- public synchronized ComponentAdapter registerComponentImplementation(Object
componentKey, Class componentImplementation,
+ public ComponentAdapter registerComponentImplementation(Object componentKey, Class
componentImplementation,
Parameter[] parameters) throws PicoRegistrationException
{
+ ComponentAdapter adapter = super.registerComponentImplementation(componentKey,
componentImplementation, parameters);
invalidate();
- return super.registerComponentImplementation(componentKey, componentImplementation,
parameters);
+ return adapter;
}
- public synchronized ComponentAdapter registerComponentImplementation(Object
componentKey, Class componentImplementation,
+ public ComponentAdapter registerComponentImplementation(Object componentKey, Class
componentImplementation,
List parameters) throws PicoRegistrationException
{
+ ComponentAdapter adapter = super.registerComponentImplementation(componentKey,
componentImplementation, parameters);
invalidate();
- return super.registerComponentImplementation(componentKey, componentImplementation,
parameters);
+ return adapter;
}
-
- public synchronized boolean addChildContainer(PicoContainer child)
- {
- invalidate();
- return super.addChildContainer(child);
- }
-
- public synchronized boolean removeChildContainer(PicoContainer child)
- {
- invalidate();
- return super.removeChildContainer(child);
- }
}
Added:
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ConcurrentPicoContainer.java
===================================================================
---
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ConcurrentPicoContainer.java
(rev 0)
+++
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ConcurrentPicoContainer.java 2010-05-06
13:21:54 UTC (rev 2352)
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.container;
+
+import org.picocontainer.ComponentAdapter;
+import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.Parameter;
+import org.picocontainer.PicoContainer;
+import org.picocontainer.PicoException;
+import org.picocontainer.PicoRegistrationException;
+import org.picocontainer.PicoVerificationException;
+import org.picocontainer.PicoVisitor;
+import org.picocontainer.alternatives.ImmutablePicoContainer;
+import org.picocontainer.defaults.AbstractPicoVisitor;
+import org.picocontainer.defaults.AmbiguousComponentResolutionException;
+import org.picocontainer.defaults.CachingComponentAdapter;
+import org.picocontainer.defaults.CachingComponentAdapterFactory;
+import org.picocontainer.defaults.ComponentAdapterFactory;
+import org.picocontainer.defaults.DefaultComponentAdapterFactory;
+import org.picocontainer.defaults.DefaultPicoContainer;
+import org.picocontainer.defaults.DuplicateComponentKeyRegistrationException;
+import org.picocontainer.defaults.InstanceComponentAdapter;
+import org.picocontainer.defaults.LifecycleVisitor;
+import org.picocontainer.defaults.VerifyingVisitor;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * This class is aimed to be the ThreadSafe counterpart of {@link DefaultPicoContainer}
based on
+ * java.util.concurrent collections.
+ *
+ * Created by The eXo Platform SAS
+ * Author : Nicolas Filotto
+ * nicolas.filotto(a)exoplatform.com
+ * 6 mai 2010
+ * @version $Revision$
+ */
+@SuppressWarnings("unchecked")
+public class ConcurrentPicoContainer implements MutablePicoContainer, Serializable
+{
+
+ /**
+ * The serial version UID
+ */
+ private static final long serialVersionUID = -2275793454555604533L;
+
+ private final ConcurrentMap<Object, ComponentAdapter> componentKeyToAdapterCache
=
+ new ConcurrentHashMap<Object, ComponentAdapter>();
+
+ private final ComponentAdapterFactory componentAdapterFactory;
+
+ private final PicoContainer parent;
+
+ private final Set<ComponentAdapter> componentAdapters = new
CopyOnWriteArraySet<ComponentAdapter>();
+
+ // Keeps track of instantiation order.
+ private final CopyOnWriteArrayList<ComponentAdapter> orderedComponentAdapters =
new CopyOnWriteArrayList<ComponentAdapter>();
+
+ private final AtomicBoolean started = new AtomicBoolean();
+
+ private final AtomicBoolean disposed = new AtomicBoolean();
+
+ private final Set<PicoContainer> children = new
CopyOnWriteArraySet<PicoContainer>();
+
+ /**
+ * Creates a new container with a custom ComponentAdapterFactory and a parent
container.
+ * <p/>
+ * <em>
+ * Important note about caching: If you intend the components to be cached, you should
pass
+ * in a factory that creates {@link CachingComponentAdapter} instances, such as for
example
+ * {@link CachingComponentAdapterFactory}. CachingComponentAdapterFactory can delegate
to
+ * other ComponentAdapterFactories.
+ * </em>
+ *
+ * @param componentAdapterFactory the factory to use for creation of
ComponentAdapters.
+ * @param parent the parent container (used for component dependency
lookups).
+ */
+ public ConcurrentPicoContainer(ComponentAdapterFactory componentAdapterFactory,
PicoContainer parent)
+ {
+ if (componentAdapterFactory == null)
+ throw new NullPointerException("componentAdapterFactory");
+ this.componentAdapterFactory = componentAdapterFactory;
+ this.parent = parent == null ? null : new ImmutablePicoContainer(parent);
+ }
+
+ /**
+ * Creates a new container with a (caching) {@link DefaultComponentAdapterFactory}
+ * and a parent container.
+ */
+ public ConcurrentPicoContainer(PicoContainer parent)
+ {
+ this(new DefaultComponentAdapterFactory(), parent);
+ }
+
+ /**
+ * Creates a new container with a custom ComponentAdapterFactory and no parent
container.
+ *
+ * @param componentAdapterFactory the ComponentAdapterFactory to use.
+ */
+ public ConcurrentPicoContainer(ComponentAdapterFactory componentAdapterFactory)
+ {
+ this(componentAdapterFactory, null);
+ }
+
+ /**
+ * Creates a new container with a (caching) {@link DefaultComponentAdapterFactory} and
no parent container.
+ */
+ public ConcurrentPicoContainer()
+ {
+ this(new DefaultComponentAdapterFactory(), null);
+ }
+
+ public Collection getComponentAdapters()
+ {
+ return Collections.unmodifiableSet(componentAdapters);
+ }
+
+ public final ComponentAdapter getComponentAdapter(Object componentKey) throws
AmbiguousComponentResolutionException
+ {
+ ComponentAdapter adapter = componentKeyToAdapterCache.get(componentKey);
+ if (adapter == null && parent != null)
+ {
+ adapter = parent.getComponentAdapter(componentKey);
+ }
+ return adapter;
+ }
+
+ public ComponentAdapter getComponentAdapterOfType(Class componentType)
+ {
+ // See
http://jira.codehaus.org/secure/ViewIssue.jspa?key=PICO-115
+ ComponentAdapter adapterByKey = getComponentAdapter(componentType);
+ if (adapterByKey != null)
+ {
+ return adapterByKey;
+ }
+
+ List found = getComponentAdaptersOfType(componentType);
+
+ if (found.size() == 1)
+ {
+ return ((ComponentAdapter)found.get(0));
+ }
+ else if (found.size() == 0)
+ {
+ if (parent != null)
+ {
+ return parent.getComponentAdapterOfType(componentType);
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ Class[] foundClasses = new Class[found.size()];
+ for (int i = 0; i < foundClasses.length; i++)
+ {
+ ComponentAdapter componentAdapter = (ComponentAdapter)found.get(i);
+ foundClasses[i] = componentAdapter.getComponentImplementation();
+ }
+
+ throw new AmbiguousComponentResolutionException(componentType, foundClasses);
+ }
+ }
+
+ public List getComponentAdaptersOfType(Class componentType)
+ {
+ if (componentType == null)
+ {
+ return Collections.EMPTY_LIST;
+ }
+ List<ComponentAdapter> found = new ArrayList<ComponentAdapter>();
+ for (Iterator<ComponentAdapter> iterator = componentAdapters.iterator();
iterator.hasNext();)
+ {
+ ComponentAdapter componentAdapter = iterator.next();
+
+ if
(componentType.isAssignableFrom(componentAdapter.getComponentImplementation()))
+ {
+ found.add(componentAdapter);
+ }
+ }
+ return found;
+ }
+
+ /**
+ * {@inheritDoc}
+ * This method can be used to override the ComponentAdapter created by the {@link
ComponentAdapterFactory}
+ * passed to the constructor of this container.
+ */
+ public ComponentAdapter registerComponent(ComponentAdapter componentAdapter)
+ throws DuplicateComponentKeyRegistrationException
+ {
+ Object componentKey = componentAdapter.getComponentKey();
+
+ if (componentKeyToAdapterCache.putIfAbsent(componentKey, componentAdapter) !=
null)
+ {
+ throw new DuplicateComponentKeyRegistrationException(componentKey);
+ }
+ componentAdapters.add(componentAdapter);
+ return componentAdapter;
+ }
+
+ public ComponentAdapter unregisterComponent(Object componentKey)
+ {
+ ComponentAdapter adapter = componentKeyToAdapterCache.remove(componentKey);
+ componentAdapters.remove(adapter);
+ orderedComponentAdapters.remove(adapter);
+ return adapter;
+ }
+
+ /**
+ * {@inheritDoc}
+ * The returned ComponentAdapter will be an {@link InstanceComponentAdapter}.
+ */
+ public ComponentAdapter registerComponentInstance(Object component) throws
PicoRegistrationException
+ {
+ return registerComponentInstance(component.getClass(), component);
+ }
+
+ /**
+ * {@inheritDoc}
+ * The returned ComponentAdapter will be an {@link InstanceComponentAdapter}.
+ */
+ public ComponentAdapter registerComponentInstance(Object componentKey, Object
componentInstance)
+ throws PicoRegistrationException
+ {
+ if (componentInstance instanceof MutablePicoContainer)
+ {
+ MutablePicoContainer pc = (MutablePicoContainer)componentInstance;
+ Object contrivedKey = new Object();
+ String contrivedComp = "";
+ pc.registerComponentInstance(contrivedKey, contrivedComp);
+ try
+ {
+ if (this.getComponentInstance(contrivedKey) != null)
+ {
+ throw new PicoRegistrationException(
+ "Cannot register a container to itself. The container is already
implicitly registered.");
+ }
+ }
+ finally
+ {
+ pc.unregisterComponent(contrivedKey);
+ }
+
+ }
+ ComponentAdapter componentAdapter = new InstanceComponentAdapter(componentKey,
componentInstance);
+ registerComponent(componentAdapter);
+ return componentAdapter;
+ }
+
+ /**
+ * {@inheritDoc}
+ * The returned ComponentAdapter will be instantiated by the {@link
ComponentAdapterFactory}
+ * passed to the container's constructor.
+ */
+ public ComponentAdapter registerComponentImplementation(Class
componentImplementation)
+ throws PicoRegistrationException
+ {
+ return registerComponentImplementation(componentImplementation,
componentImplementation);
+ }
+
+ /**
+ * {@inheritDoc}
+ * The returned ComponentAdapter will be instantiated by the {@link
ComponentAdapterFactory}
+ * passed to the container's constructor.
+ */
+ public ComponentAdapter registerComponentImplementation(Object componentKey, Class
componentImplementation)
+ throws PicoRegistrationException
+ {
+ return registerComponentImplementation(componentKey, componentImplementation,
(Parameter[])null);
+ }
+
+ /**
+ * {@inheritDoc}
+ * The returned ComponentAdapter will be instantiated by the {@link
ComponentAdapterFactory}
+ * passed to the container's constructor.
+ */
+ public ComponentAdapter registerComponentImplementation(Object componentKey, Class
componentImplementation,
+ Parameter[] parameters) throws PicoRegistrationException
+ {
+ ComponentAdapter componentAdapter =
+ componentAdapterFactory.createComponentAdapter(componentKey,
componentImplementation, parameters);
+ registerComponent(componentAdapter);
+ return componentAdapter;
+ }
+
+ /**
+ * Same as {@link #registerComponentImplementation(java.lang.Object, java.lang.Class,
org.picocontainer.Parameter[])}
+ * but with parameters as a {@link List}. Makes it possible to use with Groovy arrays
(which are actually Lists).
+ */
+ public ComponentAdapter registerComponentImplementation(Object componentKey, Class
componentImplementation,
+ List parameters) throws PicoRegistrationException
+ {
+ Parameter[] parametersAsArray = (Parameter[])parameters.toArray(new
Parameter[parameters.size()]);
+ return registerComponentImplementation(componentKey, componentImplementation,
parametersAsArray);
+ }
+
+ private void addOrderedComponentAdapter(ComponentAdapter componentAdapter)
+ {
+ orderedComponentAdapters.addIfAbsent(componentAdapter);
+ }
+
+ public List getComponentInstances() throws PicoException
+ {
+ return getComponentInstancesOfType(Object.class);
+ }
+
+ public List getComponentInstancesOfType(Class componentType) throws PicoException
+ {
+ if (componentType == null)
+ {
+ return Collections.EMPTY_LIST;
+ }
+
+ Map<ComponentAdapter, Object> adapterToInstanceMap = new
HashMap<ComponentAdapter, Object>();
+ for (Iterator<ComponentAdapter> iterator = componentAdapters.iterator();
iterator.hasNext();)
+ {
+ ComponentAdapter componentAdapter = iterator.next();
+ if
(componentType.isAssignableFrom(componentAdapter.getComponentImplementation()))
+ {
+ Object componentInstance = getInstance(componentAdapter);
+ adapterToInstanceMap.put(componentAdapter, componentInstance);
+
+ // This is to ensure all are added. (Indirect dependencies will be added
+ // from InstantiatingComponentAdapter).
+ addOrderedComponentAdapter(componentAdapter);
+ }
+ }
+ List<Object> result = new ArrayList<Object>();
+ for (Iterator<ComponentAdapter> iterator =
orderedComponentAdapters.iterator(); iterator.hasNext();)
+ {
+ Object componentAdapter = iterator.next();
+ final Object componentInstance = adapterToInstanceMap.get(componentAdapter);
+ if (componentInstance != null)
+ {
+ // may be null in the case of the "implicit" adapter
+ // representing "this".
+ result.add(componentInstance);
+ }
+ }
+ return result;
+ }
+
+ public Object getComponentInstance(Object componentKey) throws PicoException
+ {
+ ComponentAdapter componentAdapter = getComponentAdapter(componentKey);
+ if (componentAdapter != null)
+ {
+ return getInstance(componentAdapter);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public Object getComponentInstanceOfType(Class componentType)
+ {
+ final ComponentAdapter componentAdapter =
getComponentAdapterOfType(componentType);
+ return componentAdapter == null ? null : getInstance(componentAdapter);
+ }
+
+ private Object getInstance(ComponentAdapter componentAdapter)
+ {
+ // check wether this is our adapter
+ // we need to check this to ensure up-down dependencies cannot be followed
+ final boolean isLocal = componentAdapters.contains(componentAdapter);
+
+ if (isLocal)
+ {
+ Object instance = componentAdapter.getComponentInstance(this);
+
+ addOrderedComponentAdapter(componentAdapter);
+
+ return instance;
+ }
+ else if (parent != null)
+ {
+ return parent.getComponentInstance(componentAdapter.getComponentKey());
+ }
+
+ // TODO: decide .. exception or null?
+ // exceptrion: mx: +1, joehni +1
+ return null;
+ }
+
+ public PicoContainer getParent()
+ {
+ return parent;
+ }
+
+ public ComponentAdapter unregisterComponentByInstance(Object componentInstance)
+ {
+ for (Iterator<ComponentAdapter> iterator = componentAdapters.iterator();
iterator.hasNext();)
+ {
+ ComponentAdapter componentAdapter = iterator.next();
+ if (getInstance(componentAdapter).equals(componentInstance))
+ {
+ return unregisterComponent(componentAdapter.getComponentKey());
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @deprecated since 1.1 - Use new VerifyingVisitor().traverse(this)
+ */
+ public void verify() throws PicoVerificationException
+ {
+ new VerifyingVisitor().traverse(this);
+ }
+
+ /**
+ * Start the components of this PicoContainer and all its logical child containers.
+ * Any component implementing the lifecycle interface {@link
org.picocontainer.Startable} will be started.
+ * @see #makeChildContainer()
+ * @see #addChildContainer(PicoContainer)
+ * @see #removeChildContainer(PicoContainer)
+ */
+ public void start()
+ {
+ if (disposed.get())
+ throw new IllegalStateException("Already disposed");
+ if (started.get())
+ throw new IllegalStateException("Already started");
+ LifecycleVisitor.start(this);
+ started.set(true);
+ }
+
+ /**
+ * Stop the components of this PicoContainer and all its logical child containers.
+ * Any component implementing the lifecycle interface {@link
org.picocontainer.Startable} will be stopped.
+ * @see #makeChildContainer()
+ * @see #addChildContainer(PicoContainer)
+ * @see #removeChildContainer(PicoContainer)
+ */
+ public void stop()
+ {
+ if (disposed.get())
+ throw new IllegalStateException("Already disposed");
+ if (!started.get())
+ throw new IllegalStateException("Not started");
+ LifecycleVisitor.stop(this);
+ started.set(false);
+ }
+
+ /**
+ * Dispose the components of this PicoContainer and all its logical child containers.
+ * Any component implementing the lifecycle interface {@link
org.picocontainer.Disposable} will be disposed.
+ * @see #makeChildContainer()
+ * @see #addChildContainer(PicoContainer)
+ * @see #removeChildContainer(PicoContainer)
+ */
+ public void dispose()
+ {
+ if (disposed.get())
+ throw new IllegalStateException("Already disposed");
+ LifecycleVisitor.dispose(this);
+ disposed.set(true);
+ }
+
+ public MutablePicoContainer makeChildContainer()
+ {
+ DefaultPicoContainer pc = new DefaultPicoContainer(componentAdapterFactory, this);
+ addChildContainer(pc);
+ return pc;
+ }
+
+ public boolean addChildContainer(PicoContainer child)
+ {
+ return children.add(child);
+ }
+
+ public boolean removeChildContainer(PicoContainer child)
+ {
+ return children.remove(child);
+ }
+
+ public void accept(PicoVisitor visitor)
+ {
+ visitor.visitContainer(this);
+ for (Iterator<ComponentAdapter> iterator = componentAdapters.iterator();
iterator.hasNext();)
+ {
+ ComponentAdapter componentAdapter = iterator.next();
+ componentAdapter.accept(visitor);
+ }
+ for (Iterator<PicoContainer> iterator = children.iterator();
iterator.hasNext();)
+ {
+ PicoContainer child = iterator.next();
+ child.accept(visitor);
+ }
+ }
+
+ /**
+ * Accepts a visitor that should visit the child containers only.
+ */
+ protected void accept(ContainerVisitor visitor)
+ {
+ visitor.visitContainer(this);
+ for (Iterator<PicoContainer> iterator = children.iterator();
iterator.hasNext();)
+ {
+ PicoContainer child = iterator.next();
+ child.accept(visitor);
+ }
+ }
+
+ /**
+ * Cans be used to indicate that we only want to visit Containers
+ */
+ protected static abstract class ContainerVisitor extends AbstractPicoVisitor
+ {
+ public final void visitComponentAdapter(ComponentAdapter componentAdapter)
+ {
+ }
+
+ public final void visitParameter(Parameter parameter)
+ {
+ }
+ }
+}
Modified:
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/mc/MCIntegrationContainer.java
===================================================================
---
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/mc/MCIntegrationContainer.java 2010-05-06
11:53:08 UTC (rev 2351)
+++
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/mc/MCIntegrationContainer.java 2010-05-06
13:21:54 UTC (rev 2352)
@@ -21,19 +21,19 @@
*/
package org.exoplatform.container.mc;
+import org.exoplatform.container.ConcurrentPicoContainer;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.picocontainer.ComponentAdapter;
import org.picocontainer.PicoContainer;
import org.picocontainer.defaults.ComponentAdapterFactory;
-import org.picocontainer.defaults.DefaultPicoContainer;
/**
* Container class that serves as an interception point for MC integration.
*
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
-public class MCIntegrationContainer extends DefaultPicoContainer
+public class MCIntegrationContainer extends ConcurrentPicoContainer
{
/**
* Logger
Modified:
kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/TestExoContainer.java
===================================================================
---
kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/TestExoContainer.java 2010-05-06
11:53:08 UTC (rev 2351)
+++
kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/TestExoContainer.java 2010-05-06
13:21:54 UTC (rev 2352)
@@ -19,6 +19,7 @@
import org.exoplatform.container.component.BaseComponentPlugin;
import org.exoplatform.container.configuration.ConfigurationManager;
import org.exoplatform.container.jmx.AbstractTestContainer;
+import org.exoplatform.container.support.ContainerBuilder;
import org.exoplatform.container.xml.InitParams;
import org.picocontainer.ComponentAdapter;
import org.picocontainer.PicoContainer;
@@ -27,6 +28,7 @@
import org.picocontainer.PicoVisitor;
import org.picocontainer.defaults.DuplicateComponentKeyRegistrationException;
+import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -72,6 +74,53 @@
assertEquals(value, plugin.myClass_);
}
+ public void testCache()
+ {
+ URL rootURL = getClass().getResource("test-exo-container.xml");
+ URL portalURL = getClass().getResource("empty-config.xml");
+ assertNotNull(rootURL);
+ assertNotNull(portalURL);
+ //
+ new ContainerBuilder().withRoot(rootURL).withPortal(portalURL).build();
+
+ final RootContainer container = RootContainer.getInstance();
+ final ComponentAdapter ca = new ComponentAdapter()
+ {
+
+ public void accept(PicoVisitor paramPicoVisitor)
+ {
+ }
+
+ public Class getComponentImplementation()
+ {
+ return MyClass.class;
+ }
+
+ public Object getComponentInstance(PicoContainer paramPicoContainer)
+ throws PicoInitializationException, PicoIntrospectionException
+ {
+ return new MyClass();
+ }
+
+ public Object getComponentKey()
+ {
+ return "MyKey";
+ }
+
+ public void verify(PicoContainer paramPicoContainer) throws
PicoIntrospectionException
+ {
+ }
+
+ };
+ container.registerComponent(ca);
+ final PortalContainer pcontainer = PortalContainer.getInstance();
+ assertEquals(ca, container.getComponentAdapter("MyKey"));
+ assertEquals(ca, pcontainer.getComponentAdapter("MyKey"));
+ container.unregisterComponent("MyKey");
+ assertNull(container.getComponentAdapter("MyKey"));
+ assertNull(pcontainer.getComponentAdapter("MyKey"));
+ }
+
public void testMultiThreading() throws Throwable
{
final RootContainer container =
createRootContainer("test-exo-container.xml");
@@ -143,7 +192,7 @@
}
};
- ar.set(container.registerComponent(ca));
+ ar.compareAndSet(null, container.registerComponent(ca));
}
catch (DuplicateComponentKeyRegistrationException e)
{
@@ -167,7 +216,52 @@
container.unregisterComponent("a");
}
});
+
+ testMultiThreading(new Task()
+ {
+ public void execute()
+ {
+ final Object key = new Object();
+ ComponentAdapter ca = new ComponentAdapter()
+ {
+
+ public void accept(PicoVisitor paramPicoVisitor)
+ {
+ }
+
+ public Class getComponentImplementation()
+ {
+ return MyClass.class;
+ }
+
+ public Object getComponentInstance(PicoContainer paramPicoContainer)
+ throws PicoInitializationException, PicoIntrospectionException
+ {
+ return new MyClass();
+ }
+
+ public Object getComponentKey()
+ {
+ return key;
+ }
+
+ public void verify(PicoContainer paramPicoContainer) throws
PicoIntrospectionException
+ {
+ }
+
+ };
+ assertNotNull(container.registerComponent(ca));
+ assertNotNull(container.getComponentAdapter(key));
+ assertFalse(container.getComponentAdapters().isEmpty());
+ assertFalse(container.getComponentAdaptersOfType(MyClass.class).isEmpty());
+ assertNotNull(container.getComponentInstance(key));
+ assertNotNull(container.getComponentInstanceOfType(MyClass.class));
+ assertFalse(container.getComponentInstances().isEmpty());
+ assertFalse(container.getComponentInstancesOfType(MyClass.class).isEmpty());
+ assertNotNull(container.unregisterComponent(key));
+ }
+ });
}
private void testMultiThreading(final Task task) throws Throwable
@@ -326,5 +420,5 @@
MyCounter counter =
(MyCounter)container.getComponentInstanceOfType(MyCounter.class);
if (counter != null) counter.stop.add(this);
}
- }
+ }
}
\ No newline at end of file
Added:
kernel/trunk/exo.kernel.container/src/test/resources/org/exoplatform/container/empty-config.xml
===================================================================
---
kernel/trunk/exo.kernel.container/src/test/resources/org/exoplatform/container/empty-config.xml
(rev 0)
+++
kernel/trunk/exo.kernel.container/src/test/resources/org/exoplatform/container/empty-config.xml 2010-05-06
13:21:54 UTC (rev 2352)
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+
+ Copyright (C) 2009 eXo Platform SAS.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+
+-->
+<configuration
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd
http://www.exoplaform.org/xml/ns/kernel_1_1.xsd"
+
xmlns="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd">
+
+</configuration>
\ No newline at end of file