/******************************************************************************* * Copyright (c) 2015 Zend Technologies 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: * Zend Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.php.internal.debug.core.debugger; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.php.internal.core.IUniqueIdentityElement; import org.eclipse.php.internal.core.util.preferences.IXMLPreferencesStorable; import org.eclipse.php.internal.core.util.preferences.XMLPreferencesReader; import org.eclipse.php.internal.core.util.preferences.XMLPreferencesWriter; import org.eclipse.php.internal.debug.core.PHPDebugPlugin; import org.eclipse.php.internal.debug.core.preferences.PHPexeItem; import org.eclipse.php.internal.debug.core.preferences.PHPexes; import org.eclipse.php.internal.server.core.Server; import org.eclipse.php.internal.server.core.manager.ServersManager; /** * Abstract implementation for debugger settings provider. It contains default * support for loading, creating and saving debugger settings. * <p> * Client may extend this class (highly recommended) * </p> * * @author Bartlomiej Laczkowski */ @SuppressWarnings("restriction") public abstract class AbstractDebuggerSettingsProvider implements IDebuggerSettingsProvider { /** * Helper class for saving settings to persistent store. */ private final class PersistentSettings implements IXMLPreferencesStorable { private final static String TAG_OWNER = "ownerId"; //$NON-NLS-1$ private final static String TAG_SETTINGS = "settings"; //$NON-NLS-1$ private IDebuggerSettings settings; private PersistentSettings(IDebuggerSettings settings) { this.settings = settings; } @Override public Map<String, Object> storeToMap() { Map<String, Object> settingsMap = new HashMap<String, Object>(); Map<String, String> attributes = new HashMap<String, String>(); attributes.put(TAG_OWNER, settings.getOwnerId()); for (String key : settings.getAttributes().keySet()) { attributes.put(key, settings.getAttribute(key)); } settingsMap.put(TAG_SETTINGS, attributes); return (Map<String, Object>) settingsMap; } @Override public void restoreFromMap(Map<String, Object> map) { // Never used } } private final Map<String, IDebuggerSettings> settingsCache = new HashMap<String, IDebuggerSettings>(); private final Map<String, IDebuggerSettings> defaultsCache = new HashMap<String, IDebuggerSettings>(); private boolean cleanup = false; private String id; /* * (non-Javadoc) * * @see * org.eclipse.php.internal.debug.core.debugger.IDebuggerSettingsProvider * #getId() */ @Override public String getId() { return id; } /* * (non-Javadoc) * * @see * org.eclipse.php.internal.debug.core.debugger.IDebuggerSettingsProvider * #get(org.eclipse.php.internal.core.IUniqueIdentityElement) */ @Override public IDebuggerSettings get(String ownerId) { IDebuggerSettings settings = settingsCache.get(ownerId); if (settings == null) { settings = defaultsCache.get(ownerId); if (settings == null) { settings = createSettings(getKind(ownerId), ownerId); defaultsCache.put(ownerId, settings); } } return settings; } /* * (non-Javadoc) * * @see * org.eclipse.php.internal.debug.core.debugger.IDebuggerSettingsProvider * #getAll() */ @Override public List<IDebuggerSettings> getAll() { return new ArrayList<IDebuggerSettings>(settingsCache.values()); } /* * (non-Javadoc) * * @see * org.eclipse.php.internal.debug.core.debugger.IDebuggerSettingsProvider * #save(org.eclipse.php.internal.debug.core.debugger.IDebuggerSettings) */ @Override public void save(IDebuggerSettings settings) { settingsCache.put(settings.getOwnerId(), settings); save(); } /* * (non-Javadoc) * * @see * org.eclipse.php.internal.debug.core.debugger.IDebuggerSettingsProvider * #delete(org.eclipse.php.internal.debug.core.debugger.IDebuggerSettings) */ @Override public void delete(IDebuggerSettings settings) { settingsCache.remove(settings.getOwnerId()); save(); } /** * Implementors should create and return the appropriate settings taking * into account the provided settings kind and debugger owner unique ID. * * @param kind * @param ownerId * @return new settings */ protected abstract IDebuggerSettings createSettings(DebuggerSettingsKind kind, String ownerId); /** * Implementors should create and return the appropriate settings taking * into account the provided setting kind, debugger settings owner and * attributes map loaded from persistent storage. * * @param kind * @param ownerId * @param attributes * @return recreated settings */ protected abstract IDebuggerSettings createSettings(DebuggerSettingsKind kind, String ownerId, Map<String, String> attributes); /** * Restore settings with the use of data from persistent storage. */ private IDebuggerSettings restoreSettings(String ownerId, Map<String, String> attributes) { return createSettings(getKind(ownerId), ownerId, attributes); } /** * Obtains and returns kind of debugger settings owner. */ private DebuggerSettingsKind getKind(String ownerId) { IUniqueIdentityElement owner = ServersManager.findServer(ownerId); if (owner != null) return DebuggerSettingsKind.PHP_SERVER; owner = PHPexes.getInstance().findItem(ownerId); if (owner != null) return DebuggerSettingsKind.PHP_EXE; // Owner is being created if (owner == null) { if (ownerId.startsWith(Server.ID_PREFIX)) return DebuggerSettingsKind.PHP_SERVER; if (ownerId.startsWith(PHPexeItem.ID_PREFIX)) return DebuggerSettingsKind.PHP_EXE; } // Should not happen return DebuggerSettingsKind.UNKNOWN; } /** * Creates and hooks settings during provider startup if those don't exist * yet for persistent PHP servers and executable configurations. */ private void hookSettings() { // Hook existing PHP executables for (PHPexeItem owner : PHPexes.getInstance().getAllItems()) { IDebuggerSettings settings = createSettings(DebuggerSettingsKind.PHP_EXE, owner.getUniqueId()); save(settings); } // Hook existing PHP servers for (Server owner : ServersManager.getServers()) { IDebuggerSettings settings = createSettings(DebuggerSettingsKind.PHP_SERVER, owner.getUniqueId()); save(settings); } } /** * Checks if given owner exists. * * @param ownerId * @return <code>true</code> if given owner exists, <code>false</code> * otherwise */ private boolean exists(String ownerId) { // Check if owner with given ID exists if (PHPexes.getInstance().findItem(ownerId) == null && ServersManager.findServer(ownerId) == null) return false; return true; } /** * Sets this provider ID. Should only be used by * {@link DebuggerSettingsProviderRegistry} class. * * @param id */ void setId(String id) { this.id = id; } /** * Rewrite settings if there is a need. */ void cleanup() { if (cleanup) save(); } /** * Saves settings to XML preferences. */ void save() { List<IXMLPreferencesStorable> persistentSettings = new ArrayList<IXMLPreferencesStorable>(); for (IDebuggerSettings settings : settingsCache.values()) { persistentSettings.add(new PersistentSettings(settings)); } XMLPreferencesWriter.write(InstanceScope.INSTANCE.getNode(PHPDebugPlugin.ID), getId(), persistentSettings); } /** * Loads settings from XML preferences. */ @SuppressWarnings("unchecked") void load() { List<Map<String, Object>> settingsList = XMLPreferencesReader .read(InstanceScope.INSTANCE.getNode(PHPDebugPlugin.ID), getId(), false); // Hook default settings to owners if preference does not exist if (settingsList.isEmpty()) hookSettings(); for (Map<String, Object> settings : settingsList) { settings = (Map<String, Object>) settings.get(PersistentSettings.TAG_SETTINGS); Map<String, String> attributes = new HashMap<String, String>(); String ownerId = null; for (String key : settings.keySet()) { if (key.equals(PersistentSettings.TAG_OWNER)) { ownerId = (String) settings.get(key); } else { String value = (String) settings.get(key); attributes.put(key, value); } } /* * Do not restore settings if somehow the related owner doesn't * exist anymore. Set cleanup flag to remove trashes on shutdown. */ if (!exists(ownerId)) { cleanup = true; continue; } IDebuggerSettings restoredSettings = restoreSettings(ownerId, attributes); if (restoredSettings != null) settingsCache.put(ownerId, restoredSettings); } } }