Last active
August 29, 2015 14:15
-
-
Save vladdu/9834a2a0b04ef0fbeb55 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.eclipse.core.runtime.Path; | |
public interface IPreferenceNotifier { | |
void changed(Path path, String key, String newValue); | |
void added(Path path, String key); | |
void removed(Path path, String key); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************************* | |
* Copyright (C) 2010, 2015, Google Inc. 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 | |
*******************************************************************************/ | |
import java.util.Set; | |
import org.eclipse.core.runtime.CoreException; | |
import org.eclipse.core.runtime.IStatus; | |
import org.eclipse.core.runtime.Path; | |
import org.eclipse.core.runtime.Platform; | |
import org.eclipse.core.runtime.Status; | |
import org.eclipse.core.runtime.preferences.IEclipsePreferences; | |
import org.eclipse.core.runtime.preferences.IEclipsePreferences.INodeChangeListener; | |
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; | |
import org.eclipse.core.runtime.preferences.IEclipsePreferences.NodeChangeEvent; | |
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; | |
import org.osgi.service.prefs.BackingStoreException; | |
import com.google.common.base.Preconditions; | |
import com.google.common.collect.Sets; | |
/** | |
* Watches changes to Eclipse's preference tree, and sends notifications for | |
* each change. | |
* | |
* @author [email protected] (Brian Chin) | |
* @author [email protected] (Vlad Dumitrescu) | |
*/ | |
public class PreferenceWatcher { | |
private class WatcherListener implements INodeChangeListener, | |
IPreferenceChangeListener { | |
@Override | |
public void added(final NodeChangeEvent event) { | |
synchronized (lock) { | |
// It's possible that we've stopped watching, but the listeners | |
// have not yet been removed. | |
// Ensure that we're still watching before writing new data | |
if (currState != State.WATCHING) { | |
return; | |
} | |
final IEclipsePreferences childPrefs = (IEclipsePreferences) event | |
.getChild(); | |
addListener(childPrefs); | |
notifier.added(new Path(event.getParent().absolutePath()), event | |
.getChild().name()); | |
} | |
} | |
@Override | |
public void removed(final NodeChangeEvent event) { | |
synchronized (lock) { | |
if (currState != State.WATCHING) { | |
return; | |
} | |
recordedNodes.remove(event.getChild()); | |
notifier.removed(new Path(event.getParent().absolutePath()), event | |
.getChild().name()); | |
} | |
} | |
@Override | |
public void preferenceChange(final PreferenceChangeEvent event) { | |
synchronized (lock) { | |
if (currState != State.WATCHING) { | |
return; | |
} | |
notifier.changed(new Path(event.getNode().absolutePath()), | |
event.getKey(), (String) event.getNewValue()); | |
} | |
} | |
} | |
private enum State { | |
IDLE, WATCHING, COMPLETE | |
} | |
private final Object lock = new Object(); | |
private volatile State currState = State.IDLE; | |
private final WatcherListener listener = new WatcherListener(); | |
private final Set<IEclipsePreferences> recordedNodes = Sets.newHashSet(); | |
IPreferenceNotifier notifier; | |
/** | |
* Starts the process of watching changes to the eclipse preference tree. | |
* Watching may only occur once per recorder. | |
* | |
* @throws CoreException | |
* if there is a problem with the preference tree itself. | |
* @throws IllegalStateException | |
* if this object has already been used to record. | |
*/ | |
public void startWatching(final IPreferenceNotifier aNotifier) throws CoreException { | |
synchronized (lock) { | |
Preconditions.checkState(currState == State.IDLE, | |
"Recorder object has already recorded preference changes."); | |
currState = State.WATCHING; | |
notifier = aNotifier; | |
this.addListeners(Platform.getPreferencesService().getRootNode()); | |
} | |
} | |
private void addListeners(final IEclipsePreferences node) throws CoreException { | |
addListener(node); | |
try { | |
for (final String childName : node.childrenNames()) { | |
final IEclipsePreferences child = (IEclipsePreferences) node | |
.node(childName); | |
this.addListeners(child); | |
} | |
} catch (final BackingStoreException e) { | |
throw new CoreException(new Status(IStatus.ERROR, ModelPlugin.PLUGIN_ID, | |
"Could not read children for preference node", e)); | |
} | |
} | |
/** | |
* Ends the watching process. No other changes to the preference tree are | |
* reported after this method is called. | |
* | |
* @throws IllegalStateException | |
* if {@code startRecording()} had not been previously called, | |
* or if watching has already completed on this object. | |
*/ | |
public void endWatching() { | |
synchronized (lock) { | |
Preconditions.checkState(currState == State.WATCHING, | |
"Recorder object is not currently watching"); | |
currState = State.COMPLETE; | |
notifier = null; | |
for (final IEclipsePreferences node : recordedNodes) { | |
node.removeNodeChangeListener(listener); | |
node.removePreferenceChangeListener(listener); | |
} | |
recordedNodes.clear(); | |
} | |
} | |
/** | |
* Returns true if this object is currently watching. | |
*/ | |
public boolean isWatching() { | |
return this.currState == State.WATCHING; | |
} | |
private void addListener(final IEclipsePreferences node) { | |
node.addNodeChangeListener(listener); | |
node.addPreferenceChangeListener(listener); | |
recordedNodes.add(node); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment