blob: 9a33f4d86c86fa269ed5ab55d4e9eb95a384127f [file] [log] [blame]
/*******************************************************************************
* 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 com.ibm.icu.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.ISourceEditingTextTools;
import org.eclipse.wst.sse.ui.internal.provisional.extensions.breakpoint.IBreakpointProvider;
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;
ISourceEditingTextTools tools = null;
if (editorpart != null && itr.hasNext())
tools = (ISourceEditingTextTools) editorpart.getAdapter(ISourceEditingTextTools.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 contentType
* a content type ID or null
* @param ext
* a filename extension or null
* @return boolean
*/
public boolean isAvailable(String contentType, String ext) {
boolean available = false;
if (ext != null)
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);
}
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;
}
}