mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
dom.implementationClass EP
This commit is contained in:
+14
@@ -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,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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user