Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: f0b0510d4f90d0945d974ecdf059b0804aca5610 (plain) (tree)




















































































































































































































































































































































                                                                                                                                          
/*
 * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany) 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:
 *    Eike Stepper - initial API and implementation
 */
package org.eclipse.emf.cdo.releng.preferences.util;

import org.eclipse.emf.cdo.releng.preferences.PreferenceNode;
import org.eclipse.emf.cdo.releng.preferences.PreferencesFactory;
import org.eclipse.emf.cdo.releng.preferences.Property;

import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.NodeChangeEvent;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;

import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author Eike Stepper
 */
public final class PreferencesUtil
{
  /**
   * A resource load option to load an instance using {@link #getRootPreferenceNode(boolean) PreferencesUtil.getRootPreferenceNode(true)}.
   * The resource must be {@link Resource#unload() unloaded}, to avoid dangling listeners.
   */
  public static final String OPTION_SYNCHRONIZED_PREFERENCES = "SYNCHRONIZED_PREFERENCES";

  private static final IEclipsePreferences ROOT = Platform.getPreferencesService().getRootNode();

  public static final URI ROOT_PREFERENCE_NODE_URI = URI.createURI("preference:/");

  private static class PreferencesAdapter extends AdapterImpl implements IEclipsePreferences.INodeChangeListener,
      IEclipsePreferences.IPreferenceChangeListener
  {
    protected IEclipsePreferences preferences;

    public PreferencesAdapter(IEclipsePreferences preferences)
    {
      this.preferences = preferences;

      preferences.addNodeChangeListener(this);
      preferences.addPreferenceChangeListener(this);
    }

    @Override
    public boolean isAdapterForType(Object type)
    {
      return type == PreferencesAdapter.class;
    }

    public void preferenceChange(PreferenceChangeEvent event)
    {
      PreferenceNode preferenceNode = (PreferenceNode)target;
      String name = event.getKey();
      Object value = event.getNewValue();
      EList<Property> properties = preferenceNode.getProperties();
      for (int i = 0, size = properties.size(); i < size; ++i)
      {
        Property property = properties.get(i);
        int comparison = property.getName().compareTo(name);
        if (comparison == 0)
        {
          if (value == null)
          {
            properties.remove(i);
          }
          else
          {
            property.setValue(value.toString());
          }
          return;
        }
        else if (comparison > 0)
        {
          if (value != null)
          {
            property = PreferencesFactory.eINSTANCE.createProperty();
            property.setName(name);
            property.setValue(value.toString());
            properties.add(i, property);
          }
          return;
        }
      }
      Property property = PreferencesFactory.eINSTANCE.createProperty();
      property.setName(name);
      property.setValue(value.toString());
      properties.add(property);
    }

    public void added(NodeChangeEvent event)
    {
      PreferenceNode preferenceNode = (PreferenceNode)target;
      Preferences childNode = event.getChild();
      PreferenceNode childPreferenceNode = PreferencesFactory.eINSTANCE.createPreferenceNode();
      String name = childNode.name();
      childPreferenceNode.setName(name);
      traverse(childPreferenceNode, childNode, true);
      EList<PreferenceNode> children = preferenceNode.getChildren();
      for (int i = 0, size = children.size(); i < size; ++i)
      {
        PreferenceNode otherChildPreferenceNode = children.get(i);
        if (otherChildPreferenceNode.getName().compareTo(name) >= 0)
        {
          children.add(i, childPreferenceNode);
          return;
        }
      }
      children.add(childPreferenceNode);
    }

    public void removed(NodeChangeEvent event)
    {
      PreferenceNode preferenceNode = (PreferenceNode)target;
      Preferences childNode = event.getChild();
      String name = childNode.name();
      EList<PreferenceNode> children = preferenceNode.getChildren();
      for (int i = 0, size = children.size(); i < size; ++i)
      {
        PreferenceNode childPreferenceNode = children.get(i);
        if (childPreferenceNode.getName().equals(name))
        {
          children.remove(i);
          return;
        }
      }
    }

    @Override
    public void unsetTarget(Notifier oldTarget)
    {
      super.unsetTarget(oldTarget);

      preferences.removeNodeChangeListener(this);
      preferences.removePreferenceChangeListener(this);
    }
  }

  public static PreferenceNode getRootPreferenceNode()
  {
    return getRootPreferenceNode(false);
  }

  public static PreferenceNode getRootPreferenceNode(boolean isSynchronized)
  {
    ResourceSet resourceSet = new ResourceSetImpl();
    Resource resource = resourceSet.createResource(ROOT_PREFERENCE_NODE_URI.appendSegment("*.preferences"));
    PreferenceNode root = PreferencesFactory.eINSTANCE.createPreferenceNode();
    traverse(root, ROOT, isSynchronized);
    resource.getContents().add(root);

    return root;
  }

  private static void traverse(PreferenceNode preferenceNode, Preferences node, boolean isSynchronized)
  {
    try
    {
      if (isSynchronized && node instanceof IEclipsePreferences)
      {
        preferenceNode.eAdapters().add(new PreferencesAdapter((IEclipsePreferences)node));
      }

      preferenceNode.setName(node.name());

      EList<PreferenceNode> children = preferenceNode.getChildren();
      String[] childrenNames = node.childrenNames();
      Arrays.sort(childrenNames);
      for (String name : childrenNames)
      {
        Preferences childNode = node.node(name);
        PreferenceNode childPreferenceNode = PreferencesFactory.eINSTANCE.createPreferenceNode();
        traverse(childPreferenceNode, childNode, isSynchronized);
        children.add(childPreferenceNode);
      }
      EList<Property> properties = preferenceNode.getProperties();
      String[] keys = node.keys();
      Arrays.sort(keys);
      for (String name : keys)
      {
        Property property = PreferencesFactory.eINSTANCE.createProperty();
        property.setName(name);
        property.setValue(node.get(name, null));
        properties.add(property);
      }
    }
    catch (BackingStoreException ex)
    {
      // Ignore
    }
  }

  public static Preferences getPreferences(PreferenceNode preferenceNode, boolean demandCreate)
      throws BackingStoreException
  {
    if (preferenceNode == null)
    {
      return ROOT;
    }

    Preferences parentPreferences = getPreferences(preferenceNode.getParent(), demandCreate);
    if (parentPreferences != null)
    {
      String name = preferenceNode.getName();
      if (demandCreate || parentPreferences.nodeExists(name))
      {
        return parentPreferences.node(name);
      }
    }
    return null;
  }

  public static IPath getLocation(Preferences preferences)
  {
    if (preferences == null)
    {
      return null;
    }

    try
    {
      Method getLocationMethod = preferences.getClass().getDeclaredMethod("getLocation");
      getLocationMethod.setAccessible(true);
      IPath location = (IPath)getLocationMethod.invoke(preferences);
      return location;
    }
    catch (Exception ex)
    {
      // Ignore
    }

    return null;
  }

  private static List<PreferenceNode> getPath(PreferenceNode preferenceNode)
  {
    List<PreferenceNode> path = new ArrayList<PreferenceNode>();
    while (preferenceNode != null)
    {
      path.add(preferenceNode);
      preferenceNode = preferenceNode.getParent();
    }
    Collections.reverse(path);
    return path;
  }

  public static PreferenceNode getAncestor(PreferenceNode preferenceNode)
  {
    List<PreferenceNode> path = getPath(preferenceNode);
    int size = path.size();
    if (size > 1)
    {
      PreferenceNode root = path.get(0);
      if ("".equals(root.getName()))
      {
        PreferenceNode base = path.get(1);
        String name = base.getName();
        int start = 2;
        if ("project".equals(name))
        {
          name = "instance";
          PreferenceNode result = root.getNode(name);
          for (int i = ++start; result != null && i < size; ++i)
          {
            result = result.getNode(path.get(i).getName());
          }
          if (result != null)
          {
            return result;
          }
        }

        if ("instance".equals(name))
        {
          name = "default";
          PreferenceNode result = root.getNode(name);
          for (int i = start; result != null && i < size; ++i)
          {
            result = result.getNode(path.get(i).getName());
          }
          if (result != null)
          {
            return result;
          }
        }

        if ("default".equals(name))
        {
          name = "configuration";
          PreferenceNode result = root.getNode(name);
          for (int i = start; result != null && i < size; ++i)
          {
            result = result.getNode(path.get(i).getName());
          }
          if (result != null)
          {
            return result;
          }
        }

        if ("configuration".equals(name))
        {
          name = "bundle_defaults";
          PreferenceNode result = root.getNode(name);
          for (int i = start; result != null && i < size; ++i)
          {
            result = result.getNode(path.get(i).getName());
          }
          if (result != null)
          {
            return result;
          }
        }
      }
    }
    return null;
  }
}

Back to the top