Skip to main content
summaryrefslogtreecommitdiffstats
blob: 1ad2882f0a92661c4a8d1c0c9db5ef42b2d54379 (plain) (blame)
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* 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:
*    Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation

*******************************************************************************/

package org.eclipse.imp.utils;

import java.net.URL;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IContributor;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.Platform;
import org.eclipse.imp.language.ILanguageService;
import org.eclipse.imp.language.Language;
import org.eclipse.imp.language.LanguageRegistry;
import org.eclipse.imp.runtime.RuntimePlugin;
import org.osgi.framework.Bundle;

/*
 * Licensed Materials - Property of IBM, (c) Copyright IBM Corp. 2005 All Rights
 * Reserved
 */

/**
 * @author Claffra
 * @author rfuhrer@watson.ibm.com
 * @author jurgen@vinju.org
 */
public class ExtensionFactory {
    
    /**
     * Locate the first extension that matches this language and extension point id,
     * and load the class that implements it and return a handle to an object of that class.
     * 
     * @param language
     * @param extensionPointID
     * @return
     * @throws ExtensionException
     */
    public static ILanguageService createServiceExtension(Language language,
            String extensionPointID) throws ExtensionException {
        return createServiceExtensionForPlugin(language, RuntimePlugin.IMP_RUNTIME,
                extensionPointID);
    }

    /**
     * Locate all extensions that match the language and extension point id, load their
     * classes and collect handles to objects of that class in a set.
     * @param language
     * @param extensionPointID
     * @return
     * @throws ExtensionException
     */
    public static Set<ILanguageService> createServiceExtensionSet(Language language,
            String extensionPointID) throws ExtensionException {
        return createServiceExtensionSetForPlugin(language, RuntimePlugin.IMP_RUNTIME,
                extensionPointID);
    }

    /**
     * Find a language name in a language descriptor extension.
     * 
     * @param pluginID
     * @return
     */
    public static String retrieveLanguageIdFromPlugin(String pluginID) {
        IExtensionPoint extensionPoint = Platform.getExtensionRegistry()
                .getExtensionPoint(RuntimePlugin.IMP_RUNTIME,
                        RuntimePlugin.LANGUAGE_DESCRIPTOR);
        IConfigurationElement[] configElements = extensionPoint
                .getConfigurationElements();

        for (int i = 0; i < configElements.length; i++) {
            IContributor contrib = configElements[i].getContributor();

            if (contrib.getName().equals(pluginID)) {
                return configElements[i]
                        .getAttribute(Language.LANGUAGE_ID_ATTR);
            }
        }

        return null;
    }

    /**
     * Locate the first extension that matches this language, plugin, and extensionpoint id,
     * then load a class from the element named 'elementName', and return a handle to an
     * object of this class.
     * 
     * @param language
     * @param pluginID
     * @param extensionPointId
     * @param elementName
     * @return
     * @throws ExtensionException
     */
    public static ILanguageService createServiceExtensionForPlugin(
            Language language, String pluginID, String extensionPointId,
            String elementName) throws ExtensionException {
        IExtensionPoint extensionPoint = Platform.getExtensionRegistry()
                .getExtensionPoint(pluginID, extensionPointId);

        if (extensionPoint == null) {
            throw new ExtensionException(
                    "No such language service extension point defined: "
                            + pluginID + "." + extensionPointId);
        }

        ILanguageService service = getLanguageServiceForElement(
                extensionPoint, language.getName(), elementName);

        if (service == null && languageIsDerived(language)) {
            service = createServiceExtensionForPlugin(LanguageRegistry
                    .findLanguage(language.getDerivedFrom()), pluginID,
                    extensionPointId, elementName);
        }

        return service;
    }

    /**
     * Detmermine wether a language was declared to be derived from another language,
     * and whether this other language actually is registered.
     * @param language
     * @return
     */
    private static boolean languageIsDerived(Language language) {
        final boolean hasParent = language.getDerivedFrom() != null
                && LanguageRegistry.findLanguage(language.getDerivedFrom()) != null;
        return hasParent;
    }

    /**
     * Finds the first extension that matches this language, plugin and extension point id,
     * and then loads the class that implements this extension and returns a handle to it.
     * 
     * @param language
     * @param pluginID
     * @param extensionPointId
     * @return
     * @throws ExtensionException
     */
    public static ILanguageService createServiceExtensionForPlugin(Language language,
            String pluginID, String extensionPointId) throws ExtensionException {
        return createServiceExtensionForPlugin(language, pluginID,
                extensionPointId, "class");
    }

    /**
     * Find all extensions that match this pluginId, language and extension point id,
     * then loads the classes that implement these extenstions and returns them as 
     * a set of ILanguageServices.
     * 
     * @param language
     * @param pluginID
     * @param extensionPointId
     * @return
     * @throws ExtensionException
     */
    public static Set<ILanguageService> createServiceExtensionSetForPlugin(Language language,
            String pluginID, String extensionPointId) throws ExtensionException {
        IExtensionPoint extensionPoint = Platform.getExtensionRegistry()
                .getExtensionPoint(pluginID, extensionPointId);

        if (extensionPoint == null) {
            throw new ExtensionException(
                    "No such language service extension point defined: "
                            + pluginID + "." + extensionPointId);
        }

        Set<ILanguageService> services = getLanguageServiceSet(
                extensionPoint, language.getName());

        if (services.isEmpty() && languageIsDerived(language)) {
            final ILanguageService baseServiceImpl = createServiceExtensionForPlugin(
                    LanguageRegistry.findLanguage(language.getDerivedFrom()),
                    pluginID, extensionPointId);
            if (baseServiceImpl != null) {
                services.add(baseServiceImpl);
            }
        }

        return services;
    }

    /**
     * detect whether a certain plugin defines a certain extension for a certain language
     * @param pluginID
     * @param extensionPointID
     * @param language
     * @return
     */
    @SuppressWarnings("deprecation")
    public static boolean languageServiceExists(String pluginID,
            String extensionPointID, Language language) {
        if (language == null)
            return false;

        IExtensionPoint extensionPoint = Platform.getExtensionRegistry()
                .getExtensionPoint(pluginID, extensionPointID);
        IConfigurationElement[] elements = extensionPoint
                .getConfigurationElements();
        String lowerLang = language.getName().toLowerCase();

        if (elements != null) {
            for (int n = 0; n < elements.length; n++) {
                IConfigurationElement element = elements[n];
                Bundle bundle = Platform.getBundle(element
                        .getDeclaringExtension().getNamespace());

                if (bundle != null) {
                    final String attrValue = element
                            .getAttribute(Language.LANGUAGE_ID_ATTR);

                    if (attrValue != null
                            && lowerLang.equals(attrValue.toLowerCase())) {
                        return true;
                    }
                }
            }
        }

        if (languageIsDerived(language)) {
            return languageServiceExists(pluginID, extensionPointID,
                    LanguageRegistry.findLanguage(language.getDerivedFrom()));
        }

        return false;
    }

    /**
     * Locates all elements that match the language and the particular extension point id,
     * and returns a set of loaded ILanguageServices using these elements.
     * @param extensionPoint
     * @param language
     * @return
     * @throws ExtensionException
     */
    private static Set<ILanguageService> getLanguageServiceSet(
            IExtensionPoint extensionPoint, String language)
            throws ExtensionException {
        IConfigurationElement[] elements = extensionPoint
                .getConfigurationElements();
        Set<ILanguageService> result = new HashSet<ILanguageService>();

        if (elements != null) {
            for (int n = 0; n < elements.length; n++) {
                IConfigurationElement element = elements[n];
                ILanguageService service = loadLanguageService(extensionPoint, language, "class", element);
                
                if (service != null) {
                    result.add(service);
                }
            }
        }

        return result;
    }

    /**
     * Locates the first element that matches the ,anguage and the elementName, 
     * and tries to load a language service from it.
     * 
     * @param extensionPoint
     * @param language
     * @param elementName
     * @return
     * @throws ExtensionException
     */
    private static ILanguageService getLanguageServiceForElement(
            IExtensionPoint extensionPoint, String language, String elementName)
            throws ExtensionException {
        IConfigurationElement[] elements = extensionPoint
                .getConfigurationElements();
       
        if (elements != null) {
            for (int n = 0; n < elements.length; n++) {
                IConfigurationElement element = elements[n];
                ILanguageService service = loadLanguageService(extensionPoint, language, elementName, element);
                if (service != null) {
                    return service;
                }
            }
        }

        return null;
    }

    /**
     * Convenience method for actuallys creating an object from an element in an
     * extension point. Catches common exceptions that may be thrown and tries to
     * translate them into ServiceExceptions.
     * 
     * @param extensionPoint
     * @param language
     * @param elementName
     * @param element
     * @return
     * @throws ExtensionException
     */
    @SuppressWarnings("deprecation")
    private static ILanguageService loadLanguageService(IExtensionPoint extensionPoint, String language, String elementName, IConfigurationElement element) throws ExtensionException {
        Bundle bundle = Platform.getBundle(element
                .getDeclaringExtension().getNamespace());
        String lowerLang = language.toLowerCase();

        if (bundle != null) {
            final String attrValue = element
                    .getAttribute(Language.LANGUAGE_ID_ATTR);

            if (attrValue != null
                    && lowerLang.equals(attrValue.toLowerCase())) {
                try {
                    return (ILanguageService) element
                            .createExecutableExtension(elementName);
                } catch (ClassCastException e) {
                    throw new ExtensionException(
                            "Extension does not point to a class that implements an ILanguageService:"
                                    + element, e);
                } catch (IncompatibleClassChangeError e) {
                    throw new ExtensionException("Unable to instantiate implementation of "
                            + extensionPoint.getLabel()
                            + " plugin for language '"
                            + language
                            + "' because some class in the plugin is incompatible (out-of-date)", e);
                } catch (CoreException e) {
                    throw new ExtensionException(
                            "Unable to instantiate implementation of "
                                    + extensionPoint.getLabel()
                                    + " plugin for language '"
                                    + language
                                    + "' because of the following low level exception: "
                                    + e.getStatus().getException(), e);
                } catch (NoClassDefFoundError e) {
                    throw new ExtensionException(
                            "Unable to instantiate implementation of "
                                    + extensionPoint.getLabel()
                                    + " plugin for language '"
                                    + language
                                    + "' because it may not have a public zero argument constructor, or some class referenced by the plugin could not be found in the class path.",
                            e);
                }
            }
        }
        
        return null;
    }

    /**
     * Retrieves from an extension an attribute that represents a resource URL
     * @param language language that the extension is for
     * @param extensionPoint extension point identifier
     * @param the label of the attribute that contains the resource URL
     */
    @SuppressWarnings("deprecation")
    public static URL createResourceURL(String language,
            IExtensionPoint extensionPoint, String label) {
        IConfigurationElement[] elements = extensionPoint
                .getConfigurationElements();
        String lowerLabel = label.toLowerCase();
        String lowerLang = language.toLowerCase();

        if (elements != null) {
            for (int n = 0; n < elements.length; n++) {
                IConfigurationElement element = elements[n];
                Bundle bundle = Platform.getBundle(element
                        .getDeclaringExtension().getNamespace());

                if (bundle != null) {
                    final String attrValue = element
                            .getAttribute(Language.LANGUAGE_ID_ATTR);

                    if (attrValue != null
                            && lowerLang.equals(attrValue.toLowerCase())) {
                        String resourceName = element.getAttribute(lowerLabel);
                        return bundle.getResource(resourceName);
                    }
                }
            }
        }

        return null;
    }
}

Back to the top