/** * (C) Copyright 2013 Jabylon (http://www.jabylon.org) 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 */ /** * */ package org.jabylon.common.util; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.emf.common.util.URI; import org.jabylon.common.resolver.URIResolver; import org.jabylon.properties.Project; import org.jabylon.properties.PropertiesFactory; import org.jabylon.properties.PropertiesPackage; import org.jabylon.properties.ScanConfiguration; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceReference; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; /** * @author Johannes Utzig (jutzig.dev@googlemail.com) * */ public class PreferencesUtil { private static final Logger LOGGER = LoggerFactory.getLogger(PreferencesUtil.class); public static final String SCAN_CONFIG_INCLUDE = "include"; public static final String SCAN_CONFIG_EXCLUDE = "exclude"; public static final String SCAN_CONFIG_MASTER_LOCALE = "master.locale"; public static final String NODE_CHECKS = "checks"; public static final Supplier<URIResolver> resolver = Suppliers.memoize(Suppliers.compose(new Function<BundleContext, URIResolver>() { @Override public URIResolver apply(BundleContext input) { ServiceReference<URIResolver> reference = input.getServiceReference(URIResolver.class); if(reference!=null) return input.getService(reference); return null; } }, Suppliers.ofInstance(FrameworkUtil.getBundle(PreferencesUtil.class).getBundleContext()))); private static boolean isMigrated = false; private PreferencesUtil() { //hide utility class constructor } public static Preferences scopeFor(Object eobject) { migrate(); URI uri = resolver.get().getURI(eobject); String path = uri.toString(); IEclipsePreferences rootNode = InstanceScope.INSTANCE.getNode(ApplicationConstants.CONFIG_NODE); return rootNode.node(path); } /** * converts a pref node path to a URI that can be resolved by an {@link URIResolver} * @param prefs * @return */ public static URI toLookupURI(Preferences prefs) { String absolutePath = prefs.absolutePath(); absolutePath = absolutePath.substring(ApplicationConstants.CONFIG_NODE.length()); return URI.createURI(absolutePath); } private static void migrate() { if(isMigrated) return; IEclipsePreferences oldNode = InstanceScope.INSTANCE.getNode(ApplicationConstants.OLD_PLUGIN_ID); try { if(oldNode.nodeExists("config")) { LOGGER.info("Migrating old Preferences"); IEclipsePreferences newNode = InstanceScope.INSTANCE.getNode(ApplicationConstants.PLUGIN_ID); cloneNode(oldNode, newNode); deleteNode(oldNode.node("config")); } IEclipsePreferences node = InstanceScope.INSTANCE.getNode(ApplicationConstants.CONFIG_NODE); String[] childrenNames = node.childrenNames(); for (String child : childrenNames) { if(child.equals("workspace") || child.equals("security")) continue; LOGGER.info("Migrating {} to {}",child,"workspace/"+child); Preferences old = node.node(child); cloneNode(old, node.node("workspace/"+child)); deleteNode(old); } isMigrated = true; } catch (BackingStoreException e) { LOGGER.error("Failed to check if old config needs to be migrated"); } } /** * copies all values and child nodes of the source into the target node * @param source * @param target * @throws BackingStoreException */ public static void cloneNode(Preferences source, Preferences target) throws BackingStoreException { shallowClonePreferences(source, target); copyChildPreferences(source, target); target.sync(); } public static Preferences workspaceScope() { return InstanceScope.INSTANCE.getNode(ApplicationConstants.CONFIG_NODE+"/workspace"); } /** * * @return the jabylon root preference node */ public static Preferences rootScope() { return InstanceScope.INSTANCE.getNode(ApplicationConstants.PLUGIN_ID); } public static void deleteNode(Preferences node) throws BackingStoreException { Preferences parent = null; try { parent = node.parent(); } catch (Exception e) { LOGGER.warn("Failed to retrieve parent node",e); } node.removeNode(); if(parent!=null) parent.flush(); } public static Preferences renamePreferenceNode(Preferences node, String newName) { Preferences parent = node.parent(); Preferences clone = parent.node(newName); try { copyChildPreferences(node, clone); deleteNode(node); parent.flush(); } catch (BackingStoreException e) { LOGGER.error("Failed to rename preferences from "+node+" to "+clone,e); } return clone; } protected static void shallowClonePreferences(Preferences node, Preferences clone) { try { for (String key : node.keys()) { String value = node.get(key, ""); clone.put(key, value); } } catch (BackingStoreException e) { LOGGER.error("Failed to clone preferences from "+node+" to "+clone,e); } } public static void copyChildPreferences(Preferences oldParent, Preferences newParent) throws BackingStoreException { for (String name : oldParent.childrenNames()) { Preferences child = oldParent.node(name); Preferences copy = newParent.node(name); shallowClonePreferences(child, copy); copyChildPreferences(child, copy); } } public static final ScanConfiguration getScanConfigForProject(Project project) { Preferences node = scopeFor(project); ScanConfiguration configuration = PropertiesFactory.eINSTANCE.createScanConfiguration(); configuration.setExclude(node.get(SCAN_CONFIG_EXCLUDE, PropertiesPackage.Literals.SCAN_CONFIGURATION__EXCLUDE.getDefaultValueLiteral())); configuration.setInclude(node.get(SCAN_CONFIG_INCLUDE, PropertiesPackage.Literals.SCAN_CONFIGURATION__INCLUDE.getDefaultValueLiteral())); configuration.setMasterLocale(node.get(SCAN_CONFIG_MASTER_LOCALE, PropertiesPackage.Literals.SCAN_CONFIGURATION__MASTER_LOCALE.getDefaultValueLiteral())); return configuration; } public static Preferences getNodeForJob(Preferences context, String jobID) { return context.node(ApplicationConstants.JOBS_NODE_NAME).node(jobID); } }