dom.implementationClass EP

This commit is contained in:
peter
2010-07-31 10:33:58 +01:00
parent 46b73abe54
commit fd7d091589
5 changed files with 79 additions and 13 deletions
@@ -15,6 +15,8 @@
*/
package com.intellij.openapi.extensions;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.Nullable;
import org.picocontainer.PicoContainer;
import org.picocontainer.defaults.ConstructorInjectionComponentAdapter;
import org.jetbrains.annotations.NotNull;
@@ -23,6 +25,7 @@ import org.jetbrains.annotations.NotNull;
* @author peter
*/
public abstract class AbstractExtensionPointBean implements PluginAware {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.extensions.AbstractExtensionPointBean");
protected PluginDescriptor myPluginDescriptor;
public final void setPluginDescriptor(PluginDescriptor pluginDescriptor) {
@@ -34,6 +37,17 @@ public abstract class AbstractExtensionPointBean implements PluginAware {
return (Class<T>)Class.forName(className, true, getLoaderForClass());
}
@Nullable
public final <T> Class<T> findClassNoExceptions(final String className) {
try {
return findClass(className);
}
catch (ClassNotFoundException e) {
LOG.error("Problem loading class " + className + " from plugin " + myPluginDescriptor.getPluginId().getIdString(), e);
return null;
}
}
public ClassLoader getLoaderForClass() {
return myPluginDescriptor == null ? getClass().getClassLoader() : myPluginDescriptor.getPluginClassLoader();
}
+3
View File
@@ -3,6 +3,9 @@
<extensionPoint name="dom.fileDescription"
interface="com.intellij.util.xml.DomFileDescription"/>
<extensionPoint name="dom.implementationClass"
interface="com.intellij.util.xml.impl.DomImplementationClassEP"/>
<extensionPoint name="dom.extender"
interface="com.intellij.util.xml.reflect.DomExtenderEP"/>
@@ -108,7 +108,7 @@ public class DomApplicationComponent {
}
public final void registerImplementation(Class<? extends DomElement> domElementClass, Class<? extends DomElement> implementationClass,
final Disposable parentDisposable) {
@Nullable final Disposable parentDisposable) {
myCachedImplementationClasses.registerImplementation(domElementClass, implementationClass, parentDisposable);
}
@@ -0,0 +1,30 @@
package com.intellij.util.xml.impl;
import com.intellij.openapi.extensions.AbstractExtensionPointBean;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.util.xmlb.annotations.Attribute;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
public class DomImplementationClassEP extends AbstractExtensionPointBean {
public static final ExtensionPointName<DomImplementationClassEP> EP_NAME = ExtensionPointName.create("com.intellij.dom.implementationClass");
@Attribute("interfaceClass")
public String interfaceName;
@Attribute("implementationClass")
public String implementationName;
@Nullable
public Class getInterfaceClass() {
return findClassNoExceptions(interfaceName);
}
@Nullable
public Class getImplementationClass() {
return findClassNoExceptions(implementationName);
}
}
@@ -19,13 +19,13 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.ReflectionCache;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.xml.DomReflectionUtil;
import com.intellij.util.xml.Implementation;
import gnu.trove.THashMap;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -43,7 +43,7 @@ class ImplementationClassCache {
};
private final Map<Class, Class> myImplementationClasses = new THashMap<Class, Class>();
private final MultiMap<String, DomImplementationClassEP> myImplementationClasses = new MultiMap<String, DomImplementationClassEP>();
private final ConcurrentFactoryMap<Class, Class> myCache = new ConcurrentFactoryMap<Class, Class>() {
@Nullable
protected Class create(final Class concreteInterface) {
@@ -57,25 +57,44 @@ class ImplementationClassCache {
}
};
private void findImplementationClassDFS(final Class concreteInterface, SortedSet<Class> results) {
Class aClass = myImplementationClasses.get(concreteInterface);
if (aClass != null) {
results.add(aClass);
ImplementationClassCache() {
for (DomImplementationClassEP ep : DomImplementationClassEP.EP_NAME.getExtensions()) {
myImplementationClasses.putValue(ep.interfaceName, ep);
}
else {
}
private void findImplementationClassDFS(final Class concreteInterface, SortedSet<Class> results) {
final Collection<DomImplementationClassEP> values = myImplementationClasses.get(concreteInterface.getName());
for (DomImplementationClassEP value : values) {
if (value.getInterfaceClass() == concreteInterface) {
results.add(value.getImplementationClass());
}
}
if (results.isEmpty()) {
for (final Class aClass1 : ReflectionCache.getInterfaces(concreteInterface)) {
findImplementationClassDFS(aClass1, results);
}
}
}
public final void registerImplementation(final Class domElementClass, Class implementationClass,
final Disposable parentDisposable) {
myImplementationClasses.put(domElementClass, implementationClass);
public final void registerImplementation(final Class domElementClass, final Class implementationClass,
@Nullable final Disposable parentDisposable) {
final DomImplementationClassEP ep = new DomImplementationClassEP() {
@Override
public Class getInterfaceClass() {
return domElementClass;
}
@Override
public Class getImplementationClass() {
return implementationClass;
}
};
myImplementationClasses.putValue(domElementClass.getName(), ep);
if (parentDisposable != null) {
Disposer.register(parentDisposable, new Disposable() {
public void dispose() {
myImplementationClasses.remove(domElementClass);
myImplementationClasses.remove(domElementClass.getName());
}
});
}