001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal;
011:
012: import java.io.File;
013: import java.io.FileOutputStream;
014: import java.io.IOException;
015: import java.io.OutputStreamWriter;
016: import java.util.ArrayList;
017: import java.util.HashMap;
018: import java.util.Iterator;
019: import java.util.List;
020: import java.util.Map;
021: import java.util.SortedSet;
022: import java.util.TreeSet;
023:
024: import org.eclipse.core.commands.common.EventManager;
025: import org.eclipse.core.runtime.Assert;
026: import org.eclipse.core.runtime.IAdaptable;
027: import org.eclipse.core.runtime.IExtension;
028: import org.eclipse.core.runtime.IExtensionPoint;
029: import org.eclipse.core.runtime.ISafeRunnable;
030: import org.eclipse.core.runtime.Platform;
031: import org.eclipse.core.runtime.SafeRunner;
032: import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
033: import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
034: import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
035: import org.eclipse.jface.util.IPropertyChangeListener;
036: import org.eclipse.jface.util.PropertyChangeEvent;
037: import org.eclipse.swt.widgets.Display;
038: import org.eclipse.swt.widgets.Shell;
039: import org.eclipse.ui.IElementFactory;
040: import org.eclipse.ui.IMemento;
041: import org.eclipse.ui.IPersistableElement;
042: import org.eclipse.ui.IWorkingSet;
043: import org.eclipse.ui.IWorkingSetElementAdapter;
044: import org.eclipse.ui.IWorkingSetManager;
045: import org.eclipse.ui.IWorkingSetUpdater;
046: import org.eclipse.ui.PlatformUI;
047: import org.eclipse.ui.XMLMemento;
048: import org.eclipse.ui.dialogs.IWorkingSetEditWizard;
049: import org.eclipse.ui.dialogs.IWorkingSetNewWizard;
050: import org.eclipse.ui.dialogs.IWorkingSetPage;
051: import org.eclipse.ui.dialogs.IWorkingSetSelectionDialog;
052: import org.eclipse.ui.internal.dialogs.WorkingSetEditWizard;
053: import org.eclipse.ui.internal.dialogs.WorkingSetNewWizard;
054: import org.eclipse.ui.internal.dialogs.WorkingSetSelectionDialog;
055: import org.eclipse.ui.internal.misc.StatusUtil;
056: import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
057: import org.eclipse.ui.internal.registry.WorkingSetDescriptor;
058: import org.eclipse.ui.internal.registry.WorkingSetRegistry;
059: import org.eclipse.ui.statushandlers.StatusManager;
060: import org.osgi.framework.Bundle;
061: import org.osgi.framework.BundleContext;
062: import org.osgi.framework.BundleEvent;
063: import org.osgi.framework.BundleListener;
064:
065: /**
066: * Abstract implementation of <code>IWorkingSetManager</code>.
067: */
068: public abstract class AbstractWorkingSetManager extends EventManager
069: implements IWorkingSetManager, BundleListener,
070: IExtensionChangeHandler {
071:
072: private SortedSet workingSets = new TreeSet(
073: WorkingSetComparator.INSTANCE);
074:
075: /**
076: * Size of the list of most recently used working sets.
077: */
078: private static final int MRU_SIZE = 5;
079: private List recentWorkingSets = new ArrayList();
080:
081: private BundleContext bundleContext;
082: private Map/*<String, IWorkingSetUpdater>*/updaters = new HashMap();
083:
084: private Map/*<String, IWorkingSetElementAdapter>*/elementAdapters = new HashMap();
085:
086: private static final IWorkingSetUpdater NULL_UPDATER = new IWorkingSetUpdater() {
087: public void add(IWorkingSet workingSet) {
088: }
089:
090: public boolean remove(IWorkingSet workingSet) {
091: return true;
092: }
093:
094: public boolean contains(IWorkingSet workingSet) {
095: return true;
096: }
097:
098: public void dispose() {
099: }
100: };
101:
102: private static final IWorkingSetElementAdapter IDENTITY_ADAPTER = new IWorkingSetElementAdapter() {
103:
104: public IAdaptable[] adaptElements(IWorkingSet ws,
105: IAdaptable[] elements) {
106: return elements;
107: }
108:
109: public void dispose() {
110: }
111: };
112:
113: /**
114: * Returns the descriptors for the given editable working set ids. If an id
115: * refers to a missing descriptor, or one that is non-editable, it is
116: * skipped. If <code>null</code> is passed, all editable descriptors are
117: * returned.
118: *
119: * @param supportedWorkingSetIds
120: * the ids for the working set descriptors, or <code>null</code>
121: * for all editable descriptors
122: * @return the descriptors corresponding to the given editable working set
123: * ids
124: */
125: private static WorkingSetDescriptor[] getSupportedEditableDescriptors(
126: String[] supportedWorkingSetIds) {
127: WorkingSetRegistry registry = WorkbenchPlugin.getDefault()
128: .getWorkingSetRegistry();
129: if (supportedWorkingSetIds == null) {
130: return registry.getNewPageWorkingSetDescriptors();
131: }
132: List result = new ArrayList(supportedWorkingSetIds.length);
133: for (int i = 0; i < supportedWorkingSetIds.length; i++) {
134: WorkingSetDescriptor desc = registry
135: .getWorkingSetDescriptor(supportedWorkingSetIds[i]);
136: if (desc != null && desc.isEditable()) {
137: result.add(desc);
138: }
139: }
140: return (WorkingSetDescriptor[]) result
141: .toArray(new WorkingSetDescriptor[result.size()]);
142: }
143:
144: protected AbstractWorkingSetManager(BundleContext context) {
145: bundleContext = context;
146: bundleContext.addBundleListener(this );
147: PlatformUI
148: .getWorkbench()
149: .getExtensionTracker()
150: .registerHandler(
151: this ,
152: ExtensionTracker
153: .createExtensionPointFilter(getExtensionPointFilter()));
154: }
155:
156: /**
157: *
158: * @return
159: * @since 3.3
160: */
161: private IExtensionPoint getExtensionPointFilter() {
162: return Platform.getExtensionRegistry().getExtensionPoint(
163: PlatformUI.PLUGIN_ID,
164: IWorkbenchRegistryConstants.PL_WORKINGSETS);
165: }
166:
167: public void dispose() {
168: bundleContext.removeBundleListener(this );
169: for (Iterator iter = updaters.values().iterator(); iter
170: .hasNext();) {
171: ((IWorkingSetUpdater) iter.next()).dispose();
172: }
173:
174: for (Iterator iter = elementAdapters.values().iterator(); iter
175: .hasNext();) {
176: ((IWorkingSetElementAdapter) iter.next()).dispose();
177: }
178: }
179:
180: //---- working set creation -----------------------------------------------------
181:
182: /* (non-Javadoc)
183: * @see org.eclipse.ui.IWorkingSetManager
184: */
185: public IWorkingSet createWorkingSet(String name,
186: IAdaptable[] elements) {
187: return new WorkingSet(name, name, elements);
188: }
189:
190: public IWorkingSet createAggregateWorkingSet(String name,
191: String label, IWorkingSet[] components) {
192: return new AggregateWorkingSet(name, label, components);
193: }
194:
195: /*
196: * (non-Javadoc)
197: *
198: * @see org.eclipse.ui.IWorkingSetManager
199: */
200: public IWorkingSet createWorkingSet(IMemento memento) {
201: return restoreWorkingSet(memento);
202: }
203:
204: //---- working set management ---------------------------------------------------
205:
206: /* (non-Javadoc)
207: * @see org.eclipse.ui.IWorkingSetManager
208: */
209: public void addWorkingSet(IWorkingSet workingSet) {
210: Assert.isTrue(!workingSets.contains(workingSet),
211: "working set already registered"); //$NON-NLS-1$
212: internalAddWorkingSet(workingSet);
213: }
214:
215: private void internalAddWorkingSet(IWorkingSet workingSet) {
216: workingSets.add(workingSet);
217: ((AbstractWorkingSet) workingSet).connect(this );
218: addToUpdater(workingSet);
219: firePropertyChange(CHANGE_WORKING_SET_ADD, null, workingSet);
220: }
221:
222: /* (non-Javadoc)
223: * @see org.eclipse.ui.IWorkingSetManager
224: */
225: protected boolean internalRemoveWorkingSet(IWorkingSet workingSet) {
226: boolean workingSetRemoved = workingSets.remove(workingSet);
227: boolean recentWorkingSetRemoved = recentWorkingSets
228: .remove(workingSet);
229:
230: if (workingSetRemoved) {
231: ((AbstractWorkingSet) workingSet).disconnect();
232: removeFromUpdater(workingSet);
233: firePropertyChange(CHANGE_WORKING_SET_REMOVE, workingSet,
234: null);
235: }
236: return workingSetRemoved || recentWorkingSetRemoved;
237: }
238:
239: /* (non-Javadoc)
240: * @see org.eclipse.ui.IWorkingSetManager
241: */
242: public IWorkingSet[] getWorkingSets() {
243: SortedSet visibleSubset = new TreeSet(
244: WorkingSetComparator.INSTANCE);
245: for (Iterator i = workingSets.iterator(); i.hasNext();) {
246: IWorkingSet workingSet = (IWorkingSet) i.next();
247: if (workingSet.isVisible()) {
248: visibleSubset.add(workingSet);
249: }
250: }
251: return (IWorkingSet[]) visibleSubset
252: .toArray(new IWorkingSet[visibleSubset.size()]);
253: }
254:
255: public IWorkingSet[] getAllWorkingSets() {
256: return (IWorkingSet[]) workingSets
257: .toArray(new IWorkingSet[workingSets.size()]);
258: }
259:
260: /* (non-Javadoc)
261: * @see org.eclipse.ui.IWorkingSetManager
262: */
263: public IWorkingSet getWorkingSet(String name) {
264: if (name == null || workingSets == null) {
265: return null;
266: }
267:
268: Iterator iter = workingSets.iterator();
269: while (iter.hasNext()) {
270: IWorkingSet workingSet = (IWorkingSet) iter.next();
271: if (name.equals(workingSet.getName())) {
272: return workingSet;
273: }
274: }
275: return null;
276: }
277:
278: // ---- recent working set management --------------------------------------
279:
280: /* (non-Javadoc)
281: * @see org.eclipse.ui.IWorkingSetManager
282: */
283: public IWorkingSet[] getRecentWorkingSets() {
284: return (IWorkingSet[]) recentWorkingSets
285: .toArray(new IWorkingSet[recentWorkingSets.size()]);
286: }
287:
288: /**
289: * Adds the specified working set to the list of recently used
290: * working sets.
291: *
292: * @param workingSet working set to added to the list of recently
293: * used working sets.
294: */
295: protected void internalAddRecentWorkingSet(IWorkingSet workingSet) {
296: if (!workingSet.isVisible()) {
297: return;
298: }
299: recentWorkingSets.remove(workingSet);
300: recentWorkingSets.add(0, workingSet);
301: if (recentWorkingSets.size() > MRU_SIZE) {
302: recentWorkingSets.remove(MRU_SIZE);
303: }
304: }
305:
306: //---- equals and hash code -----------------------------------------------
307:
308: /**
309: * Tests the receiver and the object for equality
310: *
311: * @param object object to compare the receiver to
312: * @return true=the object equals the receiver, it has the same
313: * working sets. false otherwise
314: */
315: public boolean equals(Object object) {
316: if (this == object) {
317: return true;
318: }
319: if (!getClass().getName().equals(object.getClass().getName())) {
320: return false;
321: }
322: AbstractWorkingSetManager other = (AbstractWorkingSetManager) object;
323: return other.workingSets.equals(workingSets);
324: }
325:
326: /**
327: * Returns the hash code.
328: *
329: * @return the hash code.
330: */
331: public int hashCode() {
332: return workingSets.hashCode();
333: }
334:
335: //---- property listeners -------------------------------------------------
336:
337: /* (non-Javadoc)
338: * @see org.eclipse.ui.IWorkingSetManager
339: */
340: public void addPropertyChangeListener(
341: IPropertyChangeListener listener) {
342: addListenerObject(listener);
343: }
344:
345: /* (non-Javadoc)
346: * @see org.eclipse.ui.IWorkingSetManager
347: */
348: public void removePropertyChangeListener(
349: IPropertyChangeListener listener) {
350: removeListenerObject(listener);
351: }
352:
353: /**
354: * Notify property change listeners about a change to the list of
355: * working sets.
356: *
357: * @param changeId one of
358: * IWorkingSetManager#CHANGE_WORKING_SET_ADD
359: * IWorkingSetManager#CHANGE_WORKING_SET_REMOVE
360: * IWorkingSetManager#CHANGE_WORKING_SET_CONTENT_CHANGE
361: * IWorkingSetManager#CHANGE_WORKING_SET_NAME_CHANGE
362: * @param oldValue the removed working set or null if a working set
363: * was added or changed.
364: * @param newValue the new or changed working set or null if a working
365: * set was removed.
366: */
367: protected void firePropertyChange(String changeId, Object oldValue,
368: Object newValue) {
369: final Object[] listeners = getListeners();
370:
371: if (listeners.length == 0) {
372: return;
373: }
374:
375: final PropertyChangeEvent event = new PropertyChangeEvent(this ,
376: changeId, oldValue, newValue);
377: Runnable notifier = new Runnable() {
378: public void run() {
379: for (int i = 0; i < listeners.length; i++) {
380: final IPropertyChangeListener listener = (IPropertyChangeListener) listeners[i];
381: ISafeRunnable safetyWrapper = new ISafeRunnable() {
382:
383: public void run() throws Exception {
384: listener.propertyChange(event);
385: }
386:
387: public void handleException(Throwable exception) {
388: // logged by the runner
389: }
390: };
391: SafeRunner.run(safetyWrapper);
392: }
393: }
394: };
395: // Notifications are sent on the UI thread.
396: if (Display.getCurrent() != null) {
397: notifier.run();
398: } else {
399: // Use an asyncExec to avoid deadlocks.
400: Display.getDefault().asyncExec(notifier);
401: }
402: }
403:
404: /**
405: * Fires a property change event for the changed working set. Should only be
406: * called by org.eclipse.ui.internal.WorkingSet.
407: *
408: * @param changedWorkingSet
409: * the working set that has changed
410: * @param propertyChangeId
411: * the changed property. one of
412: * CHANGE_WORKING_SET_CONTENT_CHANGE,
413: * CHANGE_WORKING_SET_LABEL_CHANGE, and
414: * CHANGE_WORKING_SET_NAME_CHANGE
415: * @param oldValue
416: * the old value
417: */
418: public void workingSetChanged(IWorkingSet changedWorkingSet,
419: String propertyChangeId, Object oldValue) {
420: firePropertyChange(propertyChangeId, oldValue,
421: changedWorkingSet);
422: }
423:
424: // ---- Persistence
425: // ----------------------------------------------------------------
426:
427: /**
428: * Saves all persistable working sets in the persistence store.
429: *
430: * @param memento the persistence store
431: * @see IPersistableElement
432: */
433: public void saveWorkingSetState(IMemento memento) {
434: Iterator iterator = workingSets.iterator();
435:
436: // break the sets into aggregates and non aggregates. The aggregates should be saved after the non-aggregates
437: // so that on restoration all necessary aggregate components can be found.
438:
439: ArrayList standardSets = new ArrayList();
440: ArrayList aggregateSets = new ArrayList();
441: while (iterator.hasNext()) {
442: IWorkingSet set = (IWorkingSet) iterator.next();
443: if (set instanceof AggregateWorkingSet) {
444: aggregateSets.add(set);
445: } else {
446: standardSets.add(set);
447: }
448: }
449:
450: saveWorkingSetState(memento, standardSets);
451: saveWorkingSetState(memento, aggregateSets);
452: }
453:
454: /**
455: * @param memento the memento to save to
456: * @param list the working sets to save
457: * @since 3.2
458: */
459: private void saveWorkingSetState(IMemento memento, List list) {
460: for (Iterator i = list.iterator(); i.hasNext();) {
461: IPersistableElement persistable = (IWorkingSet) i.next();
462: IMemento workingSetMemento = memento
463: .createChild(IWorkbenchConstants.TAG_WORKING_SET);
464: workingSetMemento.putString(
465: IWorkbenchConstants.TAG_FACTORY_ID, persistable
466: .getFactoryId());
467: persistable.saveState(workingSetMemento);
468: }
469: }
470:
471: /**
472: * Recreates all working sets from the persistence store
473: * and adds them to the receiver.
474: *
475: * @param memento the persistence store
476: */
477: protected void restoreWorkingSetState(IMemento memento) {
478: IMemento[] children = memento
479: .getChildren(IWorkbenchConstants.TAG_WORKING_SET);
480: for (int i = 0; i < children.length; i++) {
481: IWorkingSet workingSet = restoreWorkingSet(children[i]);
482: if (workingSet != null) {
483: internalAddWorkingSet(workingSet);
484: }
485: }
486: }
487:
488: /**
489: * Recreates a working set from the persistence store.
490: *
491: * @param memento the persistence store
492: * @return the working set created from the memento or null if
493: * creation failed.
494: */
495: protected IWorkingSet restoreWorkingSet(IMemento memento) {
496: String factoryID = memento
497: .getString(IWorkbenchConstants.TAG_FACTORY_ID);
498:
499: if (factoryID == null) {
500: // if the factory id was not set in the memento
501: // then assume that the memento was created using
502: // IMemento.saveState, and should be restored using WorkingSetFactory
503: factoryID = AbstractWorkingSet.FACTORY_ID;
504: }
505: IElementFactory factory = PlatformUI.getWorkbench()
506: .getElementFactory(factoryID);
507: if (factory == null) {
508: WorkbenchPlugin
509: .log("Unable to restore working set - cannot instantiate factory: " + factoryID); //$NON-NLS-1$
510: return null;
511: }
512: IAdaptable adaptable = factory.createElement(memento);
513: if (adaptable == null) {
514: WorkbenchPlugin
515: .log("Unable to restore working set - cannot instantiate working set: " + factoryID); //$NON-NLS-1$
516: return null;
517: }
518: if ((adaptable instanceof IWorkingSet) == false) {
519: WorkbenchPlugin
520: .log("Unable to restore working set - element is not an IWorkingSet: " + factoryID); //$NON-NLS-1$
521: return null;
522: }
523: return (IWorkingSet) adaptable;
524: }
525:
526: /**
527: * Saves the list of most recently used working sets in the persistence
528: * store.
529: *
530: * @param memento the persistence store
531: */
532: protected void saveMruList(IMemento memento) {
533: Iterator iterator = recentWorkingSets.iterator();
534:
535: while (iterator.hasNext()) {
536: IWorkingSet workingSet = (IWorkingSet) iterator.next();
537: IMemento mruMemento = memento
538: .createChild(IWorkbenchConstants.TAG_MRU_LIST);
539:
540: mruMemento.putString(IWorkbenchConstants.TAG_NAME,
541: workingSet.getName());
542: }
543: }
544:
545: /**
546: * Restores the list of most recently used working sets from the
547: * persistence store.
548: *
549: * @param memento the persistence store
550: */
551: protected void restoreMruList(IMemento memento) {
552: IMemento[] mruWorkingSets = memento
553: .getChildren(IWorkbenchConstants.TAG_MRU_LIST);
554:
555: for (int i = mruWorkingSets.length - 1; i >= 0; i--) {
556: String workingSetName = mruWorkingSets[i]
557: .getString(IWorkbenchConstants.TAG_NAME);
558: if (workingSetName != null) {
559: IWorkingSet workingSet = getWorkingSet(workingSetName);
560: if (workingSet != null) {
561: internalAddRecentWorkingSet(workingSet);
562: }
563: }
564: }
565: }
566:
567: //---- user interface support -----------------------------------------------------
568:
569: /**
570: * @see org.eclipse.ui.IWorkingSetManager#createWorkingSetEditWizard(org.eclipse.ui.IWorkingSet)
571: * @since 2.1
572: */
573: public IWorkingSetEditWizard createWorkingSetEditWizard(
574: IWorkingSet workingSet) {
575: String editPageId = workingSet.getId();
576: WorkingSetRegistry registry = WorkbenchPlugin.getDefault()
577: .getWorkingSetRegistry();
578: IWorkingSetPage editPage = null;
579:
580: if (editPageId != null) {
581: editPage = registry.getWorkingSetPage(editPageId);
582: }
583:
584: // the following block kind of defeats IWorkingSet.isEditable() and it
585: // doesn't make sense for there to be a default page in such a case.
586:
587: if (editPage == null) {
588: editPage = registry.getDefaultWorkingSetPage();
589: if (editPage == null) {
590: return null;
591: }
592: }
593:
594: WorkingSetEditWizard editWizard = new WorkingSetEditWizard(
595: editPage);
596: editWizard.setSelection(workingSet);
597: return editWizard;
598: }
599:
600: /**
601: * @deprecated use createWorkingSetSelectionDialog(parent, true) instead
602: */
603: public IWorkingSetSelectionDialog createWorkingSetSelectionDialog(
604: Shell parent) {
605: return createWorkingSetSelectionDialog(parent, true);
606: }
607:
608: /* (non-Javadoc)
609: * @see org.eclipse.ui.IWorkingSetManager
610: */
611: public IWorkingSetSelectionDialog createWorkingSetSelectionDialog(
612: Shell parent, boolean multi) {
613: return createWorkingSetSelectionDialog(parent, multi, null);
614: }
615:
616: /**
617: * {@inheritDoc}
618: */
619: public IWorkingSetNewWizard createWorkingSetNewWizard(
620: String[] workingSetIds) {
621: WorkingSetDescriptor[] descriptors = getSupportedEditableDescriptors(workingSetIds);
622: if (descriptors.length == 0) {
623: return null;
624: }
625: return new WorkingSetNewWizard(descriptors);
626: }
627:
628: //---- working set delta handling -------------------------------------------------
629:
630: public void bundleChanged(BundleEvent event) {
631: if (event.getBundle().getSymbolicName() == null)
632: return;
633: // If the workbench isn't running anymore simply return.
634: if (!Workbench.getInstance().isRunning()) {
635: return;
636: }
637:
638: if (event.getBundle().getState() == Bundle.ACTIVE) {
639: WorkingSetDescriptor[] descriptors = WorkbenchPlugin
640: .getDefault().getWorkingSetRegistry()
641: .getUpdaterDescriptorsForNamespace(
642: event.getBundle().getSymbolicName());
643: synchronized (updaters) {
644: for (int i = 0; i < descriptors.length; i++) {
645: WorkingSetDescriptor descriptor = descriptors[i];
646: List workingSets = getWorkingSetsForId(descriptor
647: .getId());
648: if (workingSets.size() == 0) {
649: continue;
650: }
651: IWorkingSetUpdater updater = getUpdater(descriptor);
652: for (Iterator iter = workingSets.iterator(); iter
653: .hasNext();) {
654: IWorkingSet workingSet = (IWorkingSet) iter
655: .next();
656: if (!updater.contains(workingSet)) {
657: updater.add(workingSet);
658: }
659: }
660: }
661: }
662: }
663: }
664:
665: private List getWorkingSetsForId(String id) {
666: List result = new ArrayList();
667: for (Iterator iter = workingSets.iterator(); iter.hasNext();) {
668: IWorkingSet ws = (IWorkingSet) iter.next();
669: if (id.equals(ws.getId())) {
670: result.add(ws);
671: }
672: }
673: return result;
674: }
675:
676: private void addToUpdater(IWorkingSet workingSet) {
677: WorkingSetDescriptor descriptor = WorkbenchPlugin.getDefault()
678: .getWorkingSetRegistry().getWorkingSetDescriptor(
679: workingSet.getId());
680: if (descriptor == null || !descriptor.isUpdaterClassLoaded()) {
681: return;
682: }
683: synchronized (updaters) {
684: IWorkingSetUpdater updater = getUpdater(descriptor);
685: if (!updater.contains(workingSet)) {
686: updater.add(workingSet);
687: }
688: }
689: }
690:
691: private IWorkingSetUpdater getUpdater(
692: WorkingSetDescriptor descriptor) {
693: IWorkingSetUpdater updater = (IWorkingSetUpdater) updaters
694: .get(descriptor.getId());
695: if (updater == null) {
696: updater = descriptor.createWorkingSetUpdater();
697: if (updater == null) {
698: updater = NULL_UPDATER;
699: } else {
700: firePropertyChange(
701: CHANGE_WORKING_SET_UPDATER_INSTALLED, null,
702: updater);
703: PlatformUI.getWorkbench().getExtensionTracker()
704: .registerObject(
705: descriptor.getConfigurationElement()
706: .getDeclaringExtension(),
707: updater, IExtensionTracker.REF_WEAK);
708:
709: }
710: updaters.put(descriptor.getId(), updater);
711: }
712: return updater;
713: }
714:
715: IWorkingSetElementAdapter getElementAdapter(
716: WorkingSetDescriptor descriptor) {
717: IWorkingSetElementAdapter elementAdapter = (IWorkingSetElementAdapter) elementAdapters
718: .get(descriptor.getId());
719: if (elementAdapter == null) {
720: elementAdapter = descriptor
721: .createWorkingSetElementAdapter();
722: if (elementAdapter == null) {
723: elementAdapter = IDENTITY_ADAPTER;
724: } else {
725: elementAdapters.put(descriptor.getId(), elementAdapter);
726: }
727: }
728: return elementAdapter;
729: }
730:
731: private void removeFromUpdater(IWorkingSet workingSet) {
732: synchronized (updaters) {
733: IWorkingSetUpdater updater = (IWorkingSetUpdater) updaters
734: .get(workingSet.getId());
735: if (updater != null) {
736: updater.remove(workingSet);
737: }
738: }
739: }
740:
741: /* (non-Javadoc)
742: * @see org.eclipse.ui.IWorkingSetManager#createWorkingSetSelectionDialog(org.eclipse.swt.widgets.Shell, boolean, java.lang.String[])
743: */
744: public IWorkingSetSelectionDialog createWorkingSetSelectionDialog(
745: Shell parent, boolean multi, String[] workingsSetIds) {
746: return new WorkingSetSelectionDialog(parent, multi,
747: workingsSetIds);
748: }
749:
750: /**
751: * Save the state to the state file.
752: *
753: * @param stateFile
754: * @throws IOException
755: */
756: public void saveState(File stateFile) throws IOException {
757: XMLMemento memento = XMLMemento
758: .createWriteRoot(IWorkbenchConstants.TAG_WORKING_SET_MANAGER);
759: saveWorkingSetState(memento);
760: saveMruList(memento);
761:
762: FileOutputStream stream = new FileOutputStream(stateFile);
763: OutputStreamWriter writer = new OutputStreamWriter(stream,
764: "utf-8"); //$NON-NLS-1$
765: memento.save(writer);
766: writer.close();
767:
768: }
769:
770: /* (non-Javadoc)
771: * @see org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamichelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
772: */
773: public void addExtension(IExtensionTracker tracker,
774: IExtension extension) {
775: // nothing - this is handled lazily. These items are only created as needed by the getUpdater() and getElementAdapter() methods
776:
777: }
778:
779: /* (non-Javadoc)
780: * @see org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
781: */
782: public void removeExtension(IExtension extension, Object[] objects) {
783: for (int i = 0; i < objects.length; i++) {
784: Object object = objects[i];
785: if (object instanceof IWorkingSetUpdater) {
786: removeUpdater((IWorkingSetUpdater) object);
787:
788: }
789: if (object instanceof IWorkingSetElementAdapter) {
790: removeElementAdapter((IWorkingSetElementAdapter) object);
791: }
792: }
793: }
794:
795: /**
796: * Remove the element adapter from the manager and dispose of it.
797: *
798: * @param elementAdapter
799: * @since 3.3
800: */
801: private void removeElementAdapter(
802: final IWorkingSetElementAdapter elementAdapter) {
803: SafeRunner.run(new ISafeRunnable() {
804:
805: public void handleException(Throwable exception) {
806: StatusManager.getManager().handle(
807: StatusUtil.newStatus(PlatformUI.PLUGIN_ID,
808: exception));
809: }
810:
811: public void run() throws Exception {
812: elementAdapter.dispose();
813:
814: }
815: });
816: synchronized (elementAdapters) {
817: elementAdapters.values().remove(elementAdapter);
818: }
819: }
820:
821: /**
822: * Remove the updater from the manager and dispose of it.
823: *
824: * @param updater
825: * @since 3.3
826: */
827: private void removeUpdater(final IWorkingSetUpdater updater) {
828: SafeRunner.run(new ISafeRunnable() {
829:
830: public void handleException(Throwable exception) {
831: StatusManager.getManager().handle(
832: StatusUtil.newStatus(PlatformUI.PLUGIN_ID,
833: exception));
834: }
835:
836: public void run() throws Exception {
837: updater.dispose();
838:
839: }
840: });
841: synchronized (updaters) {
842: updaters.values().remove(updater);
843: }
844: firePropertyChange(
845: IWorkingSetManager.CHANGE_WORKING_SET_UPDATER_UNINSTALLED,
846: updater, null);
847: }
848:
849: /*
850: * (non-Javadoc)
851: *
852: * @see org.eclipse.ui.IWorkingSetManager#addToWorkingSets(org.eclipse.core.runtime.IAdaptable,
853: * org.eclipse.ui.IWorkingSet[])
854: */
855: public void addToWorkingSets(IAdaptable element,
856: IWorkingSet[] workingSets) {
857: // ideally this method would be in a static util class of some kind but
858: // we dont have any such beast for working sets and making one for one
859: // method is overkill.
860: for (int i = 0; i < workingSets.length; i++) {
861: IWorkingSet workingSet = workingSets[i];
862: IAdaptable[] adaptedNewElements = workingSet
863: .adaptElements(new IAdaptable[] { element });
864: if (adaptedNewElements.length == 1) {
865: IAdaptable[] elements = workingSet.getElements();
866: IAdaptable[] newElements = new IAdaptable[elements.length + 1];
867: System.arraycopy(elements, 0, newElements, 0,
868: elements.length);
869: newElements[newElements.length - 1] = adaptedNewElements[0];
870: workingSet.setElements(newElements);
871: }
872: }
873: }
874: }
|