Project

General

Profile

Download (13.2 KB) Statistics
| Branch: | Tag: | Revision:
1
/*******************************************************************************
2
 * Copyright (c) 2003, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 * IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.ui.internal.navigator;
12

    
13
import java.util.ArrayList;
14
import java.util.Arrays;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.List;
19
import java.util.Map;
20
import java.util.Set;
21

    
22
import org.eclipse.core.runtime.ListenerList;
23
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
24
import org.eclipse.ui.internal.navigator.extensions.NavigatorContentDescriptor;
25
import org.eclipse.ui.internal.navigator.extensions.NavigatorContentDescriptorManager;
26
import org.eclipse.ui.navigator.IExtensionActivationListener;
27
import org.eclipse.ui.navigator.INavigatorActivationService;
28
import org.eclipse.ui.navigator.INavigatorContentDescriptor;
29
import org.eclipse.ui.navigator.INavigatorContentService;
30

    
31
/**
32
 * 
33
 * The activation service determines if an extension is <i>active</i> within the
34
 * context of a given viewer. If an extension is <i>active</i> then the extension
35
 * will contribute functionality to the viewer. If an extension is not <i>active</i>,
36
 * then the extension will not be given opportunities to contribute
37
 * functionality to the given viewer. See {@link INavigatorContentService} for
38
 * more detail on what states are associated with a content extension.
39
 * 
40
 * @since 3.2
41
 */
42
public final class NavigatorActivationService implements
43
		INavigatorActivationService {
44

    
45
	private static final String ACTIVATED_EXTENSIONS = ".activatedExtensions"; //$NON-NLS-1$
46

    
47
	private static final NavigatorContentDescriptorManager CONTENT_DESCRIPTOR_REGISTRY = NavigatorContentDescriptorManager
48
			.getInstance();	
49

    
50
	private static final INavigatorContentDescriptor[] NO_DESCRIPTORS = new INavigatorContentDescriptor[0];
51

    
52
	private static final String DELIM = ";"; //$NON-NLS-1$
53

    
54
	private static final char EQUALS = '=';  
55

    
56
	/*
57
	 * Map of ids of activated extensions. Note this is only synchronized when
58
	 * modifying it structurally (that is adding or deleting entries in it). For
59
	 * changing of the activated extension state, no synchronization is
60
	 * necessary.  Though this is semantically functioning as a Set, it's implemented
61
	 * as a Map to avoid the synchronization during the frequent checking of
62
	 * extension status.
63
	 */
64
	private final Map/*<String, Boolean>*/ activatedExtensionsMap = new HashMap();
65

    
66
	/*
67
	 * IExtensionActivationListeners
68
	 */
69
	private final ListenerList listeners = new ListenerList();
70

    
71
	private INavigatorContentService contentService;
72

    
73
	/**
74
	 * Create an instance of the service.
75
	 * 
76
	 * @param aContentService
77
	 *            The associated content service.
78
	 */
79
	public NavigatorActivationService(INavigatorContentService aContentService) {
80
		contentService = aContentService;
81
		revertExtensionActivations();
82
	}
83

    
84
	/**
85
	 * 
86
	 * Checks the known activation state for the given viewer id to determine if
87
	 * the given navigator extension is 'active'.
88
	 *  
89
	 * @param aNavigatorExtensionId
90
	 *            The unique identifier associated with a given extension.
91
	 * 
92
	 * @return True if the extension is active in the context of the viewer id.
93
	 */
94
	public boolean isNavigatorExtensionActive(String aNavigatorExtensionId) {
95
		Boolean b = (Boolean) activatedExtensionsMap.get(aNavigatorExtensionId);
96
		if(b != null)
97
			return b.booleanValue();
98
		synchronized (activatedExtensionsMap) {
99
			NavigatorContentDescriptor descriptor = CONTENT_DESCRIPTOR_REGISTRY.getContentDescriptor(aNavigatorExtensionId);
100
			if (descriptor == null)
101
				return false;
102
			if(descriptor.isActiveByDefault())
103
				activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.TRUE);
104
			else
105
				activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.FALSE);
106
			return descriptor.isActiveByDefault();
107
		}
108
	}
109

    
110
	/**
111
	 * Set the activation state for the given extension in the context of the
112
	 * given viewer id. Each instance of an INavigatorContentService listens for
113
	 * the activation service to update; and if those instances were created
114
	 * with viewers, they will issue a refresh. Otherwise, clients are
115
	 * responsible for refreshing the viewers.
116
	 * 
117
	 * <p>
118
	 * Clients must call {@link #persistExtensionActivations()} to save
119
	 * the the activation state.
120
	 * </p>
121
	 * 
122
	 * <p>
123
	 * When clients are updating a batch of extensions, consider using
124
	 * {@link #setActive(String[], boolean)} when
125
	 * possible to avoid unnecessary notifications.
126
	 * </p>
127
	 * 
128
	 * @param aNavigatorExtensionId
129
	 *            The unique identifier associated with a given extension.
130
	 * @param toEnable
131
	 *            True indicates the extension should be enabled; False
132
	 *            indicates otherwise.
133
	 * 
134
	 */
135
	public void setActive(
136
			String aNavigatorExtensionId, boolean toEnable) {
137

    
138
		boolean currentlyActive = isNavigatorExtensionActive(aNavigatorExtensionId);
139
		if (currentlyActive == toEnable) {
140
			return;
141
		}
142

    
143
		if (toEnable) {
144
			activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.TRUE);
145
		} else {
146
			activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.FALSE);
147
		}
148
		notifyListeners(new String[] { aNavigatorExtensionId }, toEnable);
149

    
150
	}
151

    
152
	/**
153
	 * Set the activation state for the given extension in the context of the
154
	 * given viewer id. Each instance of an INavigatorContentService listens for
155
	 * the activation service to update; and if those instances were created
156
	 * with viewers, they will issue a refresh. Otherwise, clients are
157
	 * responsible for refreshing the viewers.
158
	 * 
159
	 * <p>
160
	 * Clients must call {@link #persistExtensionActivations()} to save
161
	 * the the activation state.
162
	 * </p>
163
	 * 
164
	 * @param aNavigatorExtensionIds
165
	 *            An array of unique identifiers associated with existing
166
	 *            extension.
167
	 * @param toEnable
168
	 *            True indicates the extension should be enabled; False
169
	 *            indicates otherwise.
170
	 * 
171
	 */
172
	public void setActive(String[] aNavigatorExtensionIds,
173
			boolean toEnable) {
174

    
175
		if (toEnable) {
176
			for (int i = 0; i < aNavigatorExtensionIds.length; i++) {
177
				activatedExtensionsMap.put(aNavigatorExtensionIds[i], Boolean.TRUE);
178
			}
179
		} else {
180
			for (int i = 0; i < aNavigatorExtensionIds.length; i++) {
181
				activatedExtensionsMap.put(aNavigatorExtensionIds[i], Boolean.FALSE);
182
			}
183
		}
184
		notifyListeners(aNavigatorExtensionIds, toEnable);
185

    
186
	}
187

    
188
	/**
189
	 * Save the activation state for the given viewer.
190
	 * 
191
	 */
192
	public void persistExtensionActivations() {
193
		IEclipsePreferences prefs = NavigatorContentService.getPreferencesRoot();
194
		
195
		synchronized (activatedExtensionsMap) {
196
			Iterator activatedExtensionsIterator = activatedExtensionsMap.keySet().iterator();
197
			
198
			/* ensure that the preference will be non-empty */
199
			StringBuffer preferenceValue = new StringBuffer();
200
			String navigatorExtensionId = null;
201
			boolean isActive = false;
202
			while (activatedExtensionsIterator.hasNext()) {
203
				navigatorExtensionId = (String) activatedExtensionsIterator.next();
204
				isActive = isNavigatorExtensionActive(navigatorExtensionId);
205
				preferenceValue.append(navigatorExtensionId)
206
									.append(EQUALS)
207
										.append( isActive ? Boolean.TRUE : Boolean.FALSE )				
208
											.append(DELIM);
209
			}
210
			prefs.put(getPreferenceKey(), preferenceValue.toString());
211
		}
212

    
213
		NavigatorContentService.flushPreferences(prefs);
214
	}
215

    
216
	/**
217
	 * Request notification when the activation state changes for the given
218
	 * viewer id.
219
	 * 
220
	 * @param aListener
221
	 *            An implementation of {@link IExtensionActivationListener}
222
	 */
223
	public void addExtensionActivationListener(
224
			IExtensionActivationListener aListener) {
225
		listeners.add(aListener);
226
	}
227

    
228
	/**
229
	 * No longer receive notification when activation state changes.
230
	 * 
231
	 * @param aListener
232
	 *            An implementation of {@link IExtensionActivationListener}
233
	 */
234
	public void removeExtensionActivationListener(
235
			IExtensionActivationListener aListener) {
236
		listeners.remove(aListener);
237
	}
238

    
239
	private void notifyListeners(String[] navigatorExtensionIds,
240
			boolean toEnable) {
241
		
242
		if(navigatorExtensionIds != null) { // should really never be null, but just in case
243
			if(navigatorExtensionIds.length > 1)
244
				Arrays.sort(navigatorExtensionIds);
245
			
246
			Object[] listenerArray = listeners.getListeners();
247
			for (int i = 0; i < listenerArray.length; i++) {
248
				((IExtensionActivationListener) listenerArray[i])
249
						.onExtensionActivation(contentService.getViewerId(),
250
								navigatorExtensionIds, toEnable);
251
			}
252
		}
253

    
254
	}
255

    
256
	private void revertExtensionActivations() {
257

    
258
		IEclipsePreferences prefs = NavigatorContentService.getPreferencesRoot();
259

    
260
		String activatedExtensionsString = prefs
261
				.get(getPreferenceKey(), null);
262

    
263
		if (activatedExtensionsString != null
264
				&& activatedExtensionsString.length() > 0) {
265
			String[] contentExtensionIds = activatedExtensionsString
266
					.split(DELIM);
267
			
268
			String id = null;
269
			String booleanString = null;
270
			int indx=0;
271
			for (int i = 0; i < contentExtensionIds.length; i++) {
272
				if( (indx = contentExtensionIds[i].indexOf(EQUALS)) > -1) {
273
					// up to but not including the equals
274
					id = contentExtensionIds[i].substring(0, indx);
275
					booleanString = contentExtensionIds[i].substring(indx+1, contentExtensionIds[i].length());
276
					activatedExtensionsMap.put(id, Boolean.valueOf(booleanString));
277
				} else {
278
					// IS THIS THE RIGHT WAY TO HANDLE THIS CASE?
279
					NavigatorContentDescriptor descriptor = CONTENT_DESCRIPTOR_REGISTRY.getContentDescriptor(contentExtensionIds[i]);
280
					if(descriptor != null)
281
						activatedExtensionsMap.put(id, Boolean.valueOf(descriptor.isActiveByDefault()));
282
				}
283
			}
284

    
285
		} else {
286
			/*
287
			 * We add the default activation of every known extension, even
288
			 * though some may not be bound to the associated content service;
289
			 * this is because they could be bound at a later time through the
290
			 * programmatic binding mechanism in INavigatorContentService.
291
			 */
292
			INavigatorContentDescriptor[] contentDescriptors = CONTENT_DESCRIPTOR_REGISTRY
293
					.getAllContentDescriptors();
294
			for (int i = 0; i < contentDescriptors.length; i++) {
295
				if (contentDescriptors[i].isActiveByDefault()) {					
296
					activatedExtensionsMap.put(contentDescriptors[i].getId(), Boolean.TRUE);
297
				}
298
			}
299
		} 
300
	}
301

    
302
	private String getPreferenceKey() {
303
		return contentService.getViewerId() + ACTIVATED_EXTENSIONS;
304
	}
305

    
306

    
307
	public INavigatorContentDescriptor[] activateExtensions(
308
			String[] extensionIds, boolean toDeactivateAllOthers) {
309

    
310
		Set activatedDescriptors = new HashSet(); 
311
		setActive(extensionIds, true);
312
		for (int extId = 0; extId < extensionIds.length; extId++) {
313
			activatedDescriptors.add(CONTENT_DESCRIPTOR_REGISTRY
314
					.getContentDescriptor(extensionIds[extId]));
315
		}
316

    
317
		if (toDeactivateAllOthers) {
318
			NavigatorContentDescriptor[] descriptors = CONTENT_DESCRIPTOR_REGISTRY
319
					.getAllContentDescriptors();
320
			List descriptorList = new ArrayList(Arrays.asList(descriptors));
321

    
322
			for (int descriptorIndx = 0; descriptorIndx < descriptors.length; descriptorIndx++) {
323
				for (int extId = 0; extId < extensionIds.length; extId++) {
324
					if (descriptors[descriptorIndx].getId().equals(
325
							extensionIds[extId])) {
326
						descriptorList.remove(descriptors[descriptorIndx]);
327
					}
328
				}
329
			}
330

    
331
			String[] deactivatedExtensions = new String[descriptorList.size()];
332
			for (int i = 0; i < descriptorList.size(); i++) {
333
				INavigatorContentDescriptor descriptor = (INavigatorContentDescriptor) descriptorList
334
						.get(i);
335
				deactivatedExtensions[i] = descriptor.getId();
336
			}
337
			setActive(deactivatedExtensions, false);
338
		}
339

    
340
		if (activatedDescriptors.size() == 0) {
341
			return NO_DESCRIPTORS;
342
		}
343
		return (INavigatorContentDescriptor[]) activatedDescriptors
344
				.toArray(new NavigatorContentDescriptor[activatedDescriptors
345
						.size()]);
346
	}
347

    
348
	public INavigatorContentDescriptor[] deactivateExtensions(
349
			String[] extensionIds, boolean toEnableAllOthers) {
350

    
351
		Set activatedDescriptors = new HashSet(); 
352
		setActive(extensionIds, false);
353

    
354
		if (toEnableAllOthers) {
355
			NavigatorContentDescriptor[] descriptors = CONTENT_DESCRIPTOR_REGISTRY
356
					.getAllContentDescriptors();
357
			List descriptorList = new ArrayList(Arrays.asList(descriptors));
358

    
359
			for (int descriptorIndx = 0; descriptorIndx < descriptors.length; descriptorIndx++) {
360
				for (int extId = 0; extId < extensionIds.length; extId++) {
361
					if (descriptors[descriptorIndx].getId().equals(
362
							extensionIds[extId])) {
363
						descriptorList.remove(descriptors[descriptorIndx]);
364
					}
365
				}
366
			}
367

    
368
			String[] activatedExtensions = new String[descriptorList.size()];
369
			for (int i = 0; i < descriptorList.size(); i++) {
370
				NavigatorContentDescriptor descriptor = (NavigatorContentDescriptor) descriptorList
371
						.get(i);
372
				activatedExtensions[i] = descriptor.getId();
373
				activatedDescriptors.add(descriptor);
374
			}
375
			setActive(activatedExtensions,	true);
376
		}
377
		if (activatedDescriptors.size() == 0) {
378
			return NO_DESCRIPTORS;
379
		}
380

    
381
		return (INavigatorContentDescriptor[]) activatedDescriptors
382
				.toArray(new NavigatorContentDescriptor[activatedDescriptors
383
						.size()]);
384
	}
385

    
386

    
387
}
(12-12/31)