diff --git a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPoint.java b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPoint.java index 2f7b8912d670..ddf639d03c84 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPoint.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPoint.java @@ -25,6 +25,9 @@ public interface ExtensionPoint { String getName(); AreaInstance getArea(); + /** + * @deprecated use {@link #getClassName()} instead + */ String getBeanClassName(); void registerExtension(@NotNull T extension); @@ -46,4 +49,10 @@ public interface ExtensionPoint { void reset(); Class getExtensionClass(); + + Kind getKind(); + + String getClassName(); + + enum Kind {INTERFACE, BEAN_CLASS} } diff --git a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionsArea.java b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionsArea.java index 5e6f5d4bb3e0..3f31a2e8aecf 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionsArea.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionsArea.java @@ -27,6 +27,7 @@ import java.util.List; */ public interface ExtensionsArea { void registerExtensionPoint(@NonNls String extensionPointName, String extensionPointBeanClass); + void registerExtensionPoint(@NonNls String extensionPointName, String extensionPointBeanClass, ExtensionPoint.Kind kind); void unregisterExtensionPoint(@NonNls String extensionPointName); boolean hasExtensionPoint(@NonNls String extensionPointName); diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java index baba63bd3414..ec20d1422339 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java @@ -39,7 +39,8 @@ public class ExtensionPointImpl implements ExtensionPoint { private final AreaInstance myArea; private final String myName; - private final String myBeanClassName; + private final String myClassName; + private final Kind myKind; private final List myExtensions = new ArrayList(); private volatile T[] myExtensionsCache; @@ -54,13 +55,15 @@ public class ExtensionPointImpl implements ExtensionPoint { private Class myExtensionClass; public ExtensionPointImpl(String name, - String beanClassName, + String className, + Kind kind, ExtensionsAreaImpl owner, AreaInstance area, LogProvider logger, PluginDescriptor descriptor) { myName = name; - myBeanClassName = beanClassName; + myClassName = className; + myKind = kind; myOwner = owner; myArea = area; myLogger = logger; @@ -76,7 +79,17 @@ public class ExtensionPointImpl implements ExtensionPoint { } public String getBeanClassName() { - return myBeanClassName; + return myClassName; + } + + @Override + public String getClassName() { + return myClassName; + } + + @Override + public Kind getKind() { + return myKind; } public void registerExtension(@NotNull T extension) { @@ -322,8 +335,8 @@ public class ExtensionPointImpl implements ExtensionPoint { ClassLoader pluginClassLoader = myDescriptor.getPluginClassLoader(); //noinspection unchecked myExtensionClass = extensionClass = pluginClassLoader == null - ? (Class)Class.forName(myBeanClassName) - : (Class)Class.forName(myBeanClassName, true, pluginClassLoader); + ? (Class)Class.forName(myClassName) + : (Class)Class.forName(myClassName, true, pluginClassLoader); } catch (ClassNotFoundException e) { throw new RuntimeException(e); diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java index 9575048d6c30..7cde8f3213f5 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java @@ -23,6 +23,7 @@ import org.jdom.Element; import org.jdom.Namespace; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.TestOnly; import org.picocontainer.MutablePicoContainer; @@ -103,18 +104,36 @@ public class ExtensionsAreaImpl implements ExtensionsArea { public void registerExtensionPoint(PluginDescriptor pluginDescriptor, Element extensionPointElement) { assert pluginDescriptor.getPluginId() != null; + final String pluginId = pluginDescriptor.getPluginId().getIdString(); String epName = extensionPointElement.getAttributeValue("qualifiedName"); if (epName == null) { - epName = pluginDescriptor.getPluginId().getIdString() + '.' + extensionPointElement.getAttributeValue("name"); + final String name = extensionPointElement.getAttributeValue("name"); + if (name == null) { + throw new RuntimeException("'name' attribute not specified for extension point in '" + pluginId + "' plugin"); + } + epName = pluginId + '.' + name; } - String className = extensionPointElement.getAttributeValue("beanClass"); - if (className == null) { - className = extensionPointElement.getAttributeValue("interface"); + + String beanClassName = extensionPointElement.getAttributeValue("beanClass"); + String interfaceClassName = extensionPointElement.getAttributeValue("interface"); + if (beanClassName == null && interfaceClassName == null) { + throw new RuntimeException("Neither 'beanClass' nor 'interface' attribute is specified for extension point '" + epName + "' in '" + pluginId + "' plugin"); } - if (className == null) { - throw new RuntimeException("No class specified for extension point: " + epName); + if (beanClassName != null && interfaceClassName != null) { + throw new RuntimeException("Both 'beanClass' and 'interface' attributes are specified for extension point '" + epName + "' in '" + pluginId + "' plugin"); } - registerExtensionPoint(epName, className, pluginDescriptor); + + ExtensionPoint.Kind kind; + String className; + if (interfaceClassName != null) { + className = interfaceClassName; + kind = ExtensionPoint.Kind.INTERFACE; + } + else { + className = beanClassName; + kind = ExtensionPoint.Kind.BEAN_CLASS; + } + registerExtensionPoint(epName, className, pluginDescriptor, kind); } public void registerExtension(final String pluginName, final Element extensionElement) { @@ -125,16 +144,19 @@ public class ExtensionsAreaImpl implements ExtensionsArea { final PluginId pluginId = pluginDescriptor.getPluginId(); String epName = extractEPName(extensionElement); - String implClass = extensionElement.getAttributeValue("implementation"); ExtensionComponentAdapter adapter; final PicoContainer container = getPluginContainer(pluginId.getIdString()); - if (implClass != null) { + final ExtensionPoint extensionPoint = getExtensionPoint(epName); + if (extensionPoint.getKind() == ExtensionPoint.Kind.INTERFACE) { + String implClass = extensionElement.getAttributeValue("implementation"); + if (implClass == null) { + throw new RuntimeException("'implementation' attribute not specified for '" + epName + "' extension in '" + pluginId.getIdString() + "' plugin"); + } adapter = new ExtensionComponentAdapter(implClass, extensionElement, container, pluginDescriptor, shouldDeserializeInstance(extensionElement)); } else { - final ExtensionPoint extensionPoint = getExtensionPoint(epName); - adapter = new ExtensionComponentAdapter(extensionPoint.getBeanClassName(), extensionElement, container, pluginDescriptor, true); + adapter = new ExtensionComponentAdapter(extensionPoint.getClassName(), extensionElement, container, pluginDescriptor, true); } myExtensionElement2extension.put(extensionElement, adapter); internalGetPluginContainer().registerComponent(adapter); @@ -276,10 +298,22 @@ public class ExtensionsAreaImpl implements ExtensionsArea { } public void registerExtensionPoint(final String extensionPointName, String extensionPointBeanClass) { - registerExtensionPoint(extensionPointName, extensionPointBeanClass, new UndefinedPluginDescriptor()); + registerExtensionPoint(extensionPointName, extensionPointBeanClass, ExtensionPoint.Kind.INTERFACE); + } + + @Override + public void registerExtensionPoint(@NonNls String extensionPointName, String extensionPointBeanClass, ExtensionPoint.Kind kind) { + registerExtensionPoint(extensionPointName, extensionPointBeanClass, new UndefinedPluginDescriptor(), kind); } public void registerExtensionPoint(final String extensionPointName, String extensionPointBeanClass, PluginDescriptor descriptor) { + registerExtensionPoint(extensionPointName, extensionPointBeanClass, descriptor, ExtensionPoint.Kind.INTERFACE); + } + + private void registerExtensionPoint(final String extensionPointName, + String extensionPointBeanClass, + PluginDescriptor descriptor, + ExtensionPoint.Kind kind) { if (hasExtensionPoint(extensionPointName)) { if (DEBUG_REGISTRATION) { final ExtensionPointImpl oldEP = getExtensionPoint(extensionPointName); @@ -290,7 +324,7 @@ public class ExtensionsAreaImpl implements ExtensionsArea { throw new RuntimeException("Duplicate registration for EP: " + extensionPointName); } - registerExtensionPoint(new ExtensionPointImpl(extensionPointName, extensionPointBeanClass, this, myAreaInstance, myLogger, descriptor)); + registerExtensionPoint(new ExtensionPointImpl(extensionPointName, extensionPointBeanClass, kind, this, myAreaInstance, myLogger, descriptor)); } public void registerExtensionPoint(final ExtensionPointImpl extensionPoint) { diff --git a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java index 07674ae7e41f..96112b912caa 100644 --- a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java +++ b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java @@ -26,11 +26,11 @@ public class ExtensionPointImplTest extends TestCase { public void testCreate() { ExtensionPointImpl extensionPoint = buildExtensionPoint(); assertEquals(ExtensionsImplTest.EXTENSION_POINT_NAME_1, extensionPoint.getName()); - assertEquals(Integer.class.getName(), extensionPoint.getBeanClassName()); + assertEquals(Integer.class.getName(), extensionPoint.getClassName()); } private ExtensionPointImpl buildExtensionPoint() { - return new ExtensionPointImpl(ExtensionsImplTest.EXTENSION_POINT_NAME_1, Integer.class.getName(), buildExtensionArea(), null, new Extensions.SimpleLogProvider(), new UndefinedPluginDescriptor()); + return new ExtensionPointImpl(ExtensionsImplTest.EXTENSION_POINT_NAME_1, Integer.class.getName(), ExtensionPoint.Kind.INTERFACE, buildExtensionArea(), null, new Extensions.SimpleLogProvider(), new UndefinedPluginDescriptor()); } private ExtensionsAreaImpl buildExtensionArea() { @@ -50,7 +50,7 @@ public class ExtensionPointImplTest extends TestCase { public void testRegisterUnregister_Extension() { final AreaInstance area = new AreaInstance() {}; - final ExtensionPointImpl extensionPoint = new ExtensionPointImpl("an.extension.point", Object.class.getName(), buildExtensionArea(), area, new Extensions.SimpleLogProvider(), new UndefinedPluginDescriptor()); + final ExtensionPointImpl extensionPoint = new ExtensionPointImpl("an.extension.point", Object.class.getName(), ExtensionPoint.Kind.INTERFACE, buildExtensionArea(), area, new Extensions.SimpleLogProvider(), new UndefinedPluginDescriptor()); final boolean[] flags = new boolean[2]; Extension extension = new Extension() { diff --git a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsAreaTest.java b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsAreaTest.java index b7e6f587f0a4..d89abfea59fd 100644 --- a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsAreaTest.java +++ b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsAreaTest.java @@ -16,6 +16,7 @@ package com.intellij.openapi.extensions.impl; +import com.intellij.openapi.extensions.ExtensionPoint; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.extensions.AreaPicoContainer; import junit.framework.TestCase; @@ -51,7 +52,7 @@ public class ExtensionsAreaTest extends TestCase { } public void testNoCreateOnUnregisterElement() { - myExtensionsArea.registerExtensionPoint("test.ep", TestClass.class.getName()); + myExtensionsArea.registerExtensionPoint("test.ep", TestClass.class.getName(), ExtensionPoint.Kind.BEAN_CLASS); final Element element = ExtensionComponentAdapterTest.readElement(""); TestClass.ourCreationCount = 0; myExtensionsArea.registerExtension("test", element); @@ -61,7 +62,7 @@ public class ExtensionsAreaTest extends TestCase { } public void testNoCreateOnUnregisterExisting() { - myExtensionsArea.registerExtensionPoint("test.ep", TestClass.class.getName()); + myExtensionsArea.registerExtensionPoint("test.ep", TestClass.class.getName(), ExtensionPoint.Kind.BEAN_CLASS); final Element element = ExtensionComponentAdapterTest.readElement(""); TestClass.ourCreationCount = 0; myExtensionsArea.registerExtension("test", element); diff --git a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsImplTest.java b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsImplTest.java index 8802d7c2be97..bf16ffaaf0ab 100644 --- a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsImplTest.java +++ b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsImplTest.java @@ -256,7 +256,7 @@ public class ExtensionsImplTest extends TestCase { public void testExtensionsNamespaces() { ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer(), new Extensions.SimpleLogProvider()); - extensionsArea.registerExtensionPoint("plugin.ep1", TestExtensionClassOne.class.getName()); + extensionsArea.registerExtensionPoint("plugin.ep1", TestExtensionClassOne.class.getName(), ExtensionPoint.Kind.BEAN_CLASS); extensionsArea.registerExtension("plugin", ExtensionComponentAdapterTest.readElement( "3")); extensionsArea.registerExtension("plugin", ExtensionComponentAdapterTest.readElement( @@ -273,7 +273,7 @@ public class ExtensionsImplTest extends TestCase { public void testExtensionsWithOrdering() { ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer(), new Extensions.SimpleLogProvider()); - extensionsArea.registerExtensionPoint("ep1", TestExtensionClassOne.class.getName()); + extensionsArea.registerExtensionPoint("ep1", TestExtensionClassOne.class.getName(), ExtensionPoint.Kind.BEAN_CLASS); extensionsArea.registerExtension("", ExtensionComponentAdapterTest.readElement( "3")); extensionsArea.registerExtension("", ExtensionComponentAdapterTest.readElement( @@ -290,7 +290,7 @@ public class ExtensionsImplTest extends TestCase { public void testExtensionsWithOrderingUpdate() { ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer(), new Extensions.SimpleLogProvider()); - extensionsArea.registerExtensionPoint("ep1", TestExtensionClassOne.class.getName()); + extensionsArea.registerExtensionPoint("ep1", TestExtensionClassOne.class.getName(), ExtensionPoint.Kind.BEAN_CLASS); extensionsArea.registerExtension("", ExtensionComponentAdapterTest.readElement( "7")); extensionsArea.registerExtension("", ExtensionComponentAdapterTest.readElement( diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformLiteFixture.java b/platform/testFramework/src/com/intellij/testFramework/PlatformLiteFixture.java index d15516e363f4..2c6d018dc03e 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformLiteFixture.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformLiteFixture.java @@ -19,6 +19,7 @@ import com.intellij.mock.MockApplication; import com.intellij.mock.MockProject; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationManagerEx; +import com.intellij.openapi.extensions.ExtensionPoint; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.extensions.ExtensionsArea; @@ -27,6 +28,8 @@ import com.intellij.openapi.vfs.encoding.EncodingManagerImpl; import org.jetbrains.annotations.NotNull; import org.picocontainer.MutablePicoContainer; +import java.lang.reflect.Modifier; + /** * @author yole */ @@ -73,7 +76,8 @@ public abstract class PlatformLiteFixture extends UsefulTestCase { final Class aClass) { final String name = extensionPointName.getName(); if (!area.hasExtensionPoint(name)) { - area.registerExtensionPoint(name, aClass.getName()); + ExtensionPoint.Kind kind = aClass.isInterface() || (aClass.getModifiers() & Modifier.ABSTRACT) != 0 ? ExtensionPoint.Kind.INTERFACE : ExtensionPoint.Kind.BEAN_CLASS; + area.registerExtensionPoint(name, aClass.getName(), kind); } }