summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Liebig2008-03-11 11:05:01 (EDT)
committerStefan Liebig2008-03-11 11:05:01 (EDT)
commitca6f5427d740f8614b0809c9fa8124bbbc6a69e1 (patch)
tree8bd96f34b31eb98f3ccb53eeab68b213ba771292
parentafee7ca3d65f253882c91c07ab386f3fad8c30cb (diff)
downloadorg.eclipse.riena-ca6f5427d740f8614b0809c9fa8124bbbc6a69e1.zip
org.eclipse.riena-ca6f5427d740f8614b0809c9fa8124bbbc6a69e1.tar.gz
org.eclipse.riena-ca6f5427d740f8614b0809c9fa8124bbbc6a69e1.tar.bz2
first attempt of extension injector
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/extension/ExtensionId.java105
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/extension/ExtensionInjector.java266
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/extension/ExtensionReader.java139
-rw-r--r--org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/ConfigurableThingMultipleData.java28
-rw-r--r--org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/ConfigurableThingSingleData.java28
-rw-r--r--org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/ExtensionInjectorTest.java92
-rw-r--r--org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/IData.java23
-rw-r--r--org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/extpoint.exsd112
-rw-r--r--org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin.xml5
-rw-r--r--org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin_ext1.xml11
-rw-r--r--org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin_ext2.xml11
-rw-r--r--org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin_ext3.xml11
12 files changed, 831 insertions, 0 deletions
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/extension/ExtensionId.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/extension/ExtensionId.java
new file mode 100644
index 0000000..610e0aa
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/extension/ExtensionId.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 compeople AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.extension;
+
+import org.eclipse.core.runtime.Assert;
+
+/**
+ *
+ */
+public class ExtensionId {
+
+ private String extensionPointId;
+ private Class<?> interfaceType;
+ private int minOccurences = 0;
+ private int maxOccurences = UNBOUNDED;
+
+ public static final int UNBOUNDED = Integer.MAX_VALUE;
+
+ /**
+ * @param extensionPointId
+ * @param interfaceType
+ */
+ public ExtensionId(String extensionPointId, Class<?> interfaceType) {
+ Assert.isNotNull(extensionPointId, "The extension id must not be null."); //$NON-NLS-1$
+ this.extensionPointId = extensionPointId;
+ this.interfaceType = interfaceType;
+ }
+
+ /**
+ * @param extension
+ */
+ public ExtensionId(String extension) {
+ this(extension, null);
+ }
+
+ /**
+ * @param target
+ */
+ public ExtensionInjector injectInto(Object target) {
+ Assert.isNotNull(target, "The target must not be null."); //$NON-NLS-1$
+ return new ExtensionInjector(this, target);
+ }
+
+ /**
+ * @param min
+ * @param max
+ * @return
+ */
+ public ExtensionId expectingMinMax(int min, int max) {
+ Assert.isLegal(max >= min, "min must not be greater than max.");
+ Assert.isLegal(min >= 0, "min must be greater or equal than zero.");
+ Assert.isLegal(max > 0, "min must be greater than zero.");
+ this.minOccurences = min;
+ this.maxOccurences = max;
+ return this;
+ }
+
+ /**
+ * @param exactly
+ * @return
+ */
+ public ExtensionId expectingExactly(int exactly) {
+ return expectingMinMax(exactly, exactly);
+ }
+
+ /**
+ * @return the extension point id
+ */
+ String getExtensionPointId() {
+ return extensionPointId;
+ }
+
+ /**
+ * @return the interfaceType
+ */
+ Class<?> getInterfaceType() {
+ return interfaceType;
+ }
+
+ /**
+ * @return the minOccurences
+ */
+ int getMinOccurences() {
+ return minOccurences;
+ }
+
+ /**
+ * @return the maxOccurences
+ */
+ int getMaxOccurences() {
+ return maxOccurences;
+ }
+
+ boolean requiresArrayUpdateMethod() {
+ return minOccurences > 1 || maxOccurences > 1;
+ }
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/extension/ExtensionInjector.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/extension/ExtensionInjector.java
new file mode 100644
index 0000000..39aca20
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/extension/ExtensionInjector.java
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 compeople AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.extension;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IRegistryEventListener;
+import org.eclipse.core.runtime.RegistryFactory;
+import org.eclipse.equinox.log.Logger;
+import org.eclipse.riena.core.logging.ConsoleLogger;
+import org.osgi.service.log.LogService;
+
+/**
+ *
+ */
+public class ExtensionInjector {
+
+ private ExtensionId extensionId;
+ private Object target;
+ private boolean started;
+ private boolean track = true;
+ private String updateMethodName = "update"; //$NON-NLS-1$
+ private Method updateMethod;
+ private IRegistryEventListener injectorListener;
+ private boolean isArray;
+ private Class<?> componentType;
+
+ private final static Logger LOGGER = new ConsoleLogger(ExtensionInjector.class.getName());
+
+ /**
+ * @param extensionId
+ * @param target
+ */
+ ExtensionInjector(ExtensionId extensionId, Object target) {
+ this.extensionId = extensionId;
+ this.target = target;
+ }
+
+ /**
+ *
+ * @param context
+ */
+ public ExtensionInjector andStart() {
+ Assert.isTrue(!started, "ExtensionInjector already started.");
+ started = true;
+
+ updateMethod = findUpdateMethod();
+ Class<?> paramaterType = updateMethod.getParameterTypes()[0];
+ isArray = paramaterType.isArray();
+ componentType = isArray ? paramaterType.getComponentType() : paramaterType;
+ populateInterfaceBeans();
+
+ if (track) {
+ IExtensionRegistry extensionRegistry = RegistryFactory.getRegistry();
+ if (extensionRegistry == null)
+ // TODO Is this an error for that we should throw an exception?
+ LOGGER.log(LogService.LOG_ERROR,
+ "For some reason the extension registry has not been created. Tracking is not possible.");
+ else {
+ injectorListener = new InjectorListener();
+ extensionRegistry.addListener(injectorListener, extensionId.getExtensionPointId());
+ }
+ }
+ return this;
+ }
+
+ /**
+ * @param updateMethodName
+ */
+ public ExtensionInjector bind(String bindMethodName) {
+ Assert.isNotNull(bindMethodName, "Bind method name must not be null");
+ Assert.isTrue(!started, "ExtensionInjector already started.");
+ this.updateMethodName = bindMethodName;
+ return this;
+ }
+
+ /**
+ * @return
+ */
+ public ExtensionInjector doNotTrack() {
+ Assert.isTrue(!started, "ExtensionInjector already started.");
+ Assert.isTrue(!this.track, "Not tracking is already set.");
+ track = false;
+ return this;
+ }
+
+ /**
+ *
+ */
+ public void stop() {
+ if (!started)
+ return;
+
+ if (track) {
+ IExtensionRegistry extensionRegistry = RegistryFactory.getRegistry();
+ if (extensionRegistry == null)
+ // TODO Is this an error for that we should throw an exception?
+ LOGGER.log(LogService.LOG_ERROR, "For some reason the extension registry has not been created.");
+ else
+ extensionRegistry.removeListener(injectorListener);
+ }
+ extensionId = null;
+ injectorListener = null;
+ }
+
+ /**
+ */
+ private Method findUpdateMethod() {
+ if (extensionId.getInterfaceType() == null) {
+ // determine interface type (array?) and method from update method
+ // name
+ return findUpdateMethodForUnkownType();
+ } else {
+ // determine method from update method name
+ return findUpdateMethodForKownType();
+ }
+ }
+
+ /**
+ * @return
+ */
+ private Method findUpdateMethodForKownType() {
+ try {
+ if (extensionId.requiresArrayUpdateMethod()) {
+ Class<?> interfaceType = Array.newInstance(extensionId.getInterfaceType(), 0).getClass();
+ return target.getClass().getMethod(updateMethodName, interfaceType);
+ }
+
+ try {
+ return target.getClass().getMethod(updateMethodName, extensionId.getInterfaceType());
+ } catch (NoSuchMethodException e) {
+ // retry with array
+ Class<?> beanType = Array.newInstance(extensionId.getInterfaceType(), 0).getClass();
+ return target.getClass().getMethod(updateMethodName, beanType);
+ }
+
+ } catch (SecurityException e) {
+ throw new IllegalStateException("Could not find a ībindī method.", e);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("Could not find a ībindī method.", e);
+ }
+
+ }
+
+ private Method findUpdateMethodForUnkownType() {
+ List<Method> candidates = new ArrayList<Method>();
+ Method[] methods = target.getClass().getMethods();
+ for (Method method : methods)
+ if (method.getName().equals(updateMethodName) && method.getParameterTypes().length == 1
+ && isInterface(method.getParameterTypes()[0]))
+ candidates.add(method);
+
+ if (candidates.size() == 0)
+ throw new IllegalStateException("No suitable ībindī method found.");
+
+ if (candidates.size() == 1)
+ if (matchesExtensionPointConstraint(candidates.get(0).getParameterTypes()[0]))
+ return candidates.get(0);
+ else
+ throw new IllegalStateException("Found method " + candidates.get(0)
+ + " does not match extension point constraints.");
+
+ if (candidates.size() > 2)
+ throw new IllegalStateException("Too much (>2) candidates (" + candidates + ") for ībindī method.");
+
+ if (matchesExtensionPointConstraint(candidates.get(0).getParameterTypes()[0]))
+ return candidates.get(0);
+
+ if (matchesExtensionPointConstraint(candidates.get(1).getParameterTypes()[0]))
+ return candidates.get(1);
+
+ throw new IllegalStateException("No suitable candidate from (" + candidates + ") found for ībindī method.");
+ }
+
+ /**
+ * @param type
+ * @return
+ */
+ private boolean isInterface(Class<?> type) {
+ type = type.isArray() ? type.getComponentType() : type;
+ return type.isInterface();
+ }
+
+ /**
+ * @param type
+ * @return
+ */
+ private boolean matchesExtensionPointConstraint(Class<?> type) {
+ return !extensionId.requiresArrayUpdateMethod() || type.isArray();
+ }
+
+ void populateInterfaceBeans() {
+ Object[] beans = ExtensionReader.read(extensionId.getExtensionPointId(), componentType);
+ if (!matchesExtensionPointConstraint(beans.length))
+ LOGGER.log(LogService.LOG_ERROR, "Number of extensions does not fullfil the extenion pointīs constraints.");
+ try {
+ if (isArray) {
+ updateMethod.invoke(target, new Object[] { beans });
+ } else {
+ updateMethod.invoke(target, new Object[] { beans.length > 0 ? beans[0] : null });
+ }
+ } catch (IllegalArgumentException e) {
+ throw new IllegalStateException("Calling ībindī method fails.", e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException("Calling ībindī method fails.", e);
+ } catch (InvocationTargetException e) {
+ throw new IllegalStateException("Calling ībindī method fails.", e);
+ }
+ }
+
+ private boolean matchesExtensionPointConstraint(int occurence) {
+ return occurence >= extensionId.getMinOccurences() && occurence <= extensionId.getMaxOccurences();
+ }
+
+ /**
+ *
+ */
+ private class InjectorListener implements IRegistryEventListener {
+
+ /*
+ * @see org.eclipse.core.runtime.IRegistryEventListener#added(org.eclipse.core.runtime.IExtension[])
+ */
+ public void added(IExtension[] extensions) {
+ populateInterfaceBeans();
+ }
+
+ /*
+ * @see org.eclipse.core.runtime.IRegistryEventListener#added(org.eclipse.core.runtime.IExtensionPoint[])
+ */
+ public void added(IExtensionPoint[] extensionPoints) {
+ populateInterfaceBeans();
+ }
+
+ /*
+ * @see org.eclipse.core.runtime.IRegistryEventListener#removed(org.eclipse.core.runtime.IExtension[])
+ */
+ public void removed(IExtension[] extensions) {
+ populateInterfaceBeans();
+ }
+
+ /*
+ * @see org.eclipse.core.runtime.IRegistryEventListener#removed(org.eclipse.core.runtime.IExtensionPoint[])
+ */
+ public void removed(IExtensionPoint[] extensionPoints) {
+ populateInterfaceBeans();
+ }
+
+ }
+
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/extension/ExtensionReader.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/extension/ExtensionReader.java
new file mode 100644
index 0000000..4ddd597
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/extension/ExtensionReader.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.extension;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.RegistryFactory;
+
+/**
+ * ExtensionReader maps Extensions to Interfaces. Extension properties can then
+ * be read by access the getters in the interface definition. ExtensionReader
+ * instantiates generic proxies to do this.<br>
+ *
+ * The ExtensionReader does not know the schema so it can only trust that the
+ * extension and the interface match.
+ */
+public class ExtensionReader {
+
+ /**
+ * Static method to read extensions
+ *
+ * @param extensionPoint
+ * @param interfaceType
+ * @return
+ */
+ public static <T> T[] read(String extensionPointId, Class<T> interfaceType) {
+ IExtensionRegistry extensionRegistry = RegistryFactory.getRegistry();
+ IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(extensionPointId);
+ if (extensionPoint == null)
+ throw new IllegalArgumentException("Extension point " + extensionPointId + " does not exist");
+
+ IExtension[] extensions = extensionPoint.getExtensions();
+ if (extensions.length == 0)
+ return (T[]) Array.newInstance(interfaceType, 0);
+
+ List<Object> list = new ArrayList<Object>();
+ for (IExtension extension : extensions)
+ for (IConfigurationElement element : extension.getConfigurationElements())
+ list.add(Proxy.newProxyInstance(interfaceType.getClassLoader(), new Class[] { interfaceType },
+ new InterfaceInvocationHandler(element)));
+
+ T[] objects = (T[]) Array.newInstance(interfaceType, list.size());
+ return list.toArray(objects);
+ }
+
+ /**
+ * InvocationHandler for managing proxies for the extension to interface
+ * proxy mapping
+ *
+ */
+ private static class InterfaceInvocationHandler implements InvocationHandler {
+
+ private IConfigurationElement configurationElement;
+ private static final String CREATE_METHOD_PREFIX = "create"; //$NON-NLS-1$
+ private static final String IS_METHOD_PREFIX = "is"; //$NON-NLS-1$
+ private static final String GETTER_METHOD_PREFIX = "get"; //$NON-NLS-1$
+ private static final String[] ALLOWED_PREFIXES = { GETTER_METHOD_PREFIX, IS_METHOD_PREFIX, CREATE_METHOD_PREFIX };
+
+ InterfaceInvocationHandler(IConfigurationElement configurationElement) {
+ this.configurationElement = configurationElement;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (method.getName().startsWith(GETTER_METHOD_PREFIX) || method.getName().startsWith(IS_METHOD_PREFIX)) {
+ Class<?> returnType = method.getReturnType();
+ String name = method.getName().startsWith(GETTER_METHOD_PREFIX) ? getAttributeName(method,
+ GETTER_METHOD_PREFIX) : getAttributeName(method, IS_METHOD_PREFIX);
+
+ if (returnType == String.class)
+ return intercept(configurationElement.getAttribute(name));
+ if (returnType.isPrimitive())
+ return coerce(returnType, intercept(configurationElement.getAttribute(name)));
+ if (returnType.isInterface()) {
+ IConfigurationElement cfgElement = configurationElement.getChildren(name)[0];
+ if (cfgElement == null) {
+ return null;
+ }
+ return Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { returnType },
+ new InterfaceInvocationHandler(cfgElement));
+ }
+ throw new UnsupportedOperationException("property for method " + method.getName() + " not found.");
+ }
+ if (method.getName().startsWith(CREATE_METHOD_PREFIX)) {
+ String name = getAttributeName(method, CREATE_METHOD_PREFIX);
+ return configurationElement.createExecutableExtension(name);
+ }
+ throw new UnsupportedOperationException("Only " + Arrays.toString(ALLOWED_PREFIXES) + " are supported.");
+ }
+
+ private String getAttributeName(Method method, String prefix) {
+ String name = method.getName().substring(prefix.length());
+ return name.substring(0, 1).toLowerCase() + name.substring(1);
+ }
+
+ private Object coerce(Class<?> toType, String value) {
+ if (toType == Long.TYPE)
+ return Long.valueOf(value);
+ if (toType == Integer.TYPE)
+ return Integer.valueOf(value);
+ if (toType == Boolean.TYPE)
+ return Boolean.valueOf(value);
+ if (toType == Float.TYPE)
+ return Float.valueOf(value);
+ if (toType == Double.TYPE)
+ return Double.valueOf(value);
+ if (toType == Short.TYPE)
+ return Short.valueOf(value);
+ if (toType == Character.TYPE)
+ return Character.valueOf(value.charAt(0));
+ if (toType == Byte.TYPE)
+ return Byte.valueOf(value);
+ return value;
+ }
+
+ private String intercept(String value) {
+ // TODO Place to intercept the values with ConfigurationPlugin
+ return value;
+ }
+ }
+
+}
diff --git a/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/ConfigurableThingMultipleData.java b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/ConfigurableThingMultipleData.java
new file mode 100644
index 0000000..6a0504c
--- /dev/null
+++ b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/ConfigurableThingMultipleData.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 compeople AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.extension;
+
+/**
+ *
+ */
+public class ConfigurableThingMultipleData {
+
+ private IData[] data;
+
+ public void update(IData[] data) {
+ this.data = data;
+ }
+
+ public IData[] getData() {
+ return data;
+ }
+
+}
diff --git a/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/ConfigurableThingSingleData.java b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/ConfigurableThingSingleData.java
new file mode 100644
index 0000000..9c2780b
--- /dev/null
+++ b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/ConfigurableThingSingleData.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 compeople AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.extension;
+
+/**
+ *
+ */
+public class ConfigurableThingSingleData {
+
+ private IData data;
+
+ public void configure(IData data) {
+ this.data = data;
+ }
+
+ public IData getData() {
+ return data;
+ }
+
+}
diff --git a/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/ExtensionInjectorTest.java b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/ExtensionInjectorTest.java
new file mode 100644
index 0000000..0aa1897
--- /dev/null
+++ b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/ExtensionInjectorTest.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 compeople AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.extension;
+
+import java.util.HashMap;
+
+import org.eclipse.riena.tests.RienaTestCase;
+import org.osgi.framework.BundleContext;
+
+/**
+ *
+ */
+public class ExtensionInjectorTest extends RienaTestCase {
+
+ public void scribble() {
+ BundleContext context = null;
+ new ExtensionId("", Object.class).expectingMinMax(0, 1).injectInto(this).andStart();
+ new ExtensionId("", Object.class).expectingExactly(1).injectInto(this).bind("update").andStart();
+ new ExtensionId("").injectInto(this).doNotTrack().andStart().stop();
+
+ }
+
+ public void testWithKnownTypeAndMultipleData() {
+ printTestName();
+ addPluginXml(ExtensionInjectorTest.class, "plugin.xml");
+ addPluginXml(ExtensionInjectorTest.class, "plugin_ext1.xml");
+ addPluginXml(ExtensionInjectorTest.class, "plugin_ext2.xml");
+ addPluginXml(ExtensionInjectorTest.class, "plugin_ext3.xml");
+ ConfigurableThingMultipleData target = new ConfigurableThingMultipleData();
+ new ExtensionId("core.test.extpoint", IData.class).injectInto(target).andStart();
+ assertEquals(3, target.getData().length);
+ removeExtension("core.test.extpoint.id1");
+ removeExtension("core.test.extpoint.id2");
+ removeExtension("core.test.extpoint.id3");
+ removeExtensionPoint("core.test.extpoint");
+ }
+
+ public void testWithUnknownTypeAndMultipleData() {
+ printTestName();
+ addPluginXml(ExtensionInjectorTest.class, "plugin.xml");
+ addPluginXml(ExtensionInjectorTest.class, "plugin_ext1.xml");
+ addPluginXml(ExtensionInjectorTest.class, "plugin_ext2.xml");
+ addPluginXml(ExtensionInjectorTest.class, "plugin_ext3.xml");
+ ConfigurableThingMultipleData target = new ConfigurableThingMultipleData();
+ new ExtensionId("core.test.extpoint").injectInto(target).andStart();
+ assertEquals(3, target.getData().length);
+ removeExtension("core.test.extpoint.id1");
+ removeExtension("core.test.extpoint.id2");
+ removeExtension("core.test.extpoint.id3");
+ removeExtensionPoint("core.test.extpoint");
+ }
+
+ public void testWithKnownTypeAndSingleData() {
+ printTestName();
+ addPluginXml(ExtensionInjectorTest.class, "plugin.xml");
+ addPluginXml(ExtensionInjectorTest.class, "plugin_ext1.xml");
+ ConfigurableThingSingleData target = new ConfigurableThingSingleData();
+ new ExtensionId("core.test.extpoint", IData.class).expectingExactly(1).injectInto(target).bind("configure")
+ .andStart();
+ assertNotNull(target.getData());
+ assertTrue(target.getData().getBoolean());
+ assertTrue(target.getData().isBoolean());
+ assertEquals("test1", target.getData().getString());
+ assertEquals(String.class, target.getData().createExecutable().getClass());
+ removeExtension("core.test.extpoint.id1");
+ removeExtensionPoint("core.test.extpoint");
+ }
+
+ public void testWithUnknownTypeAndSingleData() {
+ printTestName();
+ addPluginXml(ExtensionInjectorTest.class, "plugin.xml");
+ addPluginXml(ExtensionInjectorTest.class, "plugin_ext2.xml");
+ ConfigurableThingSingleData target = new ConfigurableThingSingleData();
+ new ExtensionId("core.test.extpoint").expectingExactly(1).injectInto(target).bind("configure").andStart();
+ assertNotNull(target.getData());
+ assertFalse(target.getData().getBoolean());
+ assertFalse(target.getData().isBoolean());
+ assertEquals("test2", target.getData().getString());
+ assertEquals(HashMap.class, target.getData().createExecutable().getClass());
+ removeExtension("core.test.extpoint.id2");
+ removeExtensionPoint("core.test.extpoint");
+ }
+
+}
diff --git a/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/IData.java b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/IData.java
new file mode 100644
index 0000000..1efbb10
--- /dev/null
+++ b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/IData.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.extension;
+
+public interface IData {
+
+ String getString();
+
+ boolean getBoolean();
+
+ boolean isBoolean();
+
+ Object createExecutable();
+
+}
diff --git a/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/extpoint.exsd b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/extpoint.exsd
new file mode 100644
index 0000000..3add169
--- /dev/null
+++ b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/extpoint.exsd
@@ -0,0 +1,112 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="de.compeople.scp.core.tests" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appinfo>
+ <meta.schema plugin="de.compeople.scp.core.tests" id="core.test.extpoint" name="extpoint"/>
+ </appinfo>
+ <documentation>
+ [Enter description of this extension point.]
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence minOccurs="1" maxOccurs="unbounded">
+ <element ref="test"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appinfo>
+ <meta.attribute translatable="true"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="test">
+ <complexType>
+ <attribute name="string" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="boolean" type="boolean">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="executable" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="java"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="since"/>
+ </appinfo>
+ <documentation>
+ [Enter the first release in which this extension point appears.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="examples"/>
+ </appinfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="apiInfo"/>
+ </appinfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+
+ <annotation>
+ <appinfo>
+ <meta.section type="implementation"/>
+ </appinfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+
+</schema>
diff --git a/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin.xml b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin.xml
new file mode 100644
index 0000000..984625a
--- /dev/null
+++ b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+ <extension-point id="core.test.extpoint" name="core test extensionpoint" schema="extpoint.exsd"/>
+</plugin>
diff --git a/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin_ext1.xml b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin_ext1.xml
new file mode 100644
index 0000000..7375b95
--- /dev/null
+++ b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin_ext1.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+ <extension id="core.test.extpoint.id1" point="core.test.extpoint">
+ <test
+ boolean="true"
+ executable="java.lang.String"
+ string="test1">
+ </test>
+ </extension>
+</plugin>
diff --git a/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin_ext2.xml b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin_ext2.xml
new file mode 100644
index 0000000..4a14d89
--- /dev/null
+++ b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin_ext2.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+ <extension id="core.test.extpoint.id2" point="core.test.extpoint">
+ <test
+ boolean="false"
+ executable="java.util.HashMap"
+ string="test2">
+ </test>
+ </extension>
+</plugin>
diff --git a/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin_ext3.xml b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin_ext3.xml
new file mode 100644
index 0000000..b125d1b
--- /dev/null
+++ b/org.eclipse.riena.tests/src/org/eclipse/riena/core/extension/plugin_ext3.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+ <extension id="core.test.extpoint.id3" point="core.test.extpoint">
+ <test
+ boolean="true"
+ executable="java.util.ArrayList"
+ string="test3">
+ </test>
+ </extension>
+</plugin>