blob: 6834bb17d5164f854f0e5213b80bde321622b8d4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.core.internal.preferences;
import java.io.File;
import java.io.IOException;
import java.util.*;
import org.eclipse.core.internal.runtime.InternalPlatform;
import org.eclipse.core.internal.runtime.SafeFileInputStream;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.osgi.framework.Bundle;
import org.osgi.service.prefs.BackingStoreException;
/**
* @since 3.0
*/
public class InstancePreferences extends EclipsePreferences {
private static final String DEFAULT_PREFERENCES_FILENAME = "prefs.ini"; //$NON-NLS-1$
private static final String OLD_EXTENSION = ".old"; //$NON-NLS-1$
// cached values
private String qualifier;
private int segmentCount;
private EclipsePreferences loadLevel;
private IPath location;
// cache which nodes have been loaded from disk
private static Set loadedNodes = new HashSet();
/**
* Default constructor. Should only be called by #createExecutableExtension.
*/
public InstancePreferences() {
this(null, null);
}
private InstancePreferences(IEclipsePreferences parent, String name) {
super(parent, name);
initialize();
}
protected boolean isAlreadyLoaded(IEclipsePreferences node) {
return loadedNodes.contains(node.name());
}
protected void loaded() {
loadedNodes.add(name());
}
/*
* @see org.osgi.service.prefs.Preferences#sync()
*/
public void sync() throws BackingStoreException {
if (location == null) {
if (InternalPlatform.DEBUG_PREFERENCES)
System.out.println("Unable to determine location of preference file for node: " + absolutePath()); //$NON-NLS-1$
return;
}
IEclipsePreferences node = getLoadLevel();
if (node == null) {
if (InternalPlatform.DEBUG_PREFERENCES)
System.out.println("Preference node is not a load root: " + absolutePath()); //$NON-NLS-1$
return;
}
if (node instanceof EclipsePreferences) {
((EclipsePreferences) node).load(location);
node.flush();
}
}
/**
* Load the Eclipse 2.1 preferences for the given bundle. If a file
* doesn't exist then assume that conversion has already occurred
* and do nothing.
*/
protected void loadLegacy() {
IPath path = new Path(absolutePath());
if (path.segmentCount() != 2)
return;
String bundleName = path.segment(1);
// the preferences file is located in the plug-in's state area at a well-known name
// don't need to create the directory if there are no preferences to load
File prefFile = InternalPlatform.getDefault().getMetaArea().getPreferenceLocation(bundleName, false).toFile();
if (!prefFile.exists()) {
// no preference file - that's fine
if (InternalPlatform.DEBUG_PREFERENCES)
System.out.println("Legacy plug-in preference file not found: " + prefFile); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
if (InternalPlatform.DEBUG_PREFERENCES)
System.out.println("Loading legacy preferences from " + prefFile); //$NON-NLS-1$
// load preferences from file
SafeFileInputStream input = null;
Properties values = new Properties();
try {
input = new SafeFileInputStream(prefFile);
values.load(input);
} catch (IOException e) {
// problems loading preference store - quietly ignore
if (InternalPlatform.DEBUG_PREFERENCES) {
String message = "IOException encountered loading legacy preference file " + prefFile; //$NON-NLS-1$
IStatus status = new Status(IStatus.ERROR, Platform.PI_RUNTIME, IStatus.ERROR, message, e);
log(status);
}
return;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
// ignore problems with close
if (InternalPlatform.DEBUG_PREFERENCES) {
System.out.println("IOException encountered closing legacy preference file " + prefFile); //$NON-NLS-1$
e.printStackTrace();
}
}
}
}
if (properties == null)
properties = new Properties();
// Store values in the preferences object
for (Iterator i = values.keySet().iterator(); i.hasNext();) {
String key = (String) i.next();
String value = values.getProperty(key);
// value shouldn't be null but check just in case...
if (value != null) {
if (InternalPlatform.DEBUG_PREFERENCES)
System.out.println("Loaded legacy preference: " + key + " -> " + value); //$NON-NLS-1$ //$NON-NLS-2$
properties.put(key, value);
}
}
// Rename the old file so we don't try and load it next time.
File destFile = new File(prefFile.getAbsolutePath() + OLD_EXTENSION + '.' + System.currentTimeMillis());
if (!prefFile.renameTo(destFile))
//Only print out message in failure case if we are debugging.
if (InternalPlatform.DEBUG_PREFERENCES)
System.out.println("Unable to rename legacy preferences file: " + prefFile + " -> " + destFile); //$NON-NLS-1$ //$NON-NLS-2$
}
protected IPath getLocation() {
return location;
}
/*
* Parse this node's absolute path and initialize some cached values for
* later use.
*/
private void initialize() {
// cache the segment count
IPath path = new Path(absolutePath());
segmentCount = path.segmentCount();
if (segmentCount < 2)
return;
// cache the qualifier
String scope = path.segment(0);
if (InstanceScope.SCOPE.equals(scope))
qualifier = path.segment(1);
// cache the location
if (qualifier == null)
return;
// get the base location from the platform
InternalPlatform platform = InternalPlatform.getDefault();
Bundle bundle = platform.getBundle(qualifier);
if (bundle == null)
return;
location = platform.getStateLocation(bundle).append(DEFAULT_PREFERENCES_FILENAME);
}
/*
* Return the node at which these preferences are loaded/saved.
*/
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.
EclipsePreferences node = this;
for (int i = 2; i < segmentCount; i++)
node = (EclipsePreferences) node.parent();
loadLevel = node;
}
return loadLevel;
}
protected EclipsePreferences internalCreate(IEclipsePreferences nodeParent, String nodeName) {
return new InstancePreferences(nodeParent, nodeName);
}
}