001/*
002 * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Jean-Marc Orliaguet, Chalmers
018 *
019 * $Id$
020 */
021
022package org.nuxeo.theme.services;
023
024import java.io.File;
025import java.io.IOException;
026import java.net.MalformedURLException;
027import java.net.URL;
028import java.util.HashMap;
029import java.util.List;
030import java.util.Map;
031
032import org.apache.commons.logging.Log;
033import org.apache.commons.logging.LogFactory;
034import org.nuxeo.runtime.model.ComponentContext;
035import org.nuxeo.runtime.model.ComponentName;
036import org.nuxeo.runtime.model.DefaultComponent;
037import org.nuxeo.runtime.model.Extension;
038import org.nuxeo.runtime.model.RuntimeContext;
039import org.nuxeo.theme.ApplicationType;
040import org.nuxeo.theme.CachingDef;
041import org.nuxeo.theme.Manager;
042import org.nuxeo.theme.NegotiationDef;
043import org.nuxeo.theme.Registrable;
044import org.nuxeo.theme.RegistryType;
045import org.nuxeo.theme.ViewDef;
046import org.nuxeo.theme.engines.EngineType;
047import org.nuxeo.theme.models.ModelType;
048import org.nuxeo.theme.perspectives.PerspectiveType;
049import org.nuxeo.theme.presets.PaletteParser;
050import org.nuxeo.theme.presets.PaletteType;
051import org.nuxeo.theme.presets.PresetType;
052import org.nuxeo.theme.resources.BankImport;
053import org.nuxeo.theme.resources.BankManager;
054import org.nuxeo.theme.resources.ResourceBank;
055import org.nuxeo.theme.resources.ResourceType;
056import org.nuxeo.theme.templates.TemplateEngineType;
057import org.nuxeo.theme.themes.ThemeDescriptor;
058import org.nuxeo.theme.themes.ThemeIOException;
059import org.nuxeo.theme.themes.ThemeManager;
060import org.nuxeo.theme.themes.ThemeParser;
061import org.nuxeo.theme.themes.ThemeSet;
062import org.nuxeo.theme.themes.ThemeSetEntry;
063import org.nuxeo.theme.types.Type;
064import org.nuxeo.theme.types.TypeFamily;
065import org.nuxeo.theme.types.TypeRegistry;
066import org.nuxeo.theme.views.ViewType;
067
068public class ThemeService extends DefaultComponent {
069
070    public static final ComponentName ID = new ComponentName("org.nuxeo.theme.services.ThemeService");
071
072    private static final Log log = LogFactory.getLog(ThemeService.class);
073
074    private Map<String, Registrable> registries = new HashMap<String, Registrable>();
075
076    private RuntimeContext context;
077
078    public Map<String, Registrable> getRegistries() {
079        return registries;
080    }
081
082    public Registrable getRegistry(String name) {
083        return registries.get(name);
084    }
085
086    public synchronized void addRegistry(String name, Registrable registry) {
087        registries.put(name, registry);
088    }
089
090    public synchronized void removeRegistry(String name) {
091        Registrable registry = registries.get(name);
092        if (registry != null) {
093            registry.clear();
094        }
095        registries.remove(name);
096    }
097
098    @Override
099    public void activate(ComponentContext ctx) {
100        context = ctx.getRuntimeContext();
101        Manager.initializeProtocols();
102        log.debug("Theme service activated");
103    }
104
105    @Override
106    public void deactivate(ComponentContext ctx) {
107        for (Registrable registry : registries.values()) {
108            registry.clear();
109        }
110        registries.clear();
111        context = null;
112        Manager.resetProtocols();
113        log.debug("Theme service deactivated");
114    }
115
116    @Override
117    public void applicationStarted(ComponentContext context) {
118        // themes registered as contributions
119        for (ThemeDescriptor themeDescriptor : ThemeManager.getThemeDescriptors()) {
120            registerTheme(themeDescriptor);
121        }
122        // custom themes located on the file-system
123        registerCustomThemes();
124
125        ThemeManager.updateThemeDescriptors();
126
127        // setup resource banks
128        BankManager.setupBanks();
129    }
130
131    @Override
132    public void registerExtension(Extension extension) {
133        String xp = extension.getExtensionPoint();
134        if (xp.equals("registries")) {
135            registerRegistryExtension(extension);
136        } else if (xp.equals("elements") || xp.equals("fragments") || xp.equals("formats")
137                || xp.equals("format-filters") || xp.equals("standalone-filters") || xp.equals("negotiations")
138                || xp.equals("shortcuts") || xp.equals("vocabularies")) {
139            registerTypeExtension(extension);
140        } else if (xp.equals("applications")) {
141            registerApplicationExtension(extension);
142        } else if (xp.equals("perspectives")) {
143            registerPerspectiveExtension(extension);
144        } else if (xp.equals("engines")) {
145            registerEngineExtension(extension);
146        } else if (xp.equals("template-engines")) {
147            registerTemplateEngineExtension(extension);
148        } else if (xp.equals("themes")) {
149            registerThemeExtension(extension);
150        } else if (xp.equals("themesets")) {
151            registerThemeSetExtension(extension);
152        } else if (xp.equals("presets")) {
153            registerPresetExtension(extension);
154        } else if (xp.equals("views")) {
155            registerViewExtension(extension);
156        } else if (xp.equals("models")) {
157            registerModelExtension(extension);
158        } else if (xp.equals("resources")) {
159            registerResourceExtension(extension);
160        } else if (xp.equals("banks")) {
161            registerBank(extension);
162        } else {
163            log.warn(String.format("Unknown extension point: %s", xp));
164        }
165    }
166
167    @Override
168    public void unregisterExtension(Extension extension) {
169        String xp = extension.getExtensionPoint();
170        if (xp.equals("registries")) {
171            unregisterRegistryExtension(extension);
172        } else if (xp.equals("elements") || xp.equals("fragments") || xp.equals("formats")
173                || xp.equals("format-filters") || xp.equals("standalone-filters") || xp.equals("engines")
174                || xp.equals("template-engines") || xp.equals("negotiations") || xp.equals("perspectives")
175                || xp.equals("applications") || xp.equals("shortcuts") || xp.equals("vocabularies")
176                || (xp.equals("presets")) || xp.equals("views") || xp.equals("themes") || xp.equals("themesets")) {
177            unregisterTypeExtension(extension);
178        } else if (xp.equals("resources")) {
179            unregisterResourceExtension(extension);
180        } else if (xp.equals("views")) {
181            unregisterViewExtension(extension);
182        } else if (xp.equals("models")) {
183            unregisterModelExtension(extension);
184        } else if (xp.equals("banks")) {
185            unregisterBank(extension);
186        } else {
187            log.warn(String.format("Unknown extension point: %s", xp));
188        }
189    }
190
191    private void registerRegistryExtension(Extension extension) {
192        Object[] contribs = extension.getContributions();
193        for (Object contrib : contribs) {
194            RegistryType registryType = (RegistryType) contrib;
195            Registrable registry = null;
196            try {
197                registry = (Registrable) context.loadClass(registryType.getClassName()).newInstance();
198            } catch (ReflectiveOperationException e) {
199                log.warn("Could not create registry: " + registryType.getName() + "(" + registryType.getClassName()
200                        + ")");
201            }
202            if (registry != null) {
203                addRegistry(registryType.getName(), registry);
204            }
205        }
206    }
207
208    private void unregisterRegistryExtension(Extension extension) {
209        Object[] contribs = extension.getContributions();
210        for (Object contrib : contribs) {
211            RegistryType registryType = (RegistryType) contrib;
212            removeRegistry(registryType.getName());
213        }
214    }
215
216    private void registerTypeExtension(Extension extension) {
217        Object[] contribs = extension.getContributions();
218        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
219        for (Object contrib : contribs) {
220            typeRegistry.register((Type) contrib);
221        }
222    }
223
224    private void unregisterTypeExtension(Extension extension) {
225        Object[] contribs = extension.getContributions();
226        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
227        if (typeRegistry != null) {
228            for (Object contrib : contribs) {
229                typeRegistry.unregister((Type) contrib);
230            }
231        }
232    }
233
234    private void registerApplicationExtension(Extension extension) {
235        Object[] contribs = extension.getContributions();
236        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
237        for (Object contrib : contribs) {
238            ApplicationType application = (ApplicationType) contrib;
239
240            ApplicationType oldApplication = (ApplicationType) typeRegistry.lookup(TypeFamily.APPLICATION,
241                    application.getTypeName());
242
243            if (oldApplication == null) {
244                String templateEngine = application.getTemplateEngine();
245                if (templateEngine == null) {
246                    final String defaultTemplateEngine = ThemeManager.getDefaultTemplateEngineName();
247                    log.warn(String.format(
248                            "Please set the 'template-engine' attribute on <application root=\"%s\" template-engine=\"...\"> (default is '%s')",
249                            application.getRoot(), defaultTemplateEngine));
250                    application.setTemplateEngine(defaultTemplateEngine);
251                }
252                typeRegistry.register(application);
253
254            } else {
255                // Merge properties from already registered application
256                final String templateEngine = application.getTemplateEngine();
257                if (templateEngine != null) {
258                    oldApplication.setTemplateEngine(templateEngine);
259                }
260
261                NegotiationDef negotiation = application.getNegotiation();
262                if (negotiation != null) {
263                    NegotiationDef oldNegotiation = oldApplication.getNegotiation();
264                    if (oldNegotiation == null) {
265                        oldNegotiation = new NegotiationDef();
266                        oldApplication.setNegotiation(oldNegotiation);
267                    }
268                    if (negotiation.getStrategy() != null) {
269                        oldNegotiation.setStrategy(negotiation.getStrategy());
270                    }
271                    if (negotiation.getDefaultTheme() != null) {
272                        oldNegotiation.setDefaultTheme(negotiation.getDefaultTheme());
273                    }
274                    if (negotiation.getDefaultPerspective() != null) {
275                        oldNegotiation.setDefaultPerspective(negotiation.getDefaultPerspective());
276                    }
277                    if (negotiation.getDefaultEngine() != null) {
278                        oldNegotiation.setDefaultEngine(negotiation.getDefaultEngine());
279                    }
280                }
281
282                CachingDef resourceCaching = application.getResourceCaching();
283                if (resourceCaching != null) {
284                    CachingDef oldResourceCaching = oldApplication.getResourceCaching();
285                    if (oldResourceCaching == null) {
286                        oldResourceCaching = new CachingDef();
287                        oldApplication.setResourceCaching(oldResourceCaching);
288                    }
289                    if (resourceCaching.getLifetime() != null) {
290                        oldResourceCaching.setLifetime(resourceCaching.getLifetime());
291                    }
292                }
293
294                CachingDef styleCaching = application.getStyleCaching();
295                if (styleCaching != null) {
296                    CachingDef oldStyleCaching = oldApplication.getStyleCaching();
297                    if (oldStyleCaching == null) {
298                        oldStyleCaching = new CachingDef();
299                        oldApplication.setStyleCaching(oldStyleCaching);
300                    }
301                    if (styleCaching.getLifetime() != null) {
302                        oldStyleCaching.setLifetime(styleCaching.getLifetime());
303                    }
304                }
305
306                Map<String, ViewDef> viewDefs = application.getViewDefs();
307                if (!viewDefs.isEmpty()) {
308                    Map<String, ViewDef> oldViewDefs = oldApplication.getViewDefs();
309                    for (Map.Entry<String, ViewDef> entry : viewDefs.entrySet()) {
310                        oldViewDefs.put(entry.getKey(), entry.getValue());
311                    }
312                }
313
314            }
315        }
316    }
317
318    private void registerPerspectiveExtension(Extension extension) {
319        Object[] contribs = extension.getContributions();
320        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
321        for (Object contrib : contribs) {
322            PerspectiveType perspective = (PerspectiveType) contrib;
323            if (!perspective.getName().matches("[a-z0-9_\\-]+")) {
324                log.error("Perspective names may only contain lowercase alphanumeric characters, underscores and hyphens ");
325                continue;
326            }
327            typeRegistry.register(perspective);
328        }
329    }
330
331    private void registerEngineExtension(Extension extension) {
332        Object[] contribs = extension.getContributions();
333        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
334        for (Object contrib : contribs) {
335            EngineType engine = (EngineType) contrib;
336            if (!engine.getName().matches("[a-z0-9_\\-]+")) {
337                log.error("Rendering engine names may only contain lowercase alphanumeric characters, underscores and hyphens ");
338                continue;
339            }
340            typeRegistry.register(engine);
341        }
342    }
343
344    private void registerTemplateEngineExtension(Extension extension) {
345        Object[] contribs = extension.getContributions();
346        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
347        for (Object contrib : contribs) {
348            TemplateEngineType engine = (TemplateEngineType) contrib;
349            if (!engine.getName().matches("[a-z0-9_\\-]+")) {
350                log.error("Template engine names may only contain lowercase alphanumeric characters, underscores and hyphens ");
351                continue;
352            }
353            typeRegistry.register(engine);
354        }
355    }
356
357    private void registerThemeExtension(Extension extension) {
358        Object[] contribs = extension.getContributions();
359        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
360
361        for (Object contrib : contribs) {
362            ThemeDescriptor themeDescriptor = (ThemeDescriptor) contrib;
363            themeDescriptor.setContext(extension.getContext());
364            themeDescriptor.setConfigured(true);
365
366            // register the theme descriptor even if the theme fails to load
367            typeRegistry.register(themeDescriptor);
368        }
369    }
370
371    private void registerTheme(ThemeDescriptor themeDescriptor) {
372        String src = themeDescriptor.getSrc();
373        if (src == null) {
374            themeDescriptor.setLoadingFailed(true);
375            log.error("Could not load theme, source not set. ");
376            return;
377        }
378        try {
379            final boolean preload = true;
380            ThemeParser.registerTheme(themeDescriptor, preload);
381        } catch (ThemeIOException e) {
382            log.error("Could not register theme: " + src + " " + e.getMessage());
383        }
384    }
385
386    private void registerThemeSetExtension(Extension extension) {
387        Object[] contribs = extension.getContributions();
388        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
389
390        for (Object contrib : contribs) {
391            ThemeSet themeSet = (ThemeSet) contrib;
392            String name = themeSet.getName();
393
394            ThemeSet oldThemeSet = (ThemeSet) typeRegistry.lookup(TypeFamily.THEMESET, name);
395
396            if (oldThemeSet == null) {
397                typeRegistry.register(themeSet);
398            } else {
399                for (ThemeSetEntry theme : themeSet.getThemes()) {
400                    String themeName = theme.getName();
401                    ThemeSetEntry oldTheme = oldThemeSet.getTheme(themeName);
402                    if (oldTheme == null) {
403                        oldTheme = new ThemeSetEntry(themeName);
404                        oldThemeSet.setTheme(oldTheme);
405                    }
406                    for (String feature : theme.getFeatures()) {
407                        oldThemeSet.addFeatureToTheme(themeName, feature);
408                    }
409                }
410
411            }
412        }
413    }
414
415    private void registerCustomThemes() {
416        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
417        for (File file : ThemeManager.getCustomThemeFiles()) {
418            ThemeDescriptor themeDescriptor = new ThemeDescriptor();
419            themeDescriptor.setConfigured(false);
420
421            String src = null;
422            try {
423                src = String.format("file://%s", file.getCanonicalPath());
424            } catch (IOException e) {
425                themeDescriptor.setLoadingFailed(true);
426                log.error("Could not read theme file: " + src);
427                continue;
428            }
429
430            themeDescriptor.setSrc(src);
431
432            try {
433                final boolean preload = true;
434                ThemeParser.registerTheme(themeDescriptor, preload);
435            } catch (ThemeIOException e) {
436                log.error("Could not register theme: " + src + " " + e.getMessage());
437                continue;
438            }
439            typeRegistry.register(themeDescriptor);
440        }
441        log.debug("Registered local themes");
442    }
443
444    private void registerPresetExtension(Extension extension) {
445        Object[] contribs = extension.getContributions();
446        RuntimeContext extensionContext = extension.getContext();
447        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
448        for (Object contrib : contribs) {
449            if (contrib instanceof PaletteType) {
450                registerPalette((PaletteType) contrib, extensionContext);
451            } else {
452                typeRegistry.register((Type) contrib);
453            }
454        }
455    }
456
457    private void registerPalette(PaletteType palette, RuntimeContext extensionContext) {
458        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
459        String paletteName = palette.getName();
460        String src = palette.getSrc();
461        String category = palette.getCategory();
462        URL url = null;
463        try {
464            url = new URL(src);
465        } catch (MalformedURLException e) {
466            url = extensionContext.getLocalResource(src);
467            if (url == null) {
468                url = extensionContext.getResource(src);
469            }
470        }
471
472        if (url != null) {
473            typeRegistry.register(palette);
474            Map<String, String> entries = PaletteParser.parse(url);
475            for (Map.Entry<String, String> entry : entries.entrySet()) {
476                PresetType preset = new PresetType(entry.getKey(), entry.getValue(), paletteName, category, "", "");
477                typeRegistry.register(preset);
478            }
479        }
480    }
481
482    private void registerViewExtension(Extension extension) {
483        Object[] contribs = extension.getContributions();
484        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
485        for (Object contrib : contribs) {
486            ViewType viewType = (ViewType) contrib;
487            String templateEngineName = viewType.getTemplateEngine();
488            final String viewName = viewType.getViewName();
489            final String viewTypeName = viewType.getTypeName();
490            if (templateEngineName == null) {
491                final String defaultTemplateEngineName = ThemeManager.getDefaultTemplateEngineName();
492                templateEngineName = defaultTemplateEngineName;
493                log.warn(String.format(
494                        "Please set the 'template-engine' attribute on <view name=\"%s\" template-engine=\"...\"> (using default '%s')",
495                        viewName, defaultTemplateEngineName));
496            } else {
497                if (templateEngineName.contains(",")) {
498                    log.warn(String.format(
499                            "The 'template-engine' attribute in <view name=\"%s\" template-engine=\"...\"> may only contain a single template-engine name",
500                            viewName, templateEngineName));
501                    templateEngineName = templateEngineName.split(",")[0];
502                }
503
504                if (viewType.isMerge()) {
505                    final ViewType oldViewType = (ViewType) typeRegistry.lookup(TypeFamily.VIEW, viewTypeName);
506                    if (oldViewType != null) {
507                        // merge resource properties
508                        List<String> newResources = viewType.getResources();
509                        if (!newResources.isEmpty()) {
510                            log.debug("Added resources " + newResources + " to THEME view: " + viewTypeName);
511                            for (String resource : newResources) {
512                                oldViewType.addResource(resource);
513                            }
514                        }
515                    }
516                } else {
517                    typeRegistry.register(viewType);
518                }
519            }
520        }
521    }
522
523    private void unregisterViewExtension(Extension extension) {
524        Object[] contribs = extension.getContributions();
525        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
526        if (typeRegistry != null) {
527            for (Object contrib : contribs) {
528                typeRegistry.unregister((ViewType) contrib);
529            }
530        }
531    }
532
533    private void registerModelExtension(Extension extension) {
534        Object[] contribs = extension.getContributions();
535        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
536        ThemeManager themeManager = (ThemeManager) getRegistry("themes");
537        for (Object contrib : contribs) {
538            ModelType modelType = (ModelType) contrib;
539            final String modelTypeName = modelType.getTypeName();
540            final ModelType oldModelType = (ModelType) typeRegistry.lookup(TypeFamily.MODEL, modelTypeName);
541            if (oldModelType != null) {
542                if (oldModelType.getClassName().equals(modelType.getClassName())) {
543                    log.debug("Model type '" + modelTypeName + "' (" + oldModelType.getClassName()
544                            + ") has already been registered.");
545                } else {
546                    log.warn("Failed to reregister model type '" + modelTypeName + "' (" + oldModelType.getClassName()
547                            + "). The new class " + modelType.getClassName() + " will be ignored.");
548                }
549                continue;
550            }
551            typeRegistry.register(modelType);
552            themeManager.registerModelByClassname(modelType);
553        }
554    }
555
556    private void unregisterModelExtension(Extension extension) {
557        Object[] contribs = extension.getContributions();
558        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
559        ThemeManager themeManager = (ThemeManager) getRegistry("themes");
560        if (typeRegistry != null) {
561            for (Object contrib : contribs) {
562                ModelType modelType = (ModelType) contrib;
563                themeManager.unregisterModelByClassname(modelType);
564                typeRegistry.unregister(modelType);
565            }
566        }
567    }
568
569    private void registerResourceExtension(Extension extension) {
570        Object[] contribs = extension.getContributions();
571        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
572        RuntimeContext extensionContext = extension.getContext();
573        for (Object contrib : contribs) {
574            if (contrib instanceof ResourceType) {
575                ResourceType resourceType = (ResourceType) contrib;
576                typeRegistry.register(resourceType);
577            } else if (contrib instanceof BankImport) {
578                BankImport bankImport = (BankImport) contrib;
579                String bankName = bankImport.getBankName();
580                String collection = bankImport.getCollection();
581                String srcFilePath = bankImport.getSrcFilePath();
582                URL srcFileUrl = extensionContext.getLocalResource(srcFilePath);
583                if (srcFileUrl == null) {
584                    srcFileUrl = extensionContext.getResource(srcFilePath);
585                }
586                if (srcFileUrl == null) {
587                    log.error("Could not import bank resources: " + srcFilePath + " (resource not found)");
588                    continue;
589                }
590                try {
591                    BankManager.importBankData(bankName, collection, srcFileUrl);
592                } catch (IOException e) {
593                    log.error("Could not import bank resources: " + srcFilePath + " (" + e.getMessage() + ")");
594                }
595            }
596        }
597        ThemeManager themeManager = (ThemeManager) getRegistry("themes");
598        themeManager.updateResourceOrdering();
599    }
600
601    private void unregisterResourceExtension(Extension extension) {
602        Object[] contribs = extension.getContributions();
603        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
604        ThemeManager themeManager = (ThemeManager) getRegistry("themes");
605        if (typeRegistry == null || themeManager == null) {
606            return;
607        }
608        RuntimeContext extensionContext = extension.getContext();
609        for (Object contrib : contribs) {
610            if (contrib instanceof ResourceType) {
611                ResourceType resourceType = (ResourceType) contrib;
612                typeRegistry.unregister(resourceType);
613                themeManager.unregisterResourceOrdering(resourceType);
614            } else if (contrib instanceof BankImport) {
615                BankImport bankImport = (BankImport) contrib;
616                String bankName = bankImport.getBankName();
617                String srcFilePath = bankImport.getSrcFilePath();
618                // TODO
619            }
620        }
621    }
622
623    private void registerBank(Extension extension) {
624        Object[] contribs = extension.getContributions();
625        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
626        for (Object contrib : contribs) {
627            if (contrib instanceof ResourceBank) {
628                ResourceBank resourceBank = (ResourceBank) contrib;
629                typeRegistry.register(resourceBank);
630            }
631        }
632    }
633
634    private void unregisterBank(Extension extension) {
635        Object[] contribs = extension.getContributions();
636        TypeRegistry typeRegistry = (TypeRegistry) getRegistry("types");
637        if (typeRegistry == null) {
638            return;
639        }
640        for (Object contrib : contribs) {
641            if (contrib instanceof ResourceBank) {
642                ResourceBank resourceBank = (ResourceBank) contrib;
643                typeRegistry.unregister(resourceBank);
644            }
645        }
646    }
647
648}