| /******************************************************************************* |
| * Copyright (c) 2001, 2004 IBM Corporation 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: |
| * IBM Corporation - initial API and implementation |
| * Jens Lukowski/Innoopract - initial renaming/restructuring |
| * |
| *******************************************************************************/ |
| package org.eclipse.wst.sse.ui.internal.extension; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.StringTokenizer; |
| |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IExtensionRegistry; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.content.IContentType; |
| import org.eclipse.swt.custom.BusyIndicator; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.wst.sse.ui.internal.Logger; |
| import org.eclipse.wst.sse.ui.internal.provisional.extensions.breakpoint.IBreakpointProvider; |
| import org.eclipse.wst.sse.ui.internal.provisional.extensions.breakpoint.SourceEditingTextTools; |
| import org.osgi.framework.Bundle; |
| |
| |
| /** |
| * Reads breakpoint extension registory and returns breakpoint provider |
| * instances |
| */ |
| public class BreakpointProviderBuilder extends RegistryReader { |
| |
| private static final String ATT_CLASS = "class"; //$NON-NLS-1$ |
| // private static final String ATT_ID = "id"; //$NON-NLS-1$ |
| private static final String ATT_CONTENT_TYPES = "contentTypes"; //$NON-NLS-1$ |
| private static final String ATT_EXTENSIONS = "extensions"; //$NON-NLS-1$ |
| private static BreakpointProviderBuilder instance; |
| private static final String PL_BREAKPOINT = "breakpoint"; //$NON-NLS-1$ |
| |
| private static final String PLUGIN_ID = "org.eclipse.wst.sse.ui"; //$NON-NLS-1$ |
| |
| private static final String TAG_BREAKPOINT_CONTRIBUTION = "breakpointContribution"; //$NON-NLS-1$ |
| private static final String TAG_PROVIDER = "provider"; //$NON-NLS-1$ |
| |
| /* |
| * Creates an executable extension. @param element the config element |
| * defining the extension @param classAttribute the name of the attribute |
| * carrying the class @return the extension object @throws CoreException |
| */ |
| static Object createExecutableExtension(final IConfigurationElement element, final String classAttribute) throws CoreException { |
| return element.createExecutableExtension(classAttribute); |
| } |
| |
| /** |
| * Creates an extension. If the extension plugin has not been loaded a |
| * busy cursor will be activated during the duration of the load. |
| * |
| * @param element |
| * the config element defining the extension |
| * @param classAttribute |
| * the name of the attribute carrying the class |
| * @return the extension object |
| * @throws CoreException |
| */ |
| public static Object createExtension(final IConfigurationElement element, final String classAttribute) { |
| // If plugin has been loaded create extension. |
| // Otherwise, show busy cursor then create extension. |
| final Object[] result = new Object[1]; |
| String pluginId = element.getDeclaringExtension().getNamespace(); |
| Bundle bundle = Platform.getBundle(pluginId); |
| if (bundle.getState() == Bundle.ACTIVE) { |
| try { |
| result[0] = createExecutableExtension(element, classAttribute); |
| } |
| catch (Exception e) { |
| handleCreateExecutableException(result, e); |
| } |
| } |
| else { |
| BusyIndicator.showWhile(null, new Runnable() { |
| public void run() { |
| try { |
| result[0] = createExecutableExtension(element, classAttribute); |
| } |
| catch (CoreException e) { |
| handleCreateExecutableException(result, e); |
| } |
| } |
| }); |
| |
| } |
| return result[0]; |
| } |
| |
| /** |
| * returns singleton instance of BreakpointProviderBuilder |
| * |
| * @return BreakpointProviderBuilder |
| */ |
| public synchronized static BreakpointProviderBuilder getInstance() { |
| if (instance == null) { |
| instance = new BreakpointProviderBuilder(); |
| } |
| return instance; |
| } |
| |
| /** |
| * @param result |
| * @param e |
| */ |
| private static void handleCreateExecutableException(Object[] result, Throwable e) { |
| Logger.logException(e); |
| result[0] = null; |
| |
| } |
| |
| protected List cache; |
| private Map map = new HashMap(); |
| |
| protected String targetContributionTag; |
| |
| /* |
| * Constructor |
| */ |
| private BreakpointProviderBuilder() { |
| super(); |
| } |
| |
| /* |
| * Creates a breakpoint provider object to given element @param element |
| * configuration element object @return IBreakpointProvider |
| */ |
| protected IBreakpointProvider createBreakpointProvider(IConfigurationElement element) { |
| Object obj = createExtension(element, ATT_CLASS); |
| if (obj == null) |
| return null; |
| return (obj instanceof IBreakpointProvider) ? (IBreakpointProvider) obj : null; |
| } |
| |
| /* |
| * Creates an array of breakpoint providers matching the given key to the |
| * value of the IConfigurationElement attribute "attrName" @return |
| * IBreakpointProvider[] |
| */ |
| protected IBreakpointProvider[] createBreakpointProviders(String attrName, String key) { |
| if (cache == null) |
| return new IBreakpointProvider[0]; |
| |
| final int num = cache.size(); |
| if (num == 0) |
| return new IBreakpointProvider[0]; |
| |
| IBreakpointProvider[] bp = new IBreakpointProvider[num]; |
| int j = 0; |
| for (int i = 0; i < num; i++) { |
| Object obj = cache.get(i); |
| if (!(obj instanceof IConfigurationElement)) |
| continue; |
| |
| IConfigurationElement element = (IConfigurationElement) obj; |
| if (!TAG_PROVIDER.equals(element.getName())) |
| continue; |
| |
| boolean doCreate = false; |
| |
| String attrValues = element.getAttribute(attrName); |
| |
| if (attrValues != null) { |
| StringTokenizer tokenizer = new StringTokenizer(attrValues, ","); //$NON-NLS-1$ |
| while (tokenizer.hasMoreTokens()) { |
| String type = tokenizer.nextToken(); |
| if (type.trim().equalsIgnoreCase(key.trim())) { |
| doCreate = true; |
| break; |
| } |
| } |
| } |
| |
| if (doCreate) { |
| IBreakpointProvider b = createBreakpointProvider(element); |
| if (b != null) { |
| bp[j] = b; |
| j++; |
| } |
| } |
| } |
| |
| IBreakpointProvider[] bp2 = new IBreakpointProvider[j]; |
| for (int i = 0; i < j; i++) { |
| bp2[i] = bp[i]; |
| } |
| |
| return bp2; |
| } |
| |
| /* |
| * Returns a matching array of extension points matching this key. Doesn't |
| * cause instantiation of providers. @return IBreakpointProvider[] |
| */ |
| protected IConfigurationElement[] findElements(String key) { |
| initCache(); |
| |
| if (cache == null || cache.size() == 0) |
| return new IConfigurationElement[0]; |
| |
| int num = cache.size(); |
| List elements = new ArrayList(1); |
| for (int i = 0; i < num; i++) { |
| Object obj = cache.get(i); |
| if (!(obj instanceof IConfigurationElement)) |
| continue; |
| |
| IConfigurationElement element = (IConfigurationElement) obj; |
| if (!TAG_PROVIDER.equals(element.getName())) |
| continue; |
| |
| boolean add = false; |
| String types = element.getAttribute(ATT_CONTENT_TYPES); |
| String exts = element.getAttribute(ATT_EXTENSIONS); |
| |
| if (types == null && exts == null) { |
| add = true; |
| } |
| |
| if (!add && types != null && types.length() > 0) { |
| IContentType testType = Platform.getContentTypeManager().getContentType(key); |
| StringTokenizer tokenizer = new StringTokenizer(types, ","); //$NON-NLS-1$ |
| while (tokenizer.hasMoreTokens()) { |
| String type = tokenizer.nextToken(); |
| IContentType contentType = Platform.getContentTypeManager().getContentType(type); |
| if (contentType != null && testType != null && contentType.isKindOf(testType)) { |
| add = true; |
| break; |
| } |
| } |
| } |
| |
| if (!add && exts != null) { |
| StringTokenizer tokenizer = new StringTokenizer(exts, ","); //$NON-NLS-1$ |
| while (tokenizer.hasMoreTokens()) { |
| String ext = tokenizer.nextToken(); |
| if (ext.trim().equals(key.trim())) { |
| add = true; |
| break; |
| } |
| } |
| } |
| |
| if (add) { |
| elements.add(element); |
| } |
| } |
| return (IConfigurationElement[]) elements.toArray(new IConfigurationElement[0]); |
| } |
| |
| /** |
| * Returns an array of breakpoint providers for a specified content type |
| * handler |
| * |
| * @param handler |
| * a content type handler |
| * @param ext |
| * file extension |
| * @return IBreakpointProvider[] |
| */ |
| public IBreakpointProvider[] getBreakpointProviders(IEditorPart editorpart, String contentTypeID, String ext) { |
| initCache(); |
| |
| // Get breakpoint providers for this content type handler |
| IBreakpointProvider[] providers1 = new IBreakpointProvider[0]; |
| IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeID); |
| List holdProviders = new ArrayList(2); |
| while (contentType != null) { |
| IBreakpointProvider[] providers = (IBreakpointProvider[]) map.get(contentType.getId()); |
| if (providers == null) { |
| providers = createBreakpointProviders(ATT_CONTENT_TYPES, contentType.getId()); |
| if (providers != null) { |
| map.put(contentType.getId(), providers); |
| } |
| } |
| // providers were retrieved from cache or newly created |
| if(providers != null) { |
| holdProviders.addAll(Arrays.asList(providers)); |
| } |
| contentType = contentType.getBaseType(); |
| } |
| providers1 = (IBreakpointProvider[]) holdProviders.toArray(new IBreakpointProvider[holdProviders.size()]); |
| |
| // Get breakpoint providers for this extension |
| IBreakpointProvider[] providers2 = new IBreakpointProvider[0]; |
| if (ext != null) { |
| providers2 = (IBreakpointProvider[]) map.get(ext); |
| if (providers2 == null) { |
| providers2 = createBreakpointProviders(ATT_EXTENSIONS, ext); |
| if (providers2 != null) { |
| map.put(ext, providers2); |
| } |
| } |
| } |
| |
| // create single hash set to remove duplication |
| Set s = new HashSet(); |
| s.addAll(Arrays.asList(providers1)); |
| s.addAll(Arrays.asList(providers2)); |
| |
| // create IBreakpointProvider[] to return |
| IBreakpointProvider[] providers = new IBreakpointProvider[s.size()]; |
| Iterator itr = s.iterator(); |
| int i = 0; |
| SourceEditingTextTools tools = null; |
| if (editorpart != null && itr.hasNext()) |
| tools = (SourceEditingTextTools) editorpart.getAdapter(SourceEditingTextTools.class); |
| while (itr.hasNext()) { |
| providers[i] = (IBreakpointProvider) itr.next(); |
| providers[i].setSourceEditingTextTools(tools); |
| i++; |
| } |
| return providers; |
| } |
| |
| /** |
| * Returns corresponding resource from given parameters |
| * |
| * @param input |
| * @param handler |
| * @param ext |
| * @return IResource |
| */ |
| public IResource getResource(IEditorInput input, String contentType, String ext) { |
| IBreakpointProvider[] providers = getBreakpointProviders(null, contentType, ext); |
| IResource res = null; |
| for (int i = 0; i < providers.length; i++) { |
| res = providers[i].getResource(input); |
| if (res != null) { |
| break; |
| } |
| } |
| return res; |
| } |
| |
| private void initCache() { |
| if (cache == null) { |
| cache = new ArrayList(); |
| readContributions(TAG_BREAKPOINT_CONTRIBUTION, PL_BREAKPOINT); |
| } |
| } |
| |
| /** |
| * Returns an array of breakpoint providers for a specified content type |
| * handler |
| * |
| * @param handler |
| * a content type handler |
| * @param ext |
| * file extension |
| * @return boolean |
| */ |
| public boolean isAvailable(String contentType, String ext) { |
| boolean available = findElements(ext).length > 0; |
| if (!available && contentType != null) |
| available = findElements(contentType).length > 0; |
| return available; |
| } |
| |
| /** |
| * Reads the contributions from the registry for the provided workbench |
| * part and the provided extension point ID. |
| * |
| * @param tag |
| * @param extensionPoint |
| */ |
| protected void readContributions(String tag, String extensionPoint) { |
| targetContributionTag = tag; |
| IExtensionRegistry registry = Platform.getExtensionRegistry(); |
| readRegistry(registry, PLUGIN_ID, extensionPoint); |
| } |
| |
| /* |
| * @see com.ibm.sed.edit.internal.extension.RegistryReader#readElement(org.eclipse.core.runtime.IConfigurationElement) |
| */ |
| protected boolean readElement(IConfigurationElement element) { |
| String tag = element.getName(); |
| if (tag.equals(targetContributionTag)) { |
| readElementChildren(element); |
| return true; |
| } |
| else if (tag.equals(TAG_PROVIDER)) { |
| cache.add(element); |
| return true; // just cache the element - don't go into it |
| } |
| return false; |
| } |
| } |