Extensions framework.

This commit is contained in:
Alexander Kireyev
2005-01-29 16:56:26 +03:00
parent 05d3bf56f1
commit d330f34cef
30 changed files with 2494 additions and 0 deletions

21
extensions/extensions.iml Normal file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4" relativePaths="true" type="JAVA_MODULE">
<component name="ModuleRootManager" />
<component name="NewModuleRootManager">
<output url="file://$MODULE_DIR$/classes/main" />
<exclude-output />
<output-test url="file://$MODULE_DIR$/classes/test" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/source" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/testSource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="XStream" level="project" />
<orderEntry type="library" exported="" name="JDOM" level="project" />
<orderEntry type="library" name="commons-collections" level="project" />
<orderEntry type="library" name="picocontainer" level="project" />
<orderEntryProperties />
</component>
</module>

View File

@@ -0,0 +1,11 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
/**
* @author akireyev
*/
public interface AreaInstance {
}

View File

@@ -0,0 +1,13 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
/**
* @author akireyev
*/
public interface AreaListener {
void areaCreated(String areaClass, AreaInstance areaInstance);
void areaDisposing(String areaClass, AreaInstance areaInstance);
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
/**
* @author AKireyev
*/
public class EPAvailabilityListenerExtension {
public static final String EXTENSION_POINT_NAME = "jetbrains.fabrique.framework.epAvailabilityListener";
private String myExtensionPointName;
private String myListenerClass;
public EPAvailabilityListenerExtension() {
}
public EPAvailabilityListenerExtension(String extensionPointName, String listenerClass) {
myExtensionPointName = extensionPointName;
myListenerClass = listenerClass;
}
public String getExtensionPointName() {
return myExtensionPointName;
}
public void setExtensionPointName(String extensionPointName) {
myExtensionPointName = extensionPointName;
}
public String getListenerClass() {
return myListenerClass;
}
public void setListenerClass(String listenerClass) {
myListenerClass = listenerClass;
}
}

View File

@@ -0,0 +1,15 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
/**
* @author kir
*
* An extension can implement this interface to get notifications when it is added/removed to {@link ExtensionPoint}
*/
public interface Extension {
void extensionAdded(ExtensionPoint extensionPoint);
void extensionRemoved(ExtensionPoint extensionPoint);
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
/**
* @author AKireyev
*/
public interface ExtensionPoint {
String getName();
AreaInstance getArea();
String getBeanClassName();
void registerExtension(Object extension);
void registerExtension(Object extension, LoadingOrder order);
Object[] getExtensions();
Object getExtension();
boolean hasExtension(Object extension);
void unregisterExtension(Object extension);
void addExtensionPointListener(ExtensionPointListener listener);
void removeExtensionPointListener(ExtensionPointListener extensionPointListener);
void reset();
Class getExtensionClass();
}

View File

@@ -0,0 +1,13 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
/**
* @author AKireyev
*/
public interface ExtensionPointAvailabilityListener {
void extensionPointRegistered(ExtensionPoint extensionPoint);
void extensionPointRemoved(ExtensionPoint extensionPoint);
}

View File

@@ -0,0 +1,10 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
public interface ExtensionPointListener {
void extensionAdded(Object extension);
void extensionRemoved(Object extension);
}

View File

@@ -0,0 +1,235 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl;
import org.apache.commons.collections.MultiHashMap;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
// todo: make default area instance a non-null object
public abstract class Extensions {
private static LogProvider ourLogger = new SimpleLogProvider();
public static final String AREA_LISTENER_EXTENSION_POINT = "jetbrains.fabrique.platform.areaListeners";
private static Map ourAreaClass2prototypeArea;
private static Map ourAreaInstance2area;
private static MultiHashMap ourAreaClass2instances;
private static Map ourAreaInstance2class;
private static Map ourAreaClass2Configuration;
public static ExtensionsArea getRootArea() {
return getArea(null);
}
public static ExtensionsArea getArea(AreaInstance areaInstance) {
init();
if (!ourAreaInstance2area.containsKey(areaInstance)) {
throw new IllegalArgumentException("No area instantiated for: " + areaInstance);
}
return (ExtensionsArea) ourAreaInstance2area.get(areaInstance);
}
public static Object[] getExtensions(String extensionPointName) {
return getExtensions(extensionPointName, null);
}
public static Object[] getExtensions(String extensionPointName, AreaInstance areaInstance) {
ExtensionsArea area = getArea(areaInstance);
assert area != null: "Unable to get area for " + areaInstance;
ExtensionPoint extensionPoint = area.getExtensionPoint(extensionPointName);
assert extensionPoint != null: "Unable to get extension point " + extensionPoint + " for " + areaInstance;
return extensionPoint.getExtensions();
}
private static void init() {
if (ourAreaInstance2area == null) {
ourAreaInstance2area = new HashMap();
ourAreaClass2prototypeArea = new HashMap();
ourAreaClass2instances = new MultiHashMap();
ourAreaInstance2class = new HashMap();
ourAreaClass2Configuration = new HashMap();
ExtensionsAreaImpl rootArea = new ExtensionsAreaImpl(null, null, null, ourLogger);
ourAreaInstance2area.put(null, rootArea);
ourAreaClass2prototypeArea.put(null, rootArea);
rootArea.registerExtensionPoint(AREA_LISTENER_EXTENSION_POINT, AreaListener.class.getName());
}
}
static void reset() {
ourAreaInstance2area = null;
ourAreaClass2instances = null;
ourAreaClass2prototypeArea = null;
ourAreaInstance2class = null;
}
public static void instantiateArea(String areaClass, AreaInstance areaInstance, AreaInstance parentAreaInstance) {
if (areaClass == null) {
throw new IllegalArgumentException("Should not try to instantiate the root area");
}
init();
if (!ourAreaClass2Configuration.containsKey(areaClass)) {
throw new IllegalArgumentException("Area class is not registered: " + areaClass);
}
if (ourAreaInstance2area.containsKey(areaInstance)) {
throw new IllegalArgumentException("Area already instantiated for: " + areaInstance);
}
ExtensionsArea parentArea = getArea(parentAreaInstance);
AreaClassConfiguration configuration = (AreaClassConfiguration)ourAreaClass2Configuration.get(areaClass);
if (!equals(parentArea.getAreaClass(), configuration.getParentClassName())) {
throw new IllegalArgumentException("Wrong parent area. Expected class: " + configuration.getParentClassName() + " actual class: " + parentArea.getAreaClass());
}
ExtensionsAreaImpl area = new ExtensionsAreaImpl(areaClass, areaInstance, parentArea.getPicoContainer(), ourLogger);
ourAreaInstance2area.put(areaInstance, area);
ourAreaClass2instances.put(areaClass, areaInstance);
ourAreaInstance2class.put(areaInstance, areaClass);
AreaListener[] listeners = getAreaListeners();
for (int i = 0; i < listeners.length; i++) {
AreaListener listener = listeners[i];
listener.areaCreated(areaClass, areaInstance);
}
}
private static AreaListener[] getAreaListeners() {
AreaListener[] listeners = (AreaListener[]) getRootArea().getExtensionPoint(AREA_LISTENER_EXTENSION_POINT).getExtensions();
return listeners;
}
public static void registerAreaClass(String areaClass, String parentAreaClass) {
init();
if (ourAreaClass2Configuration.containsKey(areaClass)) {
// allow duplicate area class registrations if they are the same - fixing duplicate registration in tests is much more trouble
AreaClassConfiguration configuration = (AreaClassConfiguration)ourAreaClass2Configuration.get(areaClass);
if (!equals(configuration.getParentClassName(), parentAreaClass)) {
throw new RuntimeException("Area class already registered: " + areaClass, ((AreaClassConfiguration)ourAreaClass2Configuration.get(areaClass)).getCreationPoint());
}
else {
return;
}
}
AreaClassConfiguration configuration = new AreaClassConfiguration(areaClass, parentAreaClass);
ourAreaClass2Configuration.put(areaClass, configuration);
}
public static void disposeArea(AreaInstance areaInstance) {
assert ourAreaInstance2area.containsKey(areaInstance);
if (areaInstance == null) {
throw new IllegalArgumentException("Cannot dispose root area");
}
AreaListener[] listeners = getAreaListeners();
String areaClass = (String) ourAreaInstance2class.get(areaInstance);
if (areaClass == null) {
throw new IllegalArgumentException("Area class is null (area never instantiated?). Instance: " + areaInstance);
}
try {
for (int i = 0; i < listeners.length; i++) {
listeners[i].areaDisposing(areaClass, areaInstance);
}
} finally {
ourAreaInstance2area.remove(areaInstance);
ourAreaClass2instances.remove(ourAreaInstance2class.remove(areaInstance), areaInstance);
ourAreaInstance2class.remove(areaInstance);
}
}
public static AreaInstance[] getAllAreas() {
init();
final Set keys = ourAreaInstance2area.keySet();
return (AreaInstance[]) keys.toArray(new AreaInstance[keys.size()]);
}
public static AreaInstance[] getAllAreas(String areaClass) {
Collection instances = (Collection) ourAreaClass2instances.get(areaClass);
if (instances != null) {
return (AreaInstance[]) instances.toArray(new AreaInstance[instances.size()]);
}
return new AreaInstance[0];
}
public static Object getAreaClass(AreaInstance areaInstance) {
if (areaInstance == null) return null;
assert ourAreaInstance2class.containsKey(areaInstance);
return ourAreaInstance2class.get(areaInstance);
}
public static void unregisterAreaClass(String areaClass) {
init();
assert ourAreaClass2Configuration.containsKey(areaClass) : "Area class is not registered: " + areaClass;
ourAreaClass2Configuration.remove(areaClass);
}
private static boolean equals(Object object1, Object object2) {
if (object1 == object2) {
return true;
}
if ((object1 == null) || (object2 == null)) {
return false;
}
return object1.equals(object2);
}
public static void setLogProvider(LogProvider logProvider) {
ourLogger = logProvider;
}
private static class AreaClassConfiguration {
private String myClassName;
private String myParentClassName;
private Throwable myCreationPoint;
AreaClassConfiguration(String className, String parentClassName) {
myCreationPoint = new Throwable();
myClassName = className;
myParentClassName = parentClassName;
}
public Throwable getCreationPoint() {
return myCreationPoint;
}
public String getClassName() {
return myClassName;
}
public String getParentClassName() {
return myParentClassName;
}
}
public static class SimpleLogProvider implements LogProvider {
public void error(String message) {
new Throwable(message).printStackTrace();
}
public void error(String message, Throwable t) {
System.err.println(message);
t.printStackTrace();
}
public void error(Throwable t) {
t.printStackTrace();
}
public void warn(String message) {
System.err.println(message);
}
public void warn(String message, Throwable t) {
System.err.println(message);
t.printStackTrace();
}
public void warn(Throwable t) {
t.printStackTrace();
}
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
import org.jdom.Element;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.PicoContainer;
/**
* @author AKireyev
*/
public interface ExtensionsArea {
void registerExtensionPoint(String extensionPointName, String extensionPointBeanClass);
void unregisterExtensionPoint(String extensionPointName);
boolean hasExtensionPoint(String extensionPointName);
ExtensionPoint getExtensionPoint(String extensionPointName);
ExtensionPoint[] getExtensionPoints();
void suspendInteractions();
void resumeInteractions();
void killPendingInteractions();
void addAvailabilityListener(String epName, ExtensionPointAvailabilityListener listener);
MutablePicoContainer getPicoContainer();
void registerExtensionPoint(String pluginName, Element extensionPointElement);
void registerExtension(String pluginName, Element extensionElement);
void unregisterExtensionPoint(String pluginName, Element extensionPointElement);
void unregisterExtension(String pluginName, Element extensionElement);
PicoContainer getPluginContainer(String pluginName);
String getAreaClass();
}

View File

@@ -0,0 +1,244 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
import org.jdom.Element;
import java.util.ArrayList;
import java.util.List;
/**
* @author Alexander Kireyev
*/
public abstract class LoadingOrder {
public static final LoadingOrder ANY = new LoadingOrder("ANY") {
int findPlace(Orderable[] orderables, int current) {
return DONT_CARE;
}
};
public static final LoadingOrder FIRST = new LoadingOrder("FIRST") {
int findPlace(Orderable[] orderables, int current) {
return SPECIAL;
}
};
public static final LoadingOrder LAST = new LoadingOrder("LAST") {
int findPlace(Orderable[] orderables, int current) {
return SPECIAL;
}
};
static final int DONT_CARE = -1;
static final int ACCEPTABLE = -2;
static final int SPECIAL = -3;
private final String myName; // for debug only
private static final String BEFORE_STR = "BEFORE:";
private static final String AFTER_STR = "AFTER:";
private LoadingOrder(String name) {
myName = name;
}
public String toString() {
return myName;
}
public static LoadingOrder before(final String id) {
return new BeforeLoadingOrder(id);
}
public static LoadingOrder after(final String id) {
return new AfterLoadingOrder(id);
}
abstract int findPlace(Orderable[] orderables, int current);
public static void sort(Orderable[] orderables) {
Orderable first = null;
Orderable last = null;
List other = new ArrayList();
for (int i = 0; i < orderables.length; i++) {
Orderable orderable = orderables[i];
if (orderable.getOrder() == FIRST) {
if (first != null) {
throw new SortingException("More than one 'first' element", new Element[] {first.getDescribingElement(), orderable.getDescribingElement()});
}
first = orderable;
}
else if (orderable.getOrder() == LAST) {
if (last != null) {
throw new SortingException("More than one 'last' element", new Element[] {last.getDescribingElement(), orderable.getDescribingElement()});
}
last = orderable;
}
else {
other.add(orderable);
}
}
List result = new ArrayList();
if (first != null) {
result.add(first);
}
result.addAll(other);
if (last != null) {
result.add(last);
}
assert result.size() == orderables.length;
Orderable[] presorted = (Orderable[]) result.toArray(new Orderable[result.size()]);
int swapCount = 0;
int maxSwaps = presorted.length * presorted.length;
for (int i = 0; i < presorted.length; i++) {
Orderable orderable = presorted[i];
LoadingOrder order = orderable.getOrder();
int place = order.findPlace(presorted, i);
if (place == DONT_CARE || place == ACCEPTABLE || place == SPECIAL) {
continue;
}
if (place == 0 && presorted[0].getOrder() == FIRST) {
throw new SortingException("Element attempts to go before the specified first", new Element[] {orderable.getDescribingElement(), presorted[0].getDescribingElement()});
}
if (place == presorted.length - 1 && presorted[presorted.length - 1].getOrder() == LAST) {
throw new SortingException("Element attempts to go after the specified last", new Element[] {orderable.getDescribingElement(), presorted[presorted.length - 1].getDescribingElement()});
}
moveTo(presorted, i, place);
if (i > place) {
i = place;
}
else {
i--;
}
swapCount++;
if (swapCount > maxSwaps) {
List allElements = new ArrayList();
for (int j = 0; j < presorted.length; j++) {
allElements.add(presorted[j].getDescribingElement());
}
throw new SortingException("Could not satisfy sorting requirements", (Element[]) allElements.toArray(new Element[allElements.size()]));
}
}
System.arraycopy(presorted, 0, orderables, 0, presorted.length);
}
private static void moveTo(Orderable[] orderables, int from, int to) {
if (to == from) return;
Orderable movedOrderable = orderables[from];
if (to > from) {
for (int i = from; i < to; i++) {
orderables[i] = orderables[i + 1];
}
}
else {
for (int i = from; i > to; i--) {
orderables[i] = orderables[i - 1];
}
}
orderables[to] = movedOrderable;
}
public static LoadingOrder readOrder(String orderAttr) {
if (orderAttr != null) {
if ("FIRST".equalsIgnoreCase(orderAttr)) return FIRST;
if ("LAST".equalsIgnoreCase(orderAttr)) return LAST;
if ("ANY".equalsIgnoreCase(orderAttr)) return ANY;
if (orderAttr.toUpperCase().startsWith(BEFORE_STR)) {
return before(orderAttr.substring(BEFORE_STR.length()));
}
if (orderAttr.toUpperCase().startsWith(AFTER_STR)) {
return after(orderAttr.substring(AFTER_STR.length()));
}
}
return ANY;
}
private static class BeforeLoadingOrder extends LoadingOrder {
private final String myId;
public BeforeLoadingOrder(String id) {
super(LoadingOrder.BEFORE_STR + id);
myId = id;
}
int findPlace(Orderable[] orderables, int current) {
for (int i = 0; i < orderables.length; i++) {
Orderable orderable = orderables[i];
String orderId = orderable.getOrderId();
if (myId.equals(orderId)) {
if (current < i) {
return ACCEPTABLE;
}
else {
return i;
}
}
}
return DONT_CARE;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BeforeLoadingOrder)) return false;
final BeforeLoadingOrder beforeLoadingOrder = (BeforeLoadingOrder) o;
if (!myId.equals(beforeLoadingOrder.myId)) return false;
return true;
}
public int hashCode() {
return myId.hashCode();
}
}
private static class AfterLoadingOrder extends LoadingOrder {
private final String myId;
public AfterLoadingOrder(String id) {
super(LoadingOrder.AFTER_STR + id);
myId = id;
}
int findPlace(Orderable[] orderables, int current) {
for (int i = 0; i < orderables.length; i++) {
Orderable orderable = orderables[i];
String orderId = orderable.getOrderId();
if (myId.equals(orderId)) {
if (current > i) {
return ACCEPTABLE;
}
else {
return i;
}
}
}
return DONT_CARE;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AfterLoadingOrder)) return false;
final AfterLoadingOrder afterLoadingOrder = (AfterLoadingOrder) o;
if (!myId.equals(afterLoadingOrder.myId)) return false;
return true;
}
public int hashCode() {
return myId.hashCode();
}
}
public interface Orderable {
String getOrderId();
LoadingOrder getOrder();
Element getDescribingElement();
}
}

View File

@@ -0,0 +1,18 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
/**
* @author Alexander Kireyev
*/
public interface LogProvider {
void error(String message);
void error(String message, Throwable t);
void error(Throwable t);
void warn(String message);
void warn(String message, Throwable t);
void warn(Throwable t);
}

View File

@@ -0,0 +1,12 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
/**
* @author akireyev
*/
public interface PluginAware {
void setPluginName(String pluginName);
}

View File

@@ -0,0 +1,14 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
import com.thoughtworks.xstream.XStream;
/**
* @author AKireyev
*/
public interface ReaderConfigurator {
void configureReader(XStream xstream);
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions;
import org.jdom.Element;
/**
* @author Alexander Kireyev
*/
public class SortingException extends RuntimeException {
private Element[] myConflictingElements;
public SortingException(String message, Element[] conflictingElements) {
super(message);
myConflictingElements = conflictingElements;
}
public Element[] getConflictingElements() {
return myConflictingElements;
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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.AreaInstance;
/**
* @author akireyev
*/
class AreaDescriptor {
private String myAreaClass;
private AreaInstance myInstance;
public AreaDescriptor(String aClass, AreaInstance instance) {
myAreaClass = aClass;
myInstance = instance;
}
public String getAreaClass() {
return myAreaClass;
}
public AreaInstance getAreaInstance() {
return myInstance;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AreaDescriptor)) return false;
final AreaDescriptor areaDescriptor = (AreaDescriptor) o;
if (myAreaClass != null ? !myAreaClass.equals(areaDescriptor.myAreaClass) : areaDescriptor.myAreaClass != null) return false;
if (myInstance != null ? !myInstance.equals(areaDescriptor.myInstance) : areaDescriptor.myInstance != null) return false;
return true;
}
public int hashCode() {
int result;
result = (myAreaClass != null ? myAreaClass.hashCode() : 0);
result = 29 * result + (myInstance != null ? myInstance.hashCode() : 0);
return result;
}
}

View File

@@ -0,0 +1,175 @@
/*
* 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 org.picocontainer.MutablePicoContainer;
import org.picocontainer.PicoContainer;
import org.picocontainer.ComponentAdapter;
import org.picocontainer.Parameter;
import org.picocontainer.defaults.DefaultPicoContainer;
import org.picocontainer.defaults.AmbiguousComponentResolutionException;
import org.picocontainer.defaults.AbstractPicoVisitor;
import org.picocontainer.alternatives.AbstractDelegatingMutablePicoContainer;
import java.util.*;
/**
* @author Alexander Kireyev
*/
public class AreaPicoContainer extends AbstractDelegatingMutablePicoContainer implements MutablePicoContainer {
private ExtensionsAreaImpl myArea;
public AreaPicoContainer(PicoContainer parentPicoContainer, ExtensionsAreaImpl area) {
super(new DefaultPicoContainer(parentPicoContainer));
myArea = area;
}
public ComponentAdapter getComponentAdapter(final Object componentKey) {
final ComponentAdapter[] result = new ComponentAdapter[] { null };
accept(new EmptyPicoVisitor() {
public void visitComponentAdapter(ComponentAdapter componentAdapter) {
if (componentKey.equals(componentAdapter.getComponentKey())) {
result[0] = componentAdapter;
}
}
});
if (result[0] != null) {
return result[0];
}
else {
if (getParent() != null) {
return getParent().getComponentAdapter(componentKey);
}
else {
return null;
}
}
}
public List getComponentInstances() {
final List result = new ArrayList();
accept(new EmptyPicoVisitor() {
public void visitContainer(PicoContainer pico) {
result.addAll(pico.getComponentInstances());
}
});
return result;
}
public List getComponentInstancesOfType(final Class type) {
final List result = new ArrayList();
accept(new EmptyPicoVisitor() {
public void visitContainer(PicoContainer pico) {
result.addAll(pico.getComponentInstancesOfType(type));
}
});
return result;
}
public Object getComponentInstanceOfType(Class componentType) {
List instances = getComponentInstancesOfType(componentType);
if (instances.size() == 0) {
return null;
}
else if (instances.size() == 1) {
return instances.get(0);
}
else {
throw new AmbiguousComponentResolutionException(componentType, instances.toArray(new Object[instances.size()]));
}
}
public Object getComponentInstance(final Object componentKey) {
if (getParent() != null) {
Object parentInstance = getParent().getComponentInstance(componentKey);
if (parentInstance != null) {
return parentInstance;
}
}
final Object[] result = new Object[] { null };
accept(new EmptyPicoVisitor() {
public void visitContainer(PicoContainer pico) {
final boolean[] found = new boolean[] { false };
pico.accept(new EmptyPicoVisitor() {
public void visitComponentAdapter(ComponentAdapter componentAdapter) {
if (componentKey.equals(componentAdapter.getComponentKey())) {
found[0] = true;
}
}
});
if (!found[0]) {
return;
}
Object componentInstance = pico.getComponentInstance(componentKey);
if (componentInstance != null) {
result[0] = componentInstance;
}
}
});
return result[0];
}
public ComponentAdapter getComponentAdapterOfType(Class componentType) {
List adapters = getComponentAdaptersOfType(componentType);
if (adapters.size() == 0) {
return null;
}
else if (adapters.size() == 1) {
return (ComponentAdapter) adapters.get(0);
}
else {
Class[] foundClasses = new Class[adapters.size()];
for (int i = 0; i < foundClasses.length; i++) {
ComponentAdapter componentAdapter = (ComponentAdapter) adapters.get(i);
foundClasses[i] = componentAdapter.getComponentImplementation();
}
throw new AmbiguousComponentResolutionException(componentType, foundClasses);
}
}
public Collection getComponentAdapters() {
final List result = new ArrayList();
if (getParent() != null) {
result.addAll(getParent().getComponentAdapters());
}
accept(new EmptyPicoVisitor() {
public void visitComponentAdapter(ComponentAdapter componentAdapter) {
result.add(componentAdapter);
}
});
return result;
}
public List getComponentAdaptersOfType(final Class componentType) {
final List result = new ArrayList();
if (getParent() != null) {
result.addAll(getParent().getComponentAdaptersOfType(componentType));
}
accept(new EmptyPicoVisitor() {
public void visitComponentAdapter(ComponentAdapter componentAdapter) {
if (componentType.isAssignableFrom(componentAdapter.getComponentImplementation())) {
result.add(componentAdapter);
}
}
});
return result;
}
public MutablePicoContainer makeChildContainer() {
throw new UnsupportedOperationException("Method makeChildContainer() is not implemented");
}
private abstract class EmptyPicoVisitor extends AbstractPicoVisitor {
public void visitContainer(PicoContainer pico) {
}
public void visitComponentAdapter(ComponentAdapter componentAdapter) {
}
public void visitParameter(Parameter parameter) {
}
}
}

View File

@@ -0,0 +1,29 @@
/*
* 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.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import org.jdom.Element;
/**
* @author Alexander Kireyev
*/
public class ElementConverter implements Converter {
public boolean canConvert(Class aClass) {
return Element.class.isAssignableFrom(aClass);
}
public void marshal(Object object, HierarchicalStreamWriter hierarchicalStreamWriter, MarshallingContext marshallingContext) {
throw new UnsupportedOperationException("This method is not yet implemented");
}
public Object unmarshal(HierarchicalStreamReader hierarchicalStreamReader, UnmarshallingContext unmarshallingContext) {
return hierarchicalStreamReader.peekUnderlyingNode();
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.openapi.extensions.impl;
public class ExtensionClassAndAreaInstance {
private final Class myExtensionClass;
private final Object myAreaInstance;
public ExtensionClassAndAreaInstance(Class extensionClass, Object areaInstance) {
myExtensionClass = extensionClass;
myAreaInstance = areaInstance;
}
public Class getExtensionClass() {
return myExtensionClass;
}
public Object getAreaInstance() {
return myAreaInstance;
}
public boolean equals(Object areaInstance) {
if (this == areaInstance) return true;
if (!(areaInstance instanceof ExtensionClassAndAreaInstance)) return false;
final ExtensionClassAndAreaInstance extensionClassAndAreaInstance = (ExtensionClassAndAreaInstance) areaInstance;
if (myAreaInstance != null ? !myAreaInstance.equals(extensionClassAndAreaInstance.myAreaInstance) : extensionClassAndAreaInstance.myAreaInstance != null) return false;
if (!myExtensionClass.equals(extensionClassAndAreaInstance.myExtensionClass)) return false;
return true;
}
public int hashCode() {
int result;
result = myExtensionClass.hashCode();
result = 29 * result + (myAreaInstance != null ? myAreaInstance.hashCode() : 0);
return result;
}
}

View File

@@ -0,0 +1,82 @@
/*
* 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.LoadingOrder;
import com.intellij.openapi.extensions.PluginAware;
import com.intellij.openapi.extensions.ReaderConfigurator;
import com.thoughtworks.xstream.XStream;
import org.jdom.Element;
import org.picocontainer.PicoContainer;
import org.picocontainer.PicoInitializationException;
import org.picocontainer.PicoIntrospectionException;
import org.picocontainer.defaults.AssignabilityRegistrationException;
import org.picocontainer.defaults.ConstructorInjectionComponentAdapter;
import org.picocontainer.defaults.NotConcreteRegistrationException;
/**
* @author Alexander Kireyev
*/
public class ExtensionComponentAdapter extends ConstructorInjectionComponentAdapter implements LoadingOrder.Orderable {
private Object myComponentInstance;
private Element myExtensionElement;
private PicoContainer myContainer;
private String myPluginName;
public ExtensionComponentAdapter(Class implementationClass, Element extensionElement, PicoContainer container, String pluginName) {
super(new Object(), implementationClass);
myExtensionElement = extensionElement;
myContainer = container;
myPluginName = pluginName;
}
public Object getComponentInstance(final PicoContainer container) throws PicoInitializationException, PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
assert myContainer == container;
if (myComponentInstance == null) {
if (!Element.class.equals(getComponentImplementation())) {
XStream xStream = new XStream(new PropertyReflectionProvider());
xStream.registerConverter(new ElementConverter());
Object componentInstance = super.getComponentInstance(container);
if (componentInstance instanceof ReaderConfigurator) {
ReaderConfigurator readerConfigurator = (ReaderConfigurator) componentInstance;
readerConfigurator.configureReader(xStream);
}
xStream.alias(myExtensionElement.getName(), componentInstance.getClass());
myComponentInstance = xStream.unmarshal(new JDomReader(myExtensionElement), componentInstance);
}
else {
myComponentInstance = myExtensionElement;
}
if (myComponentInstance instanceof PluginAware) {
PluginAware pluginAware = (PluginAware) myComponentInstance;
pluginAware.setPluginName(myPluginName);
}
}
return myComponentInstance;
}
public Object getExtension() {
return getComponentInstance(myContainer);
}
public LoadingOrder getOrder() {
String orderAttr = myExtensionElement.getAttributeValue("order");
return LoadingOrder.readOrder(orderAttr);
}
public String getOrderId() {
return myExtensionElement.getAttributeValue("id");
}
public Element getExtensionElement() {
return myExtensionElement;
}
public Element getDescribingElement() {
return getExtensionElement();
}
}

View File

@@ -0,0 +1,286 @@
/*
* 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.*;
import java.lang.ref.SoftReference;
import java.lang.reflect.Array;
import java.util.*;
import org.jdom.Element;
/**
* @author AKireyev
*/
public class ExtensionPointImpl implements ExtensionPoint {
private final LogProvider myLogger;
private String myName;
private String myBeanClassName;
private List myExtensions = new ArrayList();
private List myLoadedAdapters = new ArrayList();
private Set myExtensionAdapters = new LinkedHashSet();
private Set myEPListeners = new LinkedHashSet();
private SoftReference myExtensionsCache;
private ExtensionsAreaImpl myOwner;
private final AreaInstance myArea;
private Class myExtensionClass;
public ExtensionPointImpl(String name, String beanClassName, ExtensionsAreaImpl owner, AreaInstance area, LogProvider logger) {
myName = name;
myBeanClassName = beanClassName;
myOwner = owner;
myArea = area;
myLogger = logger;
}
public String getName() {
return myName;
}
public AreaInstance getArea() {
return myArea;
}
public String getBeanClassName() {
return myBeanClassName;
}
public void registerExtension(Object extension) {
registerExtension(extension, LoadingOrder.ANY);
}
public void registerExtension(Object extension, LoadingOrder order) {
assert (extension != null) : "Extension cannot be null";
myOwner.getMutablePicoContainer().registerComponentInstance(new Object(), extension);
assert myExtensions.size() == myLoadedAdapters.size();
if (LoadingOrder.ANY == order) {
int index = myLoadedAdapters.size();
if (myLoadedAdapters.size() > 0) {
ExtensionComponentAdapter lastAdapter = (ExtensionComponentAdapter) myLoadedAdapters.get(myLoadedAdapters.size() - 1);
if (lastAdapter.getOrder() == LoadingOrder.LAST) {
index--;
}
}
internalRegisterExtension(extension, new ObjectComponentAdapter(extension, order), index, true);
}
else {
myExtensionAdapters.add(new ObjectComponentAdapter(extension, order));
processAdapters();
}
}
private void internalRegisterExtension(Object extension, ExtensionComponentAdapter adapter, int index, boolean runNotifications) {
myExtensionsCache = null;
if (myExtensions.contains(extension)) {
myLogger.error("Extension was already added: " + extension);
}
else {
myExtensions.add(index, extension);
myLoadedAdapters.add(index, adapter);
if (runNotifications) {
if (extension instanceof Extension) {
Extension o = (Extension) extension;
try {
o.extensionAdded(this);
} catch (Throwable e) {
myLogger.error(e);
}
}
notifyListenersOnAdd(extension);
}
}
}
private void notifyListenersOnAdd(Object extension) {
ExtensionPointListener[] listeners = (ExtensionPointListener[]) myEPListeners.toArray(new ExtensionPointListener[myEPListeners.size()]);
for (int i = 0; i < listeners.length; i++) {
ExtensionPointListener listener = listeners[i];
try {
listener.extensionAdded(extension);
} catch (Throwable e) {
myLogger.error(e);
}
}
}
public Object[] getExtensions() {
Object[] result = null;
processAdapters();
if (myExtensionsCache != null) {
result = (Object[]) myExtensionsCache.get();
}
if (result == null) {
result = myExtensions.toArray((Object[])Array.newInstance(getExtensionClass(), myExtensions.size()));
myExtensionsCache = new SoftReference(result);
}
return result;
}
private void processAdapters() {
if (myExtensionAdapters.size() > 0) {
List allAdapters = new ArrayList(myExtensionAdapters.size() + myLoadedAdapters.size());
allAdapters.addAll(myExtensionAdapters);
allAdapters.addAll(myLoadedAdapters);
myExtensions.clear();
List loadedAdapters = myLoadedAdapters;
myLoadedAdapters = new ArrayList();
ExtensionComponentAdapter[] adapters = (ExtensionComponentAdapter[]) allAdapters.toArray(new ExtensionComponentAdapter[myExtensionAdapters.size()]);
LoadingOrder.sort(adapters);
for (int i = 0; i < adapters.length; i++) {
ExtensionComponentAdapter adapter = adapters[i];
Object extension = adapter.getExtension();
internalRegisterExtension(extension, adapter, i, !loadedAdapters.contains(adapter));
}
myExtensionAdapters.clear();
}
}
public Object getExtension() {
Object[] extensions = getExtensions();
if (extensions.length == 0) return null;
return extensions[0];
}
public boolean hasExtension(Object extension) {
processAdapters();
return myExtensions.contains(extension);
}
public void unregisterExtension(Object extension) {
assert (extension != null) : "Extension cannot be null";
myOwner.getMutablePicoContainer().unregisterComponentByInstance(extension);
processAdapters();
internalUnregisterExtension(extension);
}
private void internalUnregisterExtension(Object extension) {
myExtensionsCache = null;
if (!myExtensions.contains(extension)) {
throw new IllegalArgumentException("Extension to be removed not found: " + extension);
}
int index = myExtensions.indexOf(extension);
myExtensions.remove(index);
myLoadedAdapters.remove(index);
notifyListenersOnRemove(extension);
if (extension instanceof Extension) {
Extension o = (Extension) extension;
try {
o.extensionRemoved(this);
} catch (Throwable e) {
myLogger.error(e);
}
}
}
private void notifyListenersOnRemove(Object extensionObject) {
for (Iterator iterator = myEPListeners.iterator(); iterator.hasNext();) {
ExtensionPointListener listener = (ExtensionPointListener)iterator.next();
try {
listener.extensionRemoved(extensionObject);
} catch (Throwable e) {
myLogger.error(e);
}
}
}
public void addExtensionPointListener(ExtensionPointListener listener) {
if (myEPListeners.add(listener)) {
for (Iterator iterator = myExtensions.iterator(); iterator.hasNext();) {
try {
listener.extensionAdded(iterator.next());
} catch (Throwable e) {
myLogger.error(e);
}
}
}
}
public void removeExtensionPointListener(ExtensionPointListener listener) {
if (myEPListeners.contains(listener)) {
for (Iterator iterator = myExtensions.iterator(); iterator.hasNext();) {
try {
listener.extensionRemoved(iterator.next());
} catch (Throwable e) {
myLogger.error(e);
}
}
myEPListeners.remove(listener);
}
}
public void reset() {
Object[] extensions = getExtensions();
for (int i = 0; i < extensions.length; i++) {
Object extension = extensions[i];
unregisterExtension(extension);
}
}
public Class getExtensionClass() {
if (myExtensionClass == null) {
try {
myExtensionClass = Class.forName(myBeanClassName);
}
catch (ClassNotFoundException e) {
myExtensionClass = Object.class;
}
}
return myExtensionClass;
}
public String toString() {
return getName();
}
void registerExtensionAdapter(ExtensionComponentAdapter adapter) {
myExtensionAdapters.add(adapter);
}
private static class ObjectComponentAdapter extends ExtensionComponentAdapter {
private Object myExtension;
private LoadingOrder myLoadingOrder;
public ObjectComponentAdapter(Object extension, LoadingOrder loadingOrder) {
super(Object.class, null, null, null);
myExtension = extension;
myLoadingOrder = loadingOrder;
}
public Object getExtension() {
return myExtension;
}
public LoadingOrder getOrder() {
return myLoadingOrder;
}
public String getOrderId() {
return null;
}
public Element getDescribingElement() {
return new Element("RuntimeExtension: " + myExtension);
}
}
}

View File

@@ -0,0 +1,379 @@
/*
* 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.*;
import org.apache.commons.collections.MultiHashMap;
import org.apache.commons.collections.MultiMap;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.output.XMLOutputter;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.PicoContainer;
import org.picocontainer.defaults.ConstructorInjectionComponentAdapter;
import org.picocontainer.defaults.DefaultPicoContainer;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.Modifier;
import java.util.*;
public class ExtensionsAreaImpl implements ExtensionsArea {
private final LogProvider myLogger;
static Map ourDefaultEPs = new HashMap();
static {
ourDefaultEPs.put(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME, EPAvailabilityListenerExtension.class.getName());
}
private static boolean DEBUG_REGISTRATION = true;
private MutablePicoContainer myPicoContainer;
// private Map myPluginName2picoContainer = new HashMap();
private Throwable myCreationTrace = null;
private Map myExtensionPoints = new HashMap();
private Map myEPTraces = new HashMap();
private MultiMap myAvailabilityListeners = new MultiHashMap();
private List mySuspendedListenerActions = new ArrayList();
private boolean myAvailabilityNotificationsActive = true;
private final AreaInstance myAreaInstance;
private MultiMap myServiceRegistry = new MultiHashMap();
private final String myAreaClass;
private Map myServiceClass2ServicesCache = new HashMap();
private Map myExtensionElement2extension = new HashMap();
private Map myPluginName2picoContainer = new HashMap();
public ExtensionsAreaImpl(String areaClass, AreaInstance areaInstance, PicoContainer parentPicoContainer, LogProvider logger) {
if (DEBUG_REGISTRATION) {
myCreationTrace = new Throwable("Area creation trace");
}
myAreaClass = areaClass;
myAreaInstance = areaInstance;
myPicoContainer = new AreaPicoContainer(parentPicoContainer, this);
if (areaInstance != null) {
myPicoContainer.registerComponentInstance(areaInstance);
}
initialize();
myLogger = logger;
}
public ExtensionsAreaImpl(MutablePicoContainer picoContainer, LogProvider logger) {
this(null, null, picoContainer, logger);
}
public MutablePicoContainer getPicoContainer() {
return myPicoContainer;
}
MutablePicoContainer getMutablePicoContainer() {
return myPicoContainer;
}
public String getAreaClass() {
return myAreaClass;
}
public void registerExtensionPoint(String pluginName, Element extensionPointElement) {
assert pluginName != null;
String epName = pluginName + '.' + extensionPointElement.getAttributeValue("name");
String className = extensionPointElement.getAttributeValue("beanClass");
if (className == null) {
className = extensionPointElement.getAttributeValue("interface");
}
if (className == null) {
throw new RuntimeException("No class specified for extension point: " + epName);
}
registerExtensionPoint(epName, className);
}
public void registerExtension(final String pluginName, final Element extensionElement) {
String epName = extractEPName(extensionElement);
ExtensionComponentAdapter adapter;
String implClass = null;
Class extensionClass = getExtensionPoint(epName).getExtensionClass();
implClass = extensionElement.getAttributeValue("implementation");
if (extensionClass.isInterface() || Modifier.isAbstract(extensionClass.getModifiers())) {
if (implClass == null) {
throw new RuntimeException("Expected implementation for extension declaration (ep = " + epName + ")");
}
}
if (implClass != null) {
try {
Class implementationClass = Class.forName(implClass);
adapter = new ExtensionComponentAdapter(implementationClass, extensionElement, getPluginContainer(pluginName), pluginName);
}
catch (ClassNotFoundException e) {
myLogger.warn("Extension implementation class not found: " + implClass);
myExtensionElement2extension.put(extensionElement, null);
return;
}
}
else {
final ExtensionPoint extensionPoint = getExtensionPoint(epName);
adapter = new ExtensionComponentAdapter(extensionPoint.getExtensionClass(), extensionElement, getPluginContainer(pluginName), pluginName);
}
myExtensionElement2extension.put(extensionElement, adapter);
internalGetPluginContainer(pluginName).registerComponent(adapter);
getExtensionPointImpl(epName).registerExtensionAdapter(adapter);
}
private String extractEPName(final Element extensionElement) {
String epName = extensionElement.getAttributeValue("point");
if (epName == null) {
Namespace namespace = extensionElement.getNamespace();
epName = namespace.getURI() + '.' + extensionElement.getName();
}
return epName;
}
public PicoContainer getPluginContainer(String pluginName) {
return internalGetPluginContainer(pluginName);
}
private MutablePicoContainer internalGetPluginContainer(String pluginName) {
// return myPicoContainer;
DefaultPicoContainer pluginContainer = (DefaultPicoContainer) myPluginName2picoContainer.get(pluginName);
if (pluginContainer == null) {
pluginContainer = new DefaultPicoContainer(myPicoContainer);
myPicoContainer.addChildContainer(pluginContainer);
myPluginName2picoContainer.put(pluginName, pluginContainer);
}
return pluginContainer;
}
private void disposePluginContainer(String pluginName) {
DefaultPicoContainer pluginContainer = (DefaultPicoContainer) myPluginName2picoContainer.remove(pluginName);
if (pluginContainer != null) {
myPicoContainer.removeChildContainer(pluginContainer);
}
}
public void unregisterExtensionPoint(String pluginName, Element extensionPointElement) {
assert pluginName != null;
String epName = pluginName + '.' + extensionPointElement.getAttributeValue("name");
unregisterExtensionPoint(epName);
}
public void unregisterExtension(String pluginName, Element extensionElement) {
String epName = extractEPName(extensionElement);
if (!myExtensionElement2extension.containsKey(extensionElement)) {
XMLOutputter xmlOutputter = new XMLOutputter();
xmlOutputter.setIndent(" ");
xmlOutputter.setTextNormalize(true);
xmlOutputter.setNewlines(true);
StringWriter stringWriter = new StringWriter();
try {
xmlOutputter.output(extensionElement, stringWriter);
}
catch (IOException e) {
throw new RuntimeException(e);
}
myLogger.warn(stringWriter.toString());
throw new IllegalArgumentException("Trying to unregister extension element that was never registered");
}
ExtensionComponentAdapter adapter = (ExtensionComponentAdapter) myExtensionElement2extension.remove(extensionElement);
if (adapter == null) return;
if (getExtensionPoint(epName).hasExtension(adapter.getExtension())) {
getExtensionPoint(epName).unregisterExtension(adapter.getExtension());
MutablePicoContainer pluginContainer = internalGetPluginContainer(pluginName);
pluginContainer.unregisterComponent(adapter.getComponentKey());
if (pluginContainer.getComponentAdapters().size() == 0) {
disposePluginContainer(pluginName);
}
}
}
public void initialize() {
for (Iterator iterator = ourDefaultEPs.keySet().iterator(); iterator.hasNext();) {
String epName = (String) iterator.next();
registerExtensionPoint(epName, (String) ourDefaultEPs.get(epName));
}
getExtensionPoint(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME).addExtensionPointListener(new ExtensionPointListener() {
public void extensionRemoved(Object extension) {
EPAvailabilityListenerExtension epListenerExtension = (EPAvailabilityListenerExtension) extension;
List listeners = (List) myAvailabilityListeners.get(epListenerExtension.getExtensionPointName());
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
Object listener = iterator.next();
if (listener.getClass().getName().equals(epListenerExtension.getListenerClass())) {
iterator.remove();
return;
}
}
myLogger.warn("Failed to find EP availability listener: " + epListenerExtension.getListenerClass());
}
public void extensionAdded(Object extension) {
EPAvailabilityListenerExtension epListenerExtension = (EPAvailabilityListenerExtension) extension;
try {
String epName = epListenerExtension.getExtensionPointName();
ExtensionPointAvailabilityListener listener = (ExtensionPointAvailabilityListener) instantiate(Class.forName(epListenerExtension.getListenerClass()));
addAvailabilityListener(epName, listener);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
public Object instantiate(Class clazz) {
ConstructorInjectionComponentAdapter adapter = new ConstructorInjectionComponentAdapter(System.identityHashCode(new Object()) + "", clazz);
return adapter.getComponentInstance(getPicoContainer());
}
public Throwable getCreationTrace() {
return myCreationTrace;
}
public void addAvailabilityListener(String epName, ExtensionPointAvailabilityListener listener) {
myAvailabilityListeners.put(epName, listener);
if (hasExtensionPoint(epName)) {
notifyAvailableListener(listener, (ExtensionPoint) myExtensionPoints.get(epName));
}
}
public void registerExtensionPoint(final String extensionPointName, String extensionPointBeanClass) {
if (hasExtensionPoint(extensionPointName)) {
if (DEBUG_REGISTRATION) {
myLogger.error((Throwable) myEPTraces.get(extensionPointName));
}
throw new RuntimeException("Duplicate registration for EP: " + extensionPointName);
}
ExtensionPointImpl extensionPoint = new ExtensionPointImpl(extensionPointName, extensionPointBeanClass, this, myAreaInstance, myLogger);
myExtensionPoints.put(extensionPointName, extensionPoint);
notifyEPRegistered(extensionPoint);
if (DEBUG_REGISTRATION) {
myEPTraces.put(extensionPointName, new Throwable("Original registration for " + extensionPointName));
}
}
private void notifyEPRegistered(final ExtensionPoint extensionPoint) {
List listeners = (List) myAvailabilityListeners.get(extensionPoint.getName());
if (listeners != null) {
for (Iterator i = listeners.iterator(); i.hasNext();) {
final ExtensionPointAvailabilityListener listener = (ExtensionPointAvailabilityListener) i.next();
notifyAvailableListener(listener, extensionPoint);
}
}
}
private void notifyAvailableListener(final ExtensionPointAvailabilityListener listener, final ExtensionPoint extensionPoint) {
Runnable action = new Runnable() {
public void run() {
listener.extensionPointRegistered(extensionPoint);
}
};
if (myAvailabilityNotificationsActive) {
action.run();
}
else {
mySuspendedListenerActions.add(action);
}
}
public ExtensionPoint getExtensionPoint(String extensionPointName) {
return getExtensionPointImpl(extensionPointName);
}
private ExtensionPointImpl getExtensionPointImpl(String extensionPointName) {
if (!hasExtensionPoint(extensionPointName)) {
throw new IllegalArgumentException("Missing extension point: " + extensionPointName +
" in area " + myAreaInstance );
}
return (ExtensionPointImpl) myExtensionPoints.get(extensionPointName);
}
public ExtensionPoint[] getExtensionPoints() {
return (ExtensionPoint[]) myExtensionPoints.values().toArray(new ExtensionPoint[myExtensionPoints.size()]);
}
public void unregisterExtensionPoint(final String extensionPointName) {
ExtensionPoint extensionPoint = (ExtensionPoint) myExtensionPoints.get(extensionPointName);
if (extensionPoint != null) {
extensionPoint.reset();
myExtensionPoints.remove(extensionPointName);
notifyEPRemoved(extensionPoint);
}
}
private void notifyEPRemoved(final ExtensionPoint extensionPoint) {
List listeners = (List) myAvailabilityListeners.get(extensionPoint.getName());
if (listeners != null) {
for (Iterator i = listeners.iterator(); i.hasNext();) {
final ExtensionPointAvailabilityListener listener = (ExtensionPointAvailabilityListener) i.next();
Runnable action = new Runnable() {
public void run() {
listener.extensionPointRemoved(extensionPoint);
}
};
if (myAvailabilityNotificationsActive) {
action.run();
}
else {
mySuspendedListenerActions.add(action);
}
}
}
}
public boolean hasExtensionPoint(String extensionPointName) {
return myExtensionPoints.containsKey(extensionPointName);
}
public void suspendInteractions() {
myAvailabilityNotificationsActive = false;
}
public void resumeInteractions() {
myAvailabilityNotificationsActive = true;
ExtensionPoint[] extensionPoints = getExtensionPoints();
for (int i = 0; i < extensionPoints.length; i++) {
ExtensionPoint extensionPoint = extensionPoints[i];
extensionPoint.getExtensions(); // creates extensions from ComponentAdapters
}
for (Iterator i = mySuspendedListenerActions.iterator(); i.hasNext();) {
Runnable action = (Runnable) i.next();
try {
action.run();
}
catch (Exception e) {
myLogger.error(e);
}
}
mySuspendedListenerActions.clear();
}
public void killPendingInteractions() {
mySuspendedListenerActions.clear();
}
private Set collectInterfaces(String className) {
try {
Class serviceClass = Class.forName(className);
Set classes = new HashSet();
classes.add(serviceClass.getName());
collectInterfaces(serviceClass, classes);
return classes;
}
catch (ClassNotFoundException e) {
return Collections.EMPTY_SET;
}
}
private void collectInterfaces(Class serviceClass, Set classes) {
Class[] interfaces = serviceClass.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
Class anInterface = interfaces[i];
if (!classes.contains(anInterface.getName())) {
classes.add(anInterface.getName());
collectInterfaces(anInterface, classes);
}
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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 org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jmock.cglib.MockObjectTestCase;
import org.picocontainer.defaults.DefaultPicoContainer;
import java.io.IOException;
import java.io.StringReader;
import com.intellij.openapi.extensions.LoadingOrder;
/**
* @author Alexander Kireyev
*/
public class ExtensionComponentAdapterTest extends MockObjectTestCase {
public void testLoadingOrderReading() {
assertEquals(LoadingOrder.ANY, createAdapter("<extension/>").getOrder());
assertEquals(LoadingOrder.FIRST, createAdapter("<extension order=\"FIRST\"/>").getOrder());
assertEquals(LoadingOrder.LAST, createAdapter("<extension order=\"LAST\"/>").getOrder());
assertEquals(LoadingOrder.before("test"), createAdapter("<extension order=\"BEFORE:test\"/>").getOrder());
assertEquals(LoadingOrder.after("test"), createAdapter("<extension order=\"AFTER:test\"/>").getOrder());
}
private ExtensionComponentAdapter createAdapter(String text) {
Element extensionElement = readElement(text);
ExtensionComponentAdapter adapter = new ExtensionComponentAdapter(Object.class, extensionElement, new DefaultPicoContainer(), "");
return adapter;
}
static Element readElement(String text) {
Element extensionElement1 = null;
try {
extensionElement1 = new SAXBuilder().build(new StringReader(text)).getRootElement();
}
catch (JDOMException e) {
throw new RuntimeException(e);
}
catch (IOException e) {
throw new RuntimeException(e);
}
Element extensionElement = extensionElement1;
return extensionElement;
}
}

View File

@@ -0,0 +1,124 @@
/*
* 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.*;
import junit.framework.TestCase;
import org.picocontainer.defaults.DefaultPicoContainer;
/**
* @author AKireyev
*/
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());
}
private ExtensionPointImpl buildExtensionPoint() {
return new ExtensionPointImpl(ExtensionsImplTest.EXTENSION_POINT_NAME_1, Integer.class.getName(), buildExtensionArea(), null, new Extensions.SimpleLogProvider());
}
private ExtensionsAreaImpl buildExtensionArea() {
return new ExtensionsAreaImpl(new DefaultPicoContainer(), new Extensions.SimpleLogProvider());
}
public void testUnregisterObject() {
ExtensionPointImpl extensionPoint = buildExtensionPoint();
extensionPoint.registerExtension(new Integer(123));
Object[] extensions = extensionPoint.getExtensions();
assertEquals(1, extensions.length);
extensionPoint.unregisterExtension(new Integer(123));
extensions = extensionPoint.getExtensions();
assertEquals(0, extensions.length);
}
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());
final boolean[] flags = new boolean[2];
Extension extension = new Extension() {
public void extensionAdded(ExtensionPoint extensionPoint1) {
assertSame(extensionPoint, extensionPoint1);
assertSame(area, extensionPoint1.getArea());
flags[0] = true;
}
public void extensionRemoved(ExtensionPoint extensionPoint1) {
assertSame(extensionPoint, extensionPoint1);
assertSame(area, extensionPoint1.getArea());
flags[1] = true;
}
};
extensionPoint.registerExtension(extension);
assertTrue("Registratioon call is missed", flags[0]);
assertFalse(flags[1]);
extensionPoint.unregisterExtension(extension);
assertTrue("UnRegistratioon call is missed", flags[1]);
}
public void testRegisterObject() {
ExtensionPointImpl extensionPoint = buildExtensionPoint();
extensionPoint.registerExtension(new Integer(123));
Object[] extensions = extensionPoint.getExtensions();
assertEquals("One extension", 1, extensions.length);
assertEquals("Correct type", Integer[].class, extensions.getClass());
assertEquals("Correct object", new Integer(123), extensions[0]);
}
public void testRegistrationOrder() {
ExtensionPointImpl extensionPoint = buildExtensionPoint();
extensionPoint.registerExtension(new Integer(123));
extensionPoint.registerExtension(new Integer(321), LoadingOrder.FIRST);
Object[] extensions = extensionPoint.getExtensions();
assertEquals("One extension", 2, extensions.length);
assertEquals("Correct object", new Integer(321), extensions[0]);
}
public void testListener() {
ExtensionPointImpl extensionPoint = buildExtensionPoint();
final boolean added[] = new boolean[1];
final boolean removed[] = new boolean[1];
extensionPoint.addExtensionPointListener(new ExtensionPointListener() {
public void extensionAdded(Object extension) {
added[0] = true;
}
public void extensionRemoved(Object extension) {
removed[0] = true;
}
});
assertFalse(added[0]);
assertFalse(removed[0]);
extensionPoint.registerExtension(new Integer(123));
assertTrue(added[0]);
assertFalse(removed[0]);
added[0] = false;
extensionPoint.unregisterExtension(new Integer(123));
assertFalse(added[0]);
assertTrue(removed[0]);
}
public void testLateListener() {
ExtensionPointImpl extensionPoint = buildExtensionPoint();
final boolean added[] = new boolean[1];
extensionPoint.registerExtension(new Integer(123));
assertFalse(added[0]);
extensionPoint.addExtensionPointListener(new ExtensionPointListener() {
public void extensionAdded(Object extension) {
added[0] = true;
}
public void extensionRemoved(Object extension) {
}
});
assertTrue(added[0]);
}
}

View File

@@ -0,0 +1,352 @@
/*
* 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.*;
import java.util.Arrays;
import org.picocontainer.defaults.DefaultPicoContainer;
import org.picocontainer.MutablePicoContainer;
/**
* @author AKireyev
*/
public class ExtensionsImplTest extends TestCase {
public static final String EXTENSION_POINT_NAME_1 = "ext.point.one";
public static final String AREA_1 = "the.area.one";
protected void tearDown() throws Exception {
ExtensionsTestUtils.hardReset();
super.tearDown(); //To change body of overriden methods use Options | File Templates.
}
public void testCreateAndAccess() {
ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, new Extensions.SimpleLogProvider());
int numEP = extensionsArea.getExtensionPoints().length;
extensionsArea.registerExtensionPoint(EXTENSION_POINT_NAME_1, Integer.class.getName());
assertEquals("Additional EP available", numEP + 1, extensionsArea.getExtensionPoints().length);
assertNotNull("EP by name available", extensionsArea.getExtensionPoint(EXTENSION_POINT_NAME_1));
}
public void testInvalidActions() {
ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, new Extensions.SimpleLogProvider());
extensionsArea.registerExtensionPoint(EXTENSION_POINT_NAME_1, Integer.class.getName());
try {
extensionsArea.registerExtensionPoint(EXTENSION_POINT_NAME_1, Boolean.class.getName());
fail("Should not allow duplicate registration");
} catch (RuntimeException e) {
}
}
public void testUnregisterEP() {
ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, new Extensions.SimpleLogProvider());
int numEP = extensionsArea.getExtensionPoints().length;
extensionsArea.registerExtensionPoint(EXTENSION_POINT_NAME_1, Integer.class.getName());
final boolean removed[] = new boolean[1];
removed[0] = false;
extensionsArea.getExtensionPoint(EXTENSION_POINT_NAME_1).addExtensionPointListener(new ExtensionPointListener() {
public void extensionAdded(Object extension) {
}
public void extensionRemoved(Object extension) {
removed[0] = true;
}
});
extensionsArea.getExtensionPoint(EXTENSION_POINT_NAME_1).registerExtension(new Integer(123));
extensionsArea.unregisterExtensionPoint(EXTENSION_POINT_NAME_1);
assertTrue("Extension point should be removed", extensionsArea.getExtensionPoints().length == numEP);
assertTrue("Extension point disposed", removed[0]);
}
public void testAvailabilityListener() {
ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, new Extensions.SimpleLogProvider());
MyListener.reset();
extensionsArea.getExtensionPoint(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME).registerExtension(
new EPAvailabilityListenerExtension(EXTENSION_POINT_NAME_1, MyListener.class.getName()));
assertEquals(0, MyListener.regcount);
assertEquals(0, MyListener.remcount);
extensionsArea.registerExtensionPoint(EXTENSION_POINT_NAME_1, Integer.class.getName());
assertEquals(1, MyListener.regcount);
assertEquals(0, MyListener.remcount);
MyListener.reset();
extensionsArea.unregisterExtensionPoint(EXTENSION_POINT_NAME_1);
assertEquals(1, MyListener.remcount);
assertEquals(0, MyListener.regcount);
}
public void testAvailability2Listeners() {
ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, new Extensions.SimpleLogProvider());
MyListener.reset();
extensionsArea.registerExtensionPoint(EXTENSION_POINT_NAME_1, Integer.class.getName());
extensionsArea.getExtensionPoint(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME).registerExtension(
new EPAvailabilityListenerExtension(EXTENSION_POINT_NAME_1, MyListener.class.getName()));
extensionsArea.getExtensionPoint(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME).registerExtension(
new EPAvailabilityListenerExtension(EXTENSION_POINT_NAME_1, MyListener.class.getName()));
assertEquals(2, MyListener.regcount);
assertEquals(0, MyListener.remcount);
MyListener.reset();
extensionsArea.unregisterExtensionPoint(EXTENSION_POINT_NAME_1);
assertEquals(2, MyListener.remcount);
assertEquals(0, MyListener.regcount);
}
public void testAvailabilityListenerAfter() {
ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, new Extensions.SimpleLogProvider());
extensionsArea.registerExtensionPoint(EXTENSION_POINT_NAME_1, Integer.class.getName());
MyListener.reset();
extensionsArea.getExtensionPoint(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME).registerExtension(
new EPAvailabilityListenerExtension(EXTENSION_POINT_NAME_1, MyListener.class.getName()));
assertEquals(1, MyListener.regcount);
assertEquals(0, MyListener.remcount);
}
public void testAvailabilityListenerDelay() {
ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, new Extensions.SimpleLogProvider());
MyListener.reset();
extensionsArea.suspendInteractions();
extensionsArea.getExtensionPoint(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME).registerExtension(
new EPAvailabilityListenerExtension(EXTENSION_POINT_NAME_1, MyListener.class.getName()));
assertEquals(0, MyListener.regcount);
assertEquals(0, MyListener.remcount);
extensionsArea.registerExtensionPoint(EXTENSION_POINT_NAME_1, Integer.class.getName());
assertEquals(0, MyListener.regcount);
assertEquals(0, MyListener.remcount);
extensionsArea.resumeInteractions();
assertEquals(1, MyListener.regcount);
assertEquals(0, MyListener.remcount);
MyListener.reset();
extensionsArea.suspendInteractions();
assertEquals(0, MyListener.regcount);
assertEquals(0, MyListener.remcount);
extensionsArea.unregisterExtensionPoint(EXTENSION_POINT_NAME_1);
assertEquals(0, MyListener.regcount);
assertEquals(0, MyListener.remcount);
extensionsArea.resumeInteractions();
assertEquals(1, MyListener.remcount);
assertEquals(0, MyListener.regcount);
}
public void testKillAvailabilityNotifications() {
ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, new Extensions.SimpleLogProvider());
MyListener.reset();
extensionsArea.suspendInteractions();
extensionsArea.getExtensionPoint(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME).registerExtension(
new EPAvailabilityListenerExtension(EXTENSION_POINT_NAME_1, MyListener.class.getName()));
assertEquals(0, MyListener.regcount);
assertEquals(0, MyListener.remcount);
extensionsArea.registerExtensionPoint(EXTENSION_POINT_NAME_1, Integer.class.getName());
assertEquals(0, MyListener.regcount);
assertEquals(0, MyListener.remcount);
extensionsArea.killPendingInteractions();
extensionsArea.resumeInteractions();
assertEquals(0, MyListener.regcount);
assertEquals(0, MyListener.remcount);
}
public void testListenerAfterResume() {
ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, new Extensions.SimpleLogProvider());
extensionsArea.suspendInteractions();
extensionsArea.resumeInteractions();
MyListener.reset();
extensionsArea.getExtensionPoint(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME).registerExtension(
new EPAvailabilityListenerExtension(EXTENSION_POINT_NAME_1, MyListener.class.getName()));
assertEquals(0, MyListener.regcount);
assertEquals(0, MyListener.remcount);
extensionsArea.registerExtensionPoint(EXTENSION_POINT_NAME_1, Integer.class.getName());
assertEquals(1, MyListener.regcount);
assertEquals(0, MyListener.remcount);
MyListener.reset();
extensionsArea.unregisterExtensionPoint(EXTENSION_POINT_NAME_1);
assertEquals(1, MyListener.remcount);
assertEquals(0, MyListener.regcount);
}
public void testTryPicoContainer() {
DefaultPicoContainer rootContainer = new DefaultPicoContainer();
rootContainer.registerComponentInstance("plugin1", new DefaultPicoContainer(rootContainer));
rootContainer.registerComponentInstance("plugin2", new DefaultPicoContainer(rootContainer));
// rootContainer.registerComponentImplementation("plugin2", DefaultPicoContainer.class);
MutablePicoContainer container1 = (MutablePicoContainer)rootContainer.getComponentInstance("plugin1");
MutablePicoContainer container2 = (MutablePicoContainer)rootContainer.getComponentInstance("plugin2");
container1.registerComponentImplementation("component1", MyComponent1.class);
container1.registerComponentImplementation("component1.1", MyComponent1.class);
container2.registerComponentImplementation("component2", MyComponent2.class);
MyInterface1 testInstance = new MyInterface1() {
public void run() {
}
};
rootContainer.registerComponentInstance(testInstance);
MyComponent1 component1 = (MyComponent1)container1.getComponentInstance("component1");
assertEquals(testInstance, component1.testObject);
rootContainer.registerComponentInstance("component1", component1);
MyComponent1 component11 = (MyComponent1)container1.getComponentInstance("component1.1");
rootContainer.registerComponentInstance("component11", component11);
MyComponent2 component2 = (MyComponent2)container2.getComponentInstance("component2");
assertEquals(testInstance, component2.testObject);
assertTrue(Arrays.asList(component2.comp1).contains(component1));
assertTrue(Arrays.asList(component2.comp1).contains(component11));
rootContainer.registerComponentInstance("component2", component2);
rootContainer.registerComponentImplementation(MyTestComponent.class);
MyTestComponent testComponent = (MyTestComponent)rootContainer.getComponentInstance(MyTestComponent.class);
assertTrue(Arrays.asList(testComponent.comp1).contains(component1));
assertTrue(Arrays.asList(testComponent.comp1).contains(component11));
assertEquals(component2, testComponent.comp2);
}
public void testTryPicoContainer2() {
DefaultPicoContainer rootContainer = new DefaultPicoContainer();
rootContainer.registerComponentImplementation("component1", MyComponent1.class);
rootContainer.registerComponentImplementation("component1.1", MyComponent1.class);
rootContainer.registerComponentImplementation("component2", MyComponent2.class);
rootContainer.registerComponentImplementation(MyTestComponent.class);
MyInterface1 testInstance = new MyInterface1() {
public void run() {
}
};
rootContainer.registerComponentInstance(testInstance);
MyTestComponent testComponent = (MyTestComponent)rootContainer.getComponentInstance(MyTestComponent.class);
MyComponent2 component2 = (MyComponent2)rootContainer.getComponentInstance("component2");
MyComponent1 component11 = (MyComponent1)rootContainer.getComponentInstance("component1.1");
MyComponent1 component1 = (MyComponent1)rootContainer.getComponentInstance("component1");
assertEquals(testInstance, component1.testObject);
assertEquals(testInstance, component2.testObject);
assertTrue(Arrays.asList(component2.comp1).contains(component1));
assertTrue(Arrays.asList(component2.comp1).contains(component11));
assertTrue(Arrays.asList(testComponent.comp1).contains(component1));
assertTrue(Arrays.asList(testComponent.comp1).contains(component11));
assertEquals(component2, testComponent.comp2);
}
public void testExtensionsNamespaces() {
ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer(), new Extensions.SimpleLogProvider());
extensionsArea.registerExtensionPoint("plugin.ep1", TestExtensionClassOne.class.getName());
extensionsArea.registerExtension("plugin", ExtensionComponentAdapterTest.readElement(
"<plugin:ep1 xmlns:plugin=\"plugin\" order=\"LAST\"><text>3</text></plugin:ep1>"));
extensionsArea.registerExtension("plugin", ExtensionComponentAdapterTest.readElement(
"<ep1 xmlns=\"plugin\" order=\"FIRST\"><text>1</text></ep1>"));
extensionsArea.registerExtension("plugin", ExtensionComponentAdapterTest.readElement(
"<extension point=\"plugin.ep1\"><text>2</text></extension>"));
ExtensionPoint extensionPoint = extensionsArea.getExtensionPoint("plugin.ep1");
TestExtensionClassOne[] extensions = (TestExtensionClassOne[]) extensionPoint.getExtensions();
assertEquals(3, extensions.length);
assertEquals("1", extensions[0].getText());
assertEquals("2", extensions[1].getText());
assertEquals("3", extensions[2].getText());
}
public void testExtensionsWithOrdering() {
ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer(), new Extensions.SimpleLogProvider());
extensionsArea.registerExtensionPoint("ep1", TestExtensionClassOne.class.getName());
extensionsArea.registerExtension("", ExtensionComponentAdapterTest.readElement(
"<extension point=\"ep1\" order=\"LAST\"><text>3</text></extension>"));
extensionsArea.registerExtension("", ExtensionComponentAdapterTest.readElement(
"<extension point=\"ep1\" order=\"FIRST\"><text>1</text></extension>"));
extensionsArea.registerExtension("", ExtensionComponentAdapterTest.readElement(
"<extension point=\"ep1\"><text>2</text></extension>"));
ExtensionPoint extensionPoint = extensionsArea.getExtensionPoint("ep1");
TestExtensionClassOne[] extensions = (TestExtensionClassOne[]) extensionPoint.getExtensions();
assertEquals(3, extensions.length);
assertEquals("1", extensions[0].getText());
assertEquals("2", extensions[1].getText());
assertEquals("3", extensions[2].getText());
}
public void testExtensionsWithOrderingUpdate() {
ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer(), new Extensions.SimpleLogProvider());
extensionsArea.registerExtensionPoint("ep1", TestExtensionClassOne.class.getName());
extensionsArea.registerExtension("", ExtensionComponentAdapterTest.readElement(
"<extension point=\"ep1\" order=\"LAST\"><text>6</text></extension>"));
extensionsArea.registerExtension("", ExtensionComponentAdapterTest.readElement(
"<extension point=\"ep1\" order=\"FIRST\"><text>1</text></extension>"));
extensionsArea.registerExtension("", ExtensionComponentAdapterTest.readElement(
"<extension point=\"ep1\" id=\"id\"><text>3</text></extension>"));
ExtensionPoint extensionPoint = extensionsArea.getExtensionPoint("ep1");
TestExtensionClassOne[] extensions = (TestExtensionClassOne[]) extensionPoint.getExtensions();
assertEquals(3, extensions.length);
assertEquals("1", extensions[0].getText());
assertEquals("3", extensions[1].getText());
assertEquals("6", extensions[2].getText());
TestExtensionClassOne extension = new TestExtensionClassOne("xxx");
extensionPoint.registerExtension(extension);
extensionPoint.unregisterExtension(extension);
extensionsArea.registerExtension("", ExtensionComponentAdapterTest.readElement(
"<extension point=\"ep1\" order=\"BEFORE:id\"><text>2</text></extension>"));
extensionsArea.registerExtension("", ExtensionComponentAdapterTest.readElement(
"<extension point=\"ep1\" order=\"AFTER:id\"><text>4</text></extension>"));
extensionPoint.registerExtension(new TestExtensionClassOne("5"));
extensions = (TestExtensionClassOne[]) extensionPoint.getExtensions();
assertEquals(6, extensions.length);
assertEquals("1", extensions[0].getText());
assertEquals("2", extensions[1].getText());
assertEquals("3", extensions[2].getText());
assertEquals("4", extensions[3].getText());
assertEquals("5", extensions[4].getText());
assertEquals("6", extensions[5].getText());
}
public interface MyInterface1 extends Runnable {
}
public interface MyInterface2 {
}
public interface MyInterface3 extends Runnable {
}
public interface MyInterface4 extends MyInterface1, MyInterface2, MyInterface3 {
}
public static class MyClass implements MyInterface4 {
public void run() {
}
}
public static class MyComponent1 {
public MyInterface1 testObject;
public MyComponent1(MyInterface1 testObject) {
this.testObject = testObject;
}
}
public static class MyComponent2 {
public MyInterface1 testObject;
public MyComponent1[] comp1;
public MyComponent2(MyComponent1[] comp1, MyInterface1 testObject) {
this.comp1 = comp1;
this.testObject = testObject;
}
}
public static class MyTestComponent {
public MyComponent1[] comp1;
public MyComponent2 comp2;
public MyTestComponent(MyComponent1[] comp1, MyComponent2 comp2) {
this.comp1 = comp1;
this.comp2 = comp2;
}
}
public static class MyListener implements ExtensionPointAvailabilityListener {
public static int regcount = 0;
public static int remcount = 0;
public void extensionPointRegistered(ExtensionPoint extensionPoint) {
regcount++;
}
public void extensionPointRemoved(ExtensionPoint extensionPoint) {
remcount++;
}
public static void reset() {
regcount = 0;
remcount = 0;
}
}
}

View File

@@ -0,0 +1,158 @@
/*
* 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 org.jmock.cglib.MockObjectTestCase;
import org.jmock.cglib.Mock;
import org.jmock.core.stub.ReturnStub;
import org.jdom.Element;
import org.picocontainer.PicoContainer;
import org.picocontainer.defaults.AssignabilityRegistrationException;
import java.util.ArrayList;
import com.intellij.openapi.extensions.LoadingOrder;
import com.intellij.openapi.extensions.SortingException;
/**
* @author Alexander Kireyev
*/
public class LoadingOrderTest extends MockObjectTestCase {
public void testSimpleSorting() {
ArrayList target = new ArrayList();
target.add(createElement(LoadingOrder.ANY, null, "any"));
target.add(createElement(LoadingOrder.FIRST, null, "1"));
target.add(createElement(LoadingOrder.LAST, null, "2"));
target.add(createElement(LoadingOrder.ANY, null, "any"));
LoadingOrder.Orderable[] array = (LoadingOrder.Orderable[]) target.toArray(new LoadingOrder.Orderable[target.size()]);
assertSequence(array, "1anyany2");
}
public void testComplexSorting() {
ArrayList target = new ArrayList();
String idOne = "idone";
String idTwo = "idTwo";
target.add(createElement(LoadingOrder.before(idTwo), idOne, "2"));
target.add(createElement(LoadingOrder.FIRST, null, "0"));
target.add(createElement(LoadingOrder.LAST, null, "5"));
target.add(createElement(LoadingOrder.after(idTwo), null, "4"));
target.add(createElement(LoadingOrder.ANY, idTwo, "3"));
target.add(createElement(LoadingOrder.before(idOne), null, "1"));
LoadingOrder.Orderable[] array = (LoadingOrder.Orderable[]) target.toArray(new LoadingOrder.Orderable[target.size()]);
assertSequence(array, "012345");
}
public void testComplexSorting2() {
ArrayList target = new ArrayList();
String idOne = "idone";
target.add(createElement(LoadingOrder.before(idOne), null, "2"));
target.add(createElement(LoadingOrder.after(idOne), null, "4"));
target.add(createElement(LoadingOrder.FIRST, null, "1"));
target.add(createElement(LoadingOrder.ANY, idOne, "3"));
target.add(createElement(LoadingOrder.ANY, null, "5"));
target.add(createElement(LoadingOrder.LAST, null, "6"));
LoadingOrder.Orderable[] array = (LoadingOrder.Orderable[]) target.toArray(new LoadingOrder.Orderable[target.size()]);
assertSequence(array, "123456");
}
private void assertSequence(LoadingOrder.Orderable[] array, String expected) {
LoadingOrder.sort(array);
StringBuffer sequence = buildSequence(array);
assertEquals(expected, sequence.toString());
}
private StringBuffer buildSequence(LoadingOrder.Orderable[] array) {
StringBuffer sequence = new StringBuffer();
for (int i = 0; i < array.length; i++) {
LoadingOrder.Orderable adapter = array[i];
sequence.append(((MyElement)adapter.getDescribingElement()).getID());
}
return sequence;
}
public void testFailingSortingBeforeFirst() {
ArrayList target = new ArrayList();
target.add(createElement(LoadingOrder.ANY, null, "good"));
target.add(createElement(LoadingOrder.FIRST, "first", "bad"));
target.add(createElement(LoadingOrder.LAST, null, "good"));
target.add(createElement(LoadingOrder.before("first"), null, "bad"));
LoadingOrder.Orderable[] array = (LoadingOrder.Orderable[]) target.toArray(new LoadingOrder.Orderable[target.size()]);
checkSortingFailure(array, 2);
}
public void testFailingSortingFirst() {
ArrayList target = new ArrayList();
target.add(createElement(LoadingOrder.ANY, null, "good"));
target.add(createElement(LoadingOrder.FIRST, "first", "bad"));
target.add(createElement(LoadingOrder.LAST, null, "good"));
target.add(createElement(LoadingOrder.FIRST, null, "bad"));
LoadingOrder.Orderable[] array = (LoadingOrder.Orderable[]) target.toArray(new LoadingOrder.Orderable[target.size()]);
checkSortingFailure(array, 2);
}
private void checkSortingFailure(LoadingOrder.Orderable[] array, int expectedCount) {
try {
LoadingOrder.sort(array);
fail("Should have failed");
}
catch (SortingException e) {
Element[] conflictingElements = e.getConflictingElements();
assertEquals(expectedCount, conflictingElements.length);
for (int i = 0; i < conflictingElements.length; i++) {
MyElement conflictingElement = (MyElement) conflictingElements[i];
assertEquals("bad", conflictingElement.getID());
}
}
}
public void testFailingSortingAfterLast() {
ArrayList target = new ArrayList();
target.add(createElement(LoadingOrder.after("last"), null, "bad"));
target.add(createElement(LoadingOrder.FIRST, null, "good"));
target.add(createElement(LoadingOrder.LAST, "last", "bad"));
target.add(createElement(LoadingOrder.ANY, null, "good"));
LoadingOrder.Orderable[] array = (LoadingOrder.Orderable[]) target.toArray(new LoadingOrder.Orderable[target.size()]);
checkSortingFailure(array, 2);
}
public void testFailingSortingLast() {
ArrayList target = new ArrayList();
target.add(createElement(LoadingOrder.LAST, null, "bad"));
target.add(createElement(LoadingOrder.FIRST, null, "good"));
target.add(createElement(LoadingOrder.LAST, "last", "bad"));
target.add(createElement(LoadingOrder.ANY, null, "good"));
LoadingOrder.Orderable[] array = (LoadingOrder.Orderable[]) target.toArray(new LoadingOrder.Orderable[target.size()]);
checkSortingFailure(array, 2);
}
public void testFailingSortingComplex() {
ArrayList target = new ArrayList();
target.add(createElement(LoadingOrder.after("2"), "1", "bad"));
target.add(createElement(LoadingOrder.after("3"), "2", "bad"));
target.add(createElement(LoadingOrder.after("1"), "3", "bad"));
LoadingOrder.Orderable[] array = (LoadingOrder.Orderable[]) target.toArray(new LoadingOrder.Orderable[target.size()]);
checkSortingFailure(array, 3);
}
private LoadingOrder.Orderable createElement(LoadingOrder order, String idString, String elementId) {
Mock mock = new Mock(LoadingOrder.Orderable.class);
mock.stubs().method("getOrder").withNoArguments().will(new ReturnStub(order));
mock.stubs().method("getOrderId").withNoArguments().will(returnValue(idString));
mock.stubs().method("getDescribingElement").withNoArguments().will(new ReturnStub(new MyElement(elementId)));
return (LoadingOrder.Orderable) mock.proxy();
}
private static class MyElement extends Element {
private String myID;
public MyElement(String ID) {
myID = ID;
}
public String getID() {
return myID;
}
}
}

View File

@@ -0,0 +1,27 @@
/*
* 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 TestExtensionClassOne {
private String myText;
public TestExtensionClassOne() {
}
public TestExtensionClassOne(String text) {
myText = text;
}
public String getText() {
return myText;
}
public void setText(String text) {
myText = text;
}
}

BIN
lib/dev/jmock-1.0.1.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/xstream.jar Normal file

Binary file not shown.