Skip to main content
summaryrefslogtreecommitdiffstats
blob: 2a6f9b2c107b0cb295cdea04b1f52be353bdde15 (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
396
397
398
399
400
401
402
403
404
405
/*******************************************************************************
 * Copyright (c) 2001, 2006 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 && testType.isKindOf(contentType)) {
						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;
	}
}

Back to the top