diff --git a/extensions/source/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java b/extensions/source/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java
index d5984388d98a..c786f87e701a 100644
--- a/extensions/source/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java
+++ b/extensions/source/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java
@@ -5,13 +5,13 @@
package com.intellij.openapi.extensions.impl;
import com.intellij.openapi.extensions.*;
+import org.jdom.Element;
+import org.picocontainer.MutablePicoContainer;
import java.lang.ref.SoftReference;
import java.lang.reflect.Array;
import java.util.*;
-import org.jdom.Element;
-
/**
* @author AKireyev
*/
@@ -160,10 +160,15 @@ public class ExtensionPointImpl implements ExtensionPoint {
return myExtensions.contains(extension);
}
- public void unregisterExtension(Object extension) {
+ public void unregisterExtension(final Object extension) {
assert (extension != null) : "Extension cannot be null";
myOwner.getMutablePicoContainer().unregisterComponentByInstance(extension);
+ final MutablePicoContainer[] pluginContainers = myOwner.getPluginContainers();
+ for (int i = 0; i < pluginContainers.length; i++) {
+ MutablePicoContainer pluginContainer = pluginContainers[i];
+ pluginContainer.unregisterComponentByInstance(extension);
+ }
processAdapters();
diff --git a/extensions/source/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java b/extensions/source/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java
index 5c83163cae29..14ca1f098a29 100644
--- a/extensions/source/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java
+++ b/extensions/source/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java
@@ -350,4 +350,8 @@ public class ExtensionsAreaImpl implements ExtensionsArea {
public void killPendingInteractions() {
mySuspendedListenerActions.clear();
}
+
+ public MutablePicoContainer[] getPluginContainers() {
+ return (MutablePicoContainer[])myPluginName2picoContainer.values().toArray(new MutablePicoContainer[myPluginName2picoContainer.values().size()]);
+ }
}
diff --git a/extensions/testSource/com/intellij/openapi/extensions/impl/DependentObjectOne.java b/extensions/testSource/com/intellij/openapi/extensions/impl/DependentObjectOne.java
new file mode 100644
index 000000000000..d32019a0189a
--- /dev/null
+++ b/extensions/testSource/com/intellij/openapi/extensions/impl/DependentObjectOne.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
+ * Use is subject to license terms.
+ */
+package com.intellij.openapi.extensions.impl;
+
+/**
+ * @author Alexander Kireyev
+ */
+public class DependentObjectOne {
+ private XMLTestBean[] myTestBeans;
+
+ public DependentObjectOne(XMLTestBean[] testBeans) {
+ myTestBeans = testBeans;
+ }
+
+ public XMLTestBean[] getTestBeans() {
+ return myTestBeans;
+ }
+}
diff --git a/extensions/testSource/com/intellij/openapi/extensions/impl/DependentObjectThree.java b/extensions/testSource/com/intellij/openapi/extensions/impl/DependentObjectThree.java
new file mode 100644
index 000000000000..c0f7f3fb3f9c
--- /dev/null
+++ b/extensions/testSource/com/intellij/openapi/extensions/impl/DependentObjectThree.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
+ * Use is subject to license terms.
+ */
+package com.intellij.openapi.extensions.impl;
+
+/**
+ * @author Alexander Kireyev
+ */
+public class DependentObjectThree {
+ private DependentObjectOne myOne;
+ private DependentObjectTwo myTwo;
+ private XMLTestBean[] myTestBeans;
+
+ public DependentObjectThree(DependentObjectOne one, XMLTestBean[] testBeans, DependentObjectTwo two) {
+ myOne = one;
+ myTestBeans = testBeans;
+ myTwo = two;
+ }
+
+ public DependentObjectOne getOne() {
+ return myOne;
+ }
+
+ public XMLTestBean[] getTestBeans() {
+ return myTestBeans;
+ }
+
+ public DependentObjectTwo getTwo() {
+ return myTwo;
+ }
+}
diff --git a/extensions/testSource/com/intellij/openapi/extensions/impl/DependentObjectTwo.java b/extensions/testSource/com/intellij/openapi/extensions/impl/DependentObjectTwo.java
new file mode 100644
index 000000000000..d831df497a0b
--- /dev/null
+++ b/extensions/testSource/com/intellij/openapi/extensions/impl/DependentObjectTwo.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
+ * Use is subject to license terms.
+ */
+package com.intellij.openapi.extensions.impl;
+
+/**
+ * @author Alexander Kireyev
+ */
+public class DependentObjectTwo {
+ private DependentObjectOne myOne;
+
+ public DependentObjectTwo(DependentObjectOne one) {
+ myOne = one;
+ }
+
+ public DependentObjectOne getOne() {
+ return myOne;
+ }
+}
diff --git a/extensions/testSource/com/intellij/openapi/extensions/impl/ExtensionsComplexTest.java b/extensions/testSource/com/intellij/openapi/extensions/impl/ExtensionsComplexTest.java
new file mode 100644
index 000000000000..99608873af27
--- /dev/null
+++ b/extensions/testSource/com/intellij/openapi/extensions/impl/ExtensionsComplexTest.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
+ * Use is subject to license terms.
+ */
+package com.intellij.openapi.extensions.impl;
+
+import junit.framework.TestCase;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.extensions.AreaInstance;
+import com.intellij.openapi.extensions.ExtensionPoint;
+import org.jdom.Element;
+
+import java.util.Iterator;
+import java.util.Arrays;
+
+/**
+ * @author Alexander Kireyev
+ */
+public class ExtensionsComplexTest extends TestCase {
+ private static final String PLUGIN_NAME = "the.test.plugin";
+ private static final String PLUGIN_NAME_2 = "another.test.plugin";
+
+ private static final String TEST_EP_NAME = "the.test.plugin.extensionPoint";
+
+ private static final String TEST_DEPENDENT1_NAME = "the.test.plugin.dependentOne";
+ private static final String TEST_DEPENDENT2_NAME = "the.test.plugin.dependentTwo";
+ private static final String TEST_DEPENDENT3_NAME = "another.test.plugin.dependentThree";
+
+ private static final String TEST_DEPENDENT_CHILD_NAME = "the.test.plugin.dependentChildThree";
+
+ private static final String EXTENSION_POINTS_ROOT =
+ "\n" +
+ " \n" +
+ " \n" +
+ "";
+
+ private static final String EXTENSION_POINTS_4_AREA =
+ "\n" +
+ " \n" +
+ " \n" +
+ "";
+
+ private static final String EXTENSION_POINTS_4_CHILD_AREA =
+ "\n" +
+ " \n" +
+ "";
+
+ private static final String EXTENSIONS_ROOT =
+ " \n" +
+ " \n" +
+ " 321\n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ private static final String EXTENSIONS_4_AREA =
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ private static final String EXTENSIONS_4_CHILD_AREA =
+ " \n" +
+ " \n" +
+ " ";
+
+ private static final String EXTENSION_POINTS_ROOT_2 =
+ " \n" +
+ " \n" +
+ " ";
+
+ private static final String EXTENSION_POINTS_4_AREA_2 =
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ private static final String EXTENSIONS_4_AREA_2 =
+ " \n" +
+ " \n" +
+ " ";
+
+ private static final String EXTENSIONS_4_AREA_2_PLUS =
+ " \n" +
+ " \n" +
+ " ";
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ Extensions.registerAreaClass("area", null);
+ Extensions.registerAreaClass("child_area", "area");
+ }
+
+ protected void tearDown() throws Exception {
+ disposeAreas("child_area");
+ disposeAreas("area");
+ final ExtensionPoint[] extensionPoints = Extensions.getRootArea().getExtensionPoints();
+ for (int i = 0; i < extensionPoints.length; i++) {
+ ExtensionPoint extensionPoint = extensionPoints[i];
+ if (extensionPoint.getName().startsWith(PLUGIN_NAME) || extensionPoint.getName().startsWith(PLUGIN_NAME_2)) {
+ Extensions.getRootArea().unregisterExtensionPoint(extensionPoint.getName());
+ }
+ }
+ super.tearDown();
+ }
+
+ private void disposeAreas(final String areaClass) {
+ final AreaInstance[] allAreas = Extensions.getAllAreas(areaClass);
+ for (int i = 0; i < allAreas.length; i++) {
+ AreaInstance areaInstance = allAreas[i];
+ Extensions.disposeArea(areaInstance);
+ }
+ }
+
+ public void testPluginInit() throws Exception {
+ initExtensionPoints(PLUGIN_NAME, EXTENSION_POINTS_ROOT, null);
+ initExtensions(EXTENSIONS_ROOT, null);
+
+ assertTrue(Extensions.getRootArea().hasExtensionPoint(TEST_EP_NAME));
+ assertEquals(1, Extensions.getExtensions(TEST_EP_NAME).length);
+ assertEquals(321, ((XMLTestBean)Extensions.getRootArea().getExtensionPoint(TEST_EP_NAME).getExtension()).getProp1());
+ assertEquals("the.test.plugin", ((XMLTestBean)Extensions.getRootArea().getExtensionPoint(TEST_EP_NAME).getExtension()).getPluginName());
+
+ DependentObjectOne dependentObjectOne = (DependentObjectOne)Extensions.getRootArea().getExtensionPoint(TEST_DEPENDENT1_NAME).getExtension();
+ assertEquals(1, dependentObjectOne.getTestBeans().length);
+
+ AreaInstance areaInstance = new MyAreaInstance();
+ Extensions.instantiateArea("area", areaInstance, null);
+ initExtensionPoints(PLUGIN_NAME, EXTENSION_POINTS_4_AREA, areaInstance);
+ initExtensions(EXTENSIONS_4_AREA, areaInstance);
+
+ ExtensionPoint extensionPoint = Extensions.getArea(areaInstance).getExtensionPoint("the.test.plugin.extensionPoint4area");
+ assertNotNull(extensionPoint);
+ assertSame(areaInstance, extensionPoint.getArea());
+ assertNotNull(extensionPoint.getExtension());
+
+ DependentObjectTwo dependentObjectTwo = (DependentObjectTwo)Extensions.getArea(areaInstance).getExtensionPoint(TEST_DEPENDENT2_NAME).getExtension();
+ assertSame(dependentObjectOne, dependentObjectTwo.getOne());
+ }
+
+ public void testPluginInitInAreas() throws Exception {
+ initExtensionPoints(PLUGIN_NAME, EXTENSION_POINTS_ROOT, null);
+ initExtensionPoints(PLUGIN_NAME_2, EXTENSION_POINTS_ROOT_2, null);
+ initExtensions(EXTENSIONS_ROOT, null);
+
+ AreaInstance areaInstance1 = new MyAreaInstance();
+ Extensions.instantiateArea("area", areaInstance1, null);
+
+ initExtensionsInAREA(areaInstance1);
+
+ AreaInstance areaInstance2 = new MyAreaInstance();
+ Extensions.instantiateArea("area", areaInstance2, null);
+
+ initExtensionsInAREA(areaInstance2);
+
+ AreaInstance areaInstance3 = new MyAreaInstance();
+ Extensions.instantiateArea("area", areaInstance3, null);
+
+ initExtensionsInAREA(areaInstance3);
+
+ checkAreaInitialized(areaInstance1);
+ checkAreaInitialized(areaInstance2);
+ checkAreaInitialized(areaInstance3);
+
+ MyAreaInstance childAreaInstance1 = new MyAreaInstance();
+ Extensions.instantiateArea("child_area", childAreaInstance1, areaInstance1);
+ initExtensionsInCHILD_AREA(childAreaInstance1);
+ MyAreaInstance childAreaInstance2 = new MyAreaInstance();
+ Extensions.instantiateArea("child_area", childAreaInstance2, areaInstance2);
+ initExtensionsInCHILD_AREA(childAreaInstance2);
+
+ // check initialization through PicoContainer
+ DependentObjectOne dependentObjectOne = (DependentObjectOne)Extensions.getRootArea().getExtensionPoint(TEST_DEPENDENT1_NAME).getExtension();
+ assertEquals(1, dependentObjectOne.getTestBeans().length);
+ DependentObjectTwo dependentObjectTwo = (DependentObjectTwo)Extensions.getArea(areaInstance1).getExtensionPoint(TEST_DEPENDENT2_NAME).getExtension();
+ assertSame(dependentObjectOne, dependentObjectTwo.getOne());
+ DependentObjectThree dependentObjectThree = (DependentObjectThree)Extensions.getArea(areaInstance1).getExtensionPoint(TEST_DEPENDENT3_NAME).getExtension();
+ assertSame(dependentObjectOne, dependentObjectThree.getOne());
+ assertSame(dependentObjectTwo, dependentObjectThree.getTwo());
+ assertTrue(Arrays.asList(dependentObjectThree.getTestBeans()).containsAll(Arrays.asList(dependentObjectOne.getTestBeans())));
+
+ // check PicoContainers
+ assertTrue(Extensions.getRootArea().getPicoContainer().getComponentInstances().contains(dependentObjectOne));
+ assertTrue(Extensions.getArea(areaInstance1).getPicoContainer().getComponentInstances().contains(dependentObjectTwo));
+ assertTrue(Extensions.getArea(areaInstance1).getPicoContainer().getComponentInstances().contains(dependentObjectThree));
+ assertFalse(Extensions.getArea(areaInstance2).getPicoContainer().getComponentInstances().contains(dependentObjectThree));
+
+ assertTrue(Extensions.getRootArea().getPluginContainer(PLUGIN_NAME).getComponentInstances().contains(dependentObjectOne));
+ assertFalse(Extensions.getRootArea().getPluginContainer(PLUGIN_NAME_2).getComponentInstances().contains(dependentObjectOne));
+ assertTrue(Extensions.getArea(areaInstance1).getPluginContainer(PLUGIN_NAME).getComponentInstances().contains(dependentObjectTwo));
+ assertFalse(Extensions.getArea(areaInstance1).getPluginContainer(PLUGIN_NAME_2).getComponentInstances().contains(dependentObjectTwo));
+ assertTrue(Extensions.getArea(areaInstance1).getPluginContainer(PLUGIN_NAME_2).getComponentInstances().contains(dependentObjectThree));
+
+ // check area inheritance
+ DependentObjectThree dependentChild1 = (DependentObjectThree)Extensions.getArea(childAreaInstance1).getExtensionPoint(TEST_DEPENDENT_CHILD_NAME).getExtension();
+ DependentObjectThree dependentChild2 = (DependentObjectThree)Extensions.getArea(childAreaInstance2).getExtensionPoint(TEST_DEPENDENT_CHILD_NAME).getExtension();
+ assertSame(dependentObjectTwo, dependentChild1.getTwo());
+ assertNotSame(dependentObjectTwo, dependentChild2.getTwo());
+
+ // Check extensions
+ assertNotSame(Extensions.getArea(areaInstance1).getExtensionPoint("the.test.plugin.extensionPoint4area").getExtensions()[0],
+ Extensions.getArea(areaInstance2).getExtensionPoint("the.test.plugin.extensionPoint4area").getExtensions()[0]);
+
+ XMLTestBean ownExtension = new XMLTestBean();
+ ownExtension.setProp1(54321);
+ Extensions.getArea(areaInstance1).getExtensionPoint("the.test.plugin.extensionPoint4area").registerExtension(ownExtension);
+ ExtensionPoint ep = Extensions.getArea(areaInstance2).getExtensionPoint("the.test.plugin.extensionPoint4area");
+ ep.unregisterExtension(ep.getExtension());
+ ep.unregisterExtension(ep.getExtension());
+ assertEquals(3, Extensions.getArea(areaInstance1).getExtensionPoint("the.test.plugin.extensionPoint4area").getExtensions().length);
+ assertEquals(54321, ((XMLTestBean)Extensions.getArea(areaInstance1).getExtensionPoint("the.test.plugin.extensionPoint4area").getExtensions()[2]).getProp1());
+ assertEquals(0, Extensions.getArea(areaInstance2).getExtensionPoint("the.test.plugin.extensionPoint4area").getExtensions().length);
+ assertEquals(2, Extensions.getArea(areaInstance3).getExtensionPoint("the.test.plugin.extensionPoint4area").getExtensions().length);
+ }
+
+ private void initExtensionsInCHILD_AREA(final MyAreaInstance childAreaInstance1) {
+ initExtensionPoints(PLUGIN_NAME, EXTENSION_POINTS_4_CHILD_AREA, childAreaInstance1);
+ initExtensions(EXTENSIONS_4_CHILD_AREA, childAreaInstance1);
+ }
+
+ private void initExtensionsInAREA(final AreaInstance areaInstance1) {
+ initExtensionPoints(PLUGIN_NAME, EXTENSION_POINTS_4_AREA, areaInstance1);
+ initExtensionPoints(PLUGIN_NAME_2, EXTENSION_POINTS_4_AREA_2, areaInstance1);
+ initExtensions(EXTENSIONS_4_AREA, areaInstance1);
+ initExtensions(EXTENSIONS_4_AREA_2, areaInstance1);
+ initExtensions(EXTENSIONS_4_AREA_2_PLUS, areaInstance1);
+ }
+
+ private void checkAreaInitialized(AreaInstance areaInstance) {
+ assertNotNull(Extensions.getArea(areaInstance).getExtensionPoint("the.test.plugin.extensionPoint4area").getExtension());
+ assertEquals(2, Extensions.getArea(areaInstance).getExtensionPoint("the.test.plugin.extensionPoint4area").getExtensions().length);
+ assertTrue(Extensions.getArea(areaInstance).hasExtensionPoint("another.test.plugin.anotherTestEP4area"));
+ }
+
+ private void initExtensionPoints(String pluginName, String data, AreaInstance instance) {
+ final Element element = ExtensionComponentAdapterTest.readElement(data);
+ for (Iterator iterator = element.getChildren().iterator(); iterator.hasNext();) {
+ Element child = (Element)iterator.next();
+ Extensions.getArea(instance).registerExtensionPoint(pluginName, child);
+ }
+ }
+
+ private void initExtensions(String data, AreaInstance instance) {
+ final Element element = ExtensionComponentAdapterTest.readElement(data);
+ for (Iterator iterator = element.getChildren().iterator(); iterator.hasNext();) {
+ Element child = (Element)iterator.next();
+ Extensions.getArea(instance).registerExtension(element.getNamespaceURI(), child);
+ }
+ }
+
+ private static class MyAreaInstance implements AreaInstance {}
+}
diff --git a/extensions/testSource/com/intellij/openapi/extensions/impl/NonCreatableClass.java b/extensions/testSource/com/intellij/openapi/extensions/impl/NonCreatableClass.java
new file mode 100644
index 000000000000..1c04a0374f2a
--- /dev/null
+++ b/extensions/testSource/com/intellij/openapi/extensions/impl/NonCreatableClass.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
+ * Use is subject to license terms.
+ */
+package com.intellij.openapi.extensions.impl;
+
+/**
+ * @author Alexander Kireyev
+ */
+public class NonCreatableClass {
+ static {
+ if (true) {
+ throw new RuntimeException("Cannot be created");
+ }
+ }
+
+ public NonCreatableClass() {
+ throw new RuntimeException("Cannot be created");
+ }
+}
diff --git a/extensions/testSource/com/intellij/openapi/extensions/impl/XMLTestBean.java b/extensions/testSource/com/intellij/openapi/extensions/impl/XMLTestBean.java
new file mode 100644
index 000000000000..5de9b4d99de1
--- /dev/null
+++ b/extensions/testSource/com/intellij/openapi/extensions/impl/XMLTestBean.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
+ * Use is subject to license terms.
+ */
+package com.intellij.openapi.extensions.impl;
+
+import com.intellij.openapi.extensions.PluginAware;
+
+import java.util.Collection;
+
+/**
+ * @author Alexander Kireyev
+ */
+public class XMLTestBean implements PluginAware {
+ private boolean myOtherProperty;
+ private int myProp1;
+ private Object myProp2;
+ private Collection myCollectionProperty;
+ private String myPluginName;
+
+ public XMLTestBean() {
+ }
+
+ public XMLTestBean(Collection aCollectionProperty, boolean aOtherProperty, int aProp1) {
+ myCollectionProperty = aCollectionProperty;
+ myOtherProperty = aOtherProperty;
+ myProp1 = aProp1;
+ }
+
+ public boolean isOtherProperty() {
+ return myOtherProperty;
+ }
+
+ public void setOtherProperty(boolean otherProperty) {
+ myOtherProperty = otherProperty;
+ }
+
+ public int getProp1() {
+ return myProp1;
+ }
+
+ public void setProp1(int prop1) {
+ myProp1 = prop1;
+ }
+
+ public Object getProp2() {
+ return myProp2;
+ }
+
+ public void setProp2(Object prop2) {
+ myProp2 = prop2;
+ }
+
+ public Collection getCollectionProperty() {
+ return myCollectionProperty;
+ }
+
+ public void setCollectionProperty(Collection collectionProperty) {
+ myCollectionProperty = collectionProperty;
+ }
+
+ public void setPluginName(String pluginName) {
+ myPluginName = pluginName;
+ }
+
+ public String getPluginName() {
+ return myPluginName;
+ }
+}