summaryrefslogtreecommitdiffstats
blob: 4022a224ea80ef1b9e6e3697ad9d53a7f9e8f312 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*******************************************************************************
 * 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.util;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

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;

/**
 * ExtensionUtility maps Extensions to Interfaces. Extension properties can then be read by access the getters in the
 * interface definition. ExtensionUtility instantiates generic proxies to do this.
 * 
 * The ExtensionUtility does not know the schema so it can only trust that the extension and the interface match.
 * 
 */
public class ExtensionUtility {

    /**
     * Static method to read extensions
     * 
     * @param extensionPoint
     * @param interf
     * @return
     */
    public static <T> T[] readExtensions(String extensionPoint, Class<T> interf) {
        IExtensionRegistry registry = RegistryFactory.getRegistry();
        IExtensionPoint extPoint = registry.getExtensionPoint(extensionPoint);
        if (extPoint == null) {
            return null;
        }
        IExtension[] cfgExtensions = extPoint.getExtensions();
        if (cfgExtensions.length == 0) {
            return null;
        }
        T[] objects = (T[]) Array.newInstance(interf, cfgExtensions.length);
        int i = 0;
        for (IExtension cfgExt : cfgExtensions) {
            Array.set(objects, i++, Proxy.newProxyInstance(interf.getClassLoader(), new Class[] { interf }, new InterfaceInvocationHandler(cfgExt
                    .getConfigurationElements()[0], interf)));
        }
        return objects;
    }

    /**
     * InvocationHandler for managing proxies for the extension to interface proxy mapping
     * 
     */
    private static class InterfaceInvocationHandler implements InvocationHandler {

        private IConfigurationElement config;
        private Class<?> interf;

        InterfaceInvocationHandler(IConfigurationElement config, Class<?> interf) {
            this.config = config;
            this.interf = interf;
        }

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().startsWith("get")) {
                Method[] meths = interf.getMethods();
                for (Method meth : meths) {
                    if (meth.getName().equals(method.getName())) {
                        Class<?> retType = meth.getReturnType();
                        String name = method.getName().substring("get".length());
                        name = name.substring(0, 1).toLowerCase() + name.substring(1);
                        if (retType.equals(String.class)) {
                            return config.getAttribute(name);
                        } else if (retType.equals(Boolean.TYPE)) {
                            return Boolean.valueOf(config.getAttribute(name));
                        } else if (retType.isInterface()) {
                            IConfigurationElement cfgElement = config.getChildren(name)[0];
                            if (cfgElement == null) {
                                return null;
                            }
                            return Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { retType }, new InterfaceInvocationHandler(cfgElement,
                                    retType));
                        }
                    }
                }
                throw new UnsupportedOperationException("property for method " + method.getName() + " not found.");
            }
            if (method.getName().startsWith("create")) {
                String name = method.getName().substring("create".length());
                name = name.substring(0, 1).toLowerCase() + name.substring(1);
                return config.createExecutableExtension(name);
            }
            throw new UnsupportedOperationException("only getXXX or createXXX is supported");
        }
    }

}