Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Rich Client Platform (RCP) » No UserScope?(How to store preferences on a per user base?)
icon5.gif  No UserScope? [message #649434] Wed, 19 January 2011 03:57 Go to next message
Michael Breu is currently offline Michael Breu
Messages: 19
Registered: April 2010
Location: Inzing, Austria
Junior Member
Hello,

We implement an RCP-client that needs to store preferences on a per user base.

I have found implementations for InstanceScope, ConfigurationScope, ProjectScope, (in standard eclipse (galileo) ..., however no implementation for UserScope.

Interestingly the FAQ http://www.eclipse.org/eclipse/platform-core/documents/user_ settings/faq.html#basicGet mentions in 4a a class UserScope, but does not give details.

My questions:


  • Is there an "official" implementation of a UserScope?
  • If not: I have seen in my home-directory an ".eclipse" folder with some internal structure: which class/package/plug-in manages this folder? Can it be reused for arbitrary preferences? Or at least, does it provide some public API to implement my own preferences in this folder (just to avoid proliferation of individual private folders Rolling Eyes )?
  • Is there any other example implementation for a UserScope?. I have seen that the code for the ProjectScope can be adapted quite easily, however I would prefer some "standard" solution.


Thank you for your support

Michael

[Updated on: Wed, 19 January 2011 03:58]

Report message to a moderator

Re: No UserScope? [message #649496 is a reply to message #649434] Wed, 19 January 2011 08:28 Go to previous messageGo to next message
Paul Webster is currently offline Paul Webster
Messages: 6859
Registered: July 2009
Location: Ottawa
Senior Member

Looks like it is not implemented, although the low level support is there.

Ex you could implement it by mirroring InstanceScope,
InstancePreferences, and using the user filter from
org.eclipse.osgi.service.datalocation.Location

PW

--
Paul Webster
http://wiki.eclipse.org/Platform_Command_Framework
http://wiki.eclipse.org/Command_Core_Expressions
http://wiki.eclipse.org/Platform_Expression_Framework
http://wiki.eclipse.org/Menu_Contributions
http://wiki.eclipse.org/Menus_Extension_Mapping
http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse .platform.doc.isv/guide/workbench.htm


Re: No UserScope? [message #649674 is a reply to message #649496] Thu, 20 January 2011 04:10 Go to previous messageGo to next message
Michael Breu is currently offline Michael Breu
Messages: 19
Registered: April 2010
Location: Inzing, Austria
Junior Member
Hello Paul,

Thank you for your reply.

I have derived my solution from ProjectScope and ProjectPreferences, but it seems to make not much difference.

The solution is problematic, because the exported package API is for usage of the PreferenceInterface, but not for extending and inheriting from EclipsePreferences. Thus I get a lot of "Discouraged Access"-warnings.

Also the precise behaviour of EclipsePreferences was not absolutely clear to me.

But it seems to work now.

I add it here for reference by other users. It has some minor dependencies to other classes, which should be easily resolvable.

Enjoy it, but it may still not be perfect. It would be better to include it directly into the org.eclipse.equinox,preferences package.

Usage
		prefStore = new ScopedPreferenceStore(new UserScope(symbolicBundleName), "someUserData");


Class Definitions
package at.arctis.license.client.preferences;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.osgi.service.prefs.Preferences;

public class UserScope implements IScopeContext {

	/**
	 * String constant (value of <code>"user"</code>) used for the 
	 * scope name for this preference scope.
	 */
	public static final String SCOPE = "user"; //$NON-NLS-1$

	/**
	 * the root context.
	 */
	String context = "";

	protected UserPreferences licUserPreferences = null;
	
	/**
	 * Create and return a new user scope with the given context.
	 * 
	 * @param context the context
	 */
	public UserScope(String context) {
		this.context = context;
		licUserPreferences = 
			(UserPreferences) new UserPreferences().node(UserScope.SCOPE).node(context);
	}
	public UserScope() {
		this("");
	}

	/*
	 * @see org.eclipse.core.runtime.IScopeContext#getNode(java.lang.String)
	 */
	public IEclipsePreferences getNode(String qualifier) {
		if (qualifier == null)
			throw new IllegalArgumentException();
		final Preferences qualifierNode = licUserPreferences.node(qualifier);
		return (IEclipsePreferences) qualifierNode;
	}

	/**
	 * @see org.eclipse.core.runtime.preferences.IScopeContext#getLocation()
	 */
	public IPath getLocation() {
		return UserPreferences.getStaticLocation();
	}

	/**
	 * @see org.eclipse.core.runtime.preferences.IScopeContext#getName()
	 */
	public String getName() {
		return SCOPE;
	}

	/**
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (!(obj instanceof UserScope))
			return false;
		UserScope other = (UserScope) obj;
		return context.equals(other.context);
	}

	/**
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return super.hashCode() + context.hashCode();
	}

}



/*******************************************************************************
 * 
 * Copyright (c) 2004, 2008 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
 *     arctis Softwaretechnologie - Derived from class org.eclipse.core.internal.resources.ProjectPreferences
 */
package at.arctis.license.client.preferences;

import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;

import org.eclipse.core.internal.preferences.EclipsePreferences;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IPath;
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.osgi.service.datalocation.Location;

public class UserPreferences extends EclipsePreferences {

	// cached values
	private String qualifier;
	private IEclipsePreferences loadLevel;
	int segmentCount;
	// cache which nodes have been loaded from disk
	private static Set<String> loadedNodes = Collections.synchronizedSet(new HashSet<String>());
	private static boolean initialized = false;
	private static IPath baseLocation;
	private IPath location;

	static {
		ILog logger = Platform.getLog(Platform.getBundle(AbstractLicensePreferencePage.PLUGIN_ID));
		
		
		Location something = Platform.getUserLocation();
		System.err.println(something.getURL());
		
		String userHome = System.getProperty("user.home");

		if (userHome == null) {
			logger
					.log(new Status(Status.WARNING, AbstractLicensePreferencePage.PLUGIN_ID,
							"Cannot determine user home"));
		} else {
			File homeDir = new File(userHome);
			final File eclipsePrefDir = new File(homeDir, ".eclipse");
			if ((!eclipsePrefDir.exists() && !homeDir.canWrite()) || !eclipsePrefDir.canWrite()) {
				logger.log(new Status(Status.WARNING, AbstractLicensePreferencePage.PLUGIN_ID,
						"Cannot write to user home at " + homeDir.getAbsolutePath()));
			} else {
				baseLocation = new Path(eclipsePrefDir.getAbsolutePath());
			}
		}
	}

	/**
	 * Default constructor. Should only be called by #createExecutableExtension.
	 */
	public UserPreferences() {
		this(null, null);
	}

	private UserPreferences(EclipsePreferences parent, String name) {
		super(parent, name);

		initializeChildren();

//		// cache the segment count
		String path = absolutePath();
		StringTokenizer tokenizer = new StringTokenizer(path, String.valueOf(IPath.SEPARATOR));
		segmentCount = tokenizer.countTokens();
		if (segmentCount < 2)
			return;

		// cache the qualifier
		qualifier = getSegment(path, 1);

		// cache the location
		if (qualifier == null)
			return;
		if (baseLocation != null)
			location = computeLocation(baseLocation, qualifier);
	}

	@Override
	public IPath getLocation() {
		return location;
	}

	public static IPath getStaticLocation() {
		return baseLocation;
	}

	@Override
	protected boolean isAlreadyLoaded(IEclipsePreferences node) {
		return loadedNodes.contains(node.name());
	}

	@Override
	protected void loaded() {
		loadedNodes.add(name());
	}

	/*
	 * Return the node at which these preferences are loaded/saved.
	 */
	@Override
	protected IEclipsePreferences getLoadLevel() {
		if (loadLevel == null) {
			if (qualifier == null)
				return null;
			// Make it relative to this node rather than navigating to it from
			// the root.
			// Walk backwards up the tree starting at this node.
			// This is important to avoid a chicken/egg thing on startup.
			IEclipsePreferences node = this;
			for (int i = 2; i < segmentCount; i++)
				node = (EclipsePreferences) node.parent();
			loadLevel = node;
		}
		return loadLevel;
	}

	protected void initializeChildren() {
		if (initialized || parent == null)
			return;
		try {
			synchronized (this) {
				if (baseLocation == null)
					return;
				String[] names = computeChildren(baseLocation);
				for (int i = 0; i < names.length; i++)
					addChild(names[i], null);
			}
		} finally {
			initialized = true;
		}
	}
	@Override
	protected EclipsePreferences internalCreate(EclipsePreferences nodeParent, String nodeName, Object context) {
		return new UserPreferences(nodeParent, nodeName);
	}
}

[Updated on: Thu, 20 January 2011 04:12]

Report message to a moderator

Re: No UserScope? [message #649724 is a reply to message #649674] Thu, 20 January 2011 07:47 Go to previous messageGo to next message
Paul Webster is currently offline Paul Webster
Messages: 6859
Registered: July 2009
Location: Ottawa
Senior Member

On 01/20/2011 04:11 AM, Michael Breu wrote:
>
> static {
> ILog logger =
> Platform.getLog(Platform.getBundle(AbstractLicensePreference Page.PLUGIN_ID));
>
>
>
> Location something = Platform.getUserLocation();
> System.err.println(something.getURL());
>
> String userHome = System.getProperty("user.home");
>
> if (userHome == null) {
> logger
> .log(new Status(Status.WARNING, AbstractLicensePreferencePage.PLUGIN_ID,
> "Cannot determine user home"));
> } else {
> File homeDir = new File(userHome);
> final File eclipsePrefDir = new File(homeDir, ".eclipse");
> if ((!eclipsePrefDir.exists() && !homeDir.canWrite()) ||
> !eclipsePrefDir.canWrite()) {
> logger.log(new Status(Status.WARNING,
> AbstractLicensePreferencePage.PLUGIN_ID,
> "Cannot write to user home at " + homeDir.getAbsolutePath()));
> } else {
> baseLocation = new Path(eclipsePrefDir.getAbsolutePath());
> }
> }
> }
>

I'm not that familiar with this kind of code, so on the surface it looks
OK. The only thing I would suggest is using the OSGi Location service
instead of a property. Something similar to:

BundleContext context = Activator.getContext();
Filter filter = null;
try {
filter = context.createFilter(Location.USER_FILTER);
} catch (InvalidSyntaxException e) {
// ignore this.
}

userLocationTracker = new ServiceTracker(context, filter, null);
userLocationTracker.open();
Location location = (Location) userLocationTracker.getService();
if (location != null) {
URL url = location.getURL();
if (url != null)
baseLocation = new Path(url.getFile());
}

This is similar to what is done in
org.eclipse.core.internal.preferences.PreferencesOSGiUtils ... you have
to remember to close the service tracker when you're done.

PW


--
Paul Webster
http://wiki.eclipse.org/Platform_Command_Framework
http://wiki.eclipse.org/Command_Core_Expressions
http://wiki.eclipse.org/Platform_Expression_Framework
http://wiki.eclipse.org/Menu_Contributions
http://wiki.eclipse.org/Menus_Extension_Mapping
http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse .platform.doc.isv/guide/workbench.htm


Re: No UserScope? [message #649764 is a reply to message #649724] Thu, 20 January 2011 09:45 Go to previous messageGo to next message
Michael Breu is currently offline Michael Breu
Messages: 19
Registered: April 2010
Location: Inzing, Austria
Junior Member
Hi Paul,

You have recognized that a piece of debug code slipped into the final version.

Actually on my (Windows7/eclipse 3.5) Platform.getUserLocation() returned null. And I did not find the way to use the filter directly.

So I implemented the other way.

I will give your proposal a try.

Thank you

Michael

Re: No UserScope? [message #649849 is a reply to message #649764] Thu, 20 January 2011 13:08 Go to previous message
Paul Webster is currently offline Paul Webster
Messages: 6859
Registered: July 2009
Location: Ottawa
Senior Member

Oh, Platform.getUserLocation().getURL() is the equvalent of most of what
I wrote (it uses the ServiceTracker behind the scenes). In my running
eclipse for
System.out.println(Platform.getUserLocation().getURL());
I get
file:/opt/users/pwebster/user/

PW

--
Paul Webster
http://wiki.eclipse.org/Platform_Command_Framework
http://wiki.eclipse.org/Command_Core_Expressions
http://wiki.eclipse.org/Platform_Expression_Framework
http://wiki.eclipse.org/Menu_Contributions
http://wiki.eclipse.org/Menus_Extension_Mapping
http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse .platform.doc.isv/guide/workbench.htm


Previous Topic:splash not shown when run from ide on linux
Next Topic:Initialize a view that was contributed via perspective extensions
Goto Forum:
  


Current Time: Sat Aug 02 04:43:51 EDT 2014

Powered by FUDForum. Page generated in 0.02455 seconds