/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * 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: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.message.internal; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker; import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler; import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker; import org.eclipse.core.runtime.dynamichelpers.IFilter; import org.simantics.message.IMessageDataSchemeExtension; import org.simantics.message.IMessageSchemeManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Tuukka Lehtonen */ public class MessageSchemeManager implements IExtensionChangeHandler, IMessageSchemeManager { private static final Logger LOGGER = LoggerFactory.getLogger(MessageSchemeManager.class); public final static String NAMESPACE = "org.simantics.message"; public final static String ELEMENT_NAME = "scheme"; public final static String EP_NAME = "messageDataScheme"; private ExtensionTracker tracker; private MessageDataSchemeExtension[] extensions = new MessageDataSchemeExtension[0]; public MessageSchemeManager() { tracker = new ExtensionTracker(); // Cache defined actions IExtensionPoint expt = Platform.getExtensionRegistry().getExtensionPoint(NAMESPACE, EP_NAME); loadExtensions(expt.getConfigurationElements()); // Start tracking for new and removed extensions IFilter filter = ExtensionTracker.createExtensionPointFilter(expt); tracker.registerHandler(this, filter); } private String getDescription(IConfigurationElement el) { for (IConfigurationElement desc : el.getChildren("description")) { return desc.getValue(); } return null; } private void loadExtensions(IConfigurationElement[] configurationElements) { Set newExtensions = new HashSet(Arrays.asList(extensions)); // Initialize id -> extension lookup Map schemes = new HashMap(); for (MessageDataSchemeExtension ext : newExtensions) { schemes.put(ext.getId(), ext); } // 1st pass: load schemes for (IConfigurationElement el : configurationElements) { String name = el.getName(); if ("scheme".equals(name)) { String id = el.getAttribute("id"); if (id == null) continue; String scheme = el.getAttribute("scheme"); if (scheme == null) continue; String description = getDescription(el); MessageDataSchemeExtension ext = schemes.get(id); if (ext != null) { // This scheme is already registered, two contributors are contributing the same scheme. StringBuilder msg = new StringBuilder(); msg.append("Multiple contributors for message scheme '" + id + "':"); msg.append("\n 1st: " + ext.getSchemeElement().getContributor().getName()); msg.append("\n 2nd: " + el.getContributor().getName()); msg.append("\nUsing the first one."); LOGGER.info(msg.toString()); continue; } ext = new MessageDataSchemeExtension(el, id, scheme, description); // Start tracking the new extension object, its removal will be notified of // with removeExtension(extension, Object[]). tracker.registerObject(el.getDeclaringExtension(), ext, IExtensionTracker.REF_STRONG); newExtensions.add(ext); schemes.put(id, ext); } } // 2nd pass: load handlers for (IConfigurationElement el : configurationElements) { String name = el.getName(); if ("handler".equals(name)) { String id = el.getAttribute("schemeId"); if (id == null) continue; MessageDataSchemeExtension ext = schemes.get(id); if (ext == null) { // Unusable handler since there is no scheme to use it for. StringBuilder msg = new StringBuilder(); msg.append("No scheme extension for message scheme id '" + id + "'. Ignoring handler '" + el.getAttribute("handler") + "'"); msg.append("\nUsing the first one."); LOGGER.info(msg.toString()); continue; } IConfigurationElement prev = ext.getHandlerElement(); if (prev != null) { // Unusable handler since there already exists a handler for this scheme. StringBuilder msg = new StringBuilder(); msg.append("Multiple handler contributors for message scheme '" + id + "':\n"); msg.append("\n 1st: " + prev.getContributor().getName()); msg.append("\n 2nd: " + el.getContributor().getName()); msg.append("\nUsing the first one."); LOGGER.info(msg.toString()); continue; } ext.setHandlerElement(el); } } // Atomic assignment this.extensions = newExtensions.toArray(new MessageDataSchemeExtension[newExtensions.size()]); } @Override public void addExtension(IExtensionTracker tracker, IExtension extension) { loadExtensions(extension.getConfigurationElements()); } @Override public void removeExtension(IExtension extension, Object[] objects) { Set newExtensions = new HashSet(Arrays.asList(extensions)); for (Object o : objects) { tracker.unregisterObject(extension, o); newExtensions.remove((IMessageDataSchemeExtension) o); } // Atomic assignment this.extensions = newExtensions.toArray(new MessageDataSchemeExtension[newExtensions.size()]); } @Override public IMessageDataSchemeExtension[] getByScheme(String scheme) { if (scheme == null) throw new IllegalArgumentException("null scheme"); ArrayList result = new ArrayList(); for (MessageDataSchemeExtension ext : extensions) { if (scheme.equals(ext.getScheme())) result.add(ext); } return result.toArray(new MessageDataSchemeExtension[result.size()]); } }