/******************************************************************************* * Copyright (c) 2009 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 * Zend Technologies *******************************************************************************/ package org.eclipse.php.internal.debug.core.preferences.stepFilters; import java.util.ArrayList; import java.util.HashMap; import java.util.StringTokenizer; import org.eclipse.core.runtime.*; import org.eclipse.dltk.core.DLTKCore; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.php.internal.core.util.FileUtils; import org.eclipse.php.internal.debug.core.IPHPDebugConstants; import org.eclipse.php.internal.debug.core.PHPDebugPlugin; import org.eclipse.php.internal.ui.PHPUiPlugin; /** * This Singleton class is used to bridge between the debugger and the Debug * Step filter Preferences. * * @author yaronm */ public class DebugStepFilterController implements IDebugStepFilterPrefListener { private static final int MAX_CACHE_SIZE = 5000; private static DebugStepFilterController instance = null; private DebugStepFilter[] enabledFilters = null; // filters that are enabled private DebugStepFilter[] extendedFilters = null; // filters that come from // extension point private HashMap<String, Boolean> filtersCheckCache = new HashMap<String, Boolean>(); private DebugStepFilterController() { } public static synchronized DebugStepFilterController getInstance() { if (instance == null) { instance = new DebugStepFilterController(); } return instance; } /** * Checks whether the given file path is filtered in the Debug Step Filters * list * * @param path * - a file path */ public boolean isFiltered(String path) { Boolean cachedFilterResult = filtersCheckCache.get(path); if (cachedFilterResult != null) { return cachedFilterResult; } if (enabledFilters == null) { enabledFilters = getAllEnabledFilters(); } boolean filterResult = false; for (DebugStepFilter currentFilter : enabledFilters) { String filterPath = currentFilter.getPath(); if (currentFilter.getType() == IStepFilterTypes.PATH_PATTERN) { if (filterPath.startsWith("*") && filterPath.endsWith("*")) {// *...* //$NON-NLS-1$ //$NON-NLS-2$ if (path.contains(filterPath.substring(1, filterPath.length() - 1))) { filterResult = true; break; } } else if (filterPath.startsWith("*")) {// *... //$NON-NLS-1$ if (path.endsWith(filterPath.substring(1))) { filterResult = true; break; } } else if (filterPath.endsWith("*")) {// ...* //$NON-NLS-1$ if (path.startsWith(filterPath.substring(0, filterPath.length() - 1))) { filterResult = true; break; } } // else, simply compare the exact path string else {// check if simple path pattern filterResult = FileUtils.checkIfEqualFilePaths(path, currentFilter.getPath()); break; } } else {// no '*' in filter // check if the given path is inside a filtered container // (folder, project etc..) if ((currentFilter.getType() == IStepFilterTypes.PHP_PROJECT) || (currentFilter.getType() == IStepFilterTypes.PHP_PROJECT_FOLDER) || (currentFilter.getType() == IStepFilterTypes.PHP_INCLUDE_PATH_LIBRARY_FOLDER) || (currentFilter.getType() == IStepFilterTypes.PHP_INCLUDE_PATH_LIBRARY)) { filterResult = FileUtils.checkIfContainerOfFile(currentFilter.getPath(), path); break; } // check if the given path is inside an include path variable // container else if ((currentFilter.getType() == IStepFilterTypes.PHP_INCLUDE_PATH_VAR) || currentFilter.getType() == IStepFilterTypes.PHP_INCLUDE_PATH_VAR_FOLDER) { IPath resolvedVariablePath = DLTKCore.getResolvedVariablePath(new Path(currentFilter.getPath())); if (resolvedVariablePath != null) { String includePathVarPath = resolvedVariablePath.toOSString(); filterResult = FileUtils.checkIfContainerOfFile(includePathVarPath, path); } break; } } } addToCache(path, filterResult); return filterResult; } private void addToCache(String path, boolean filterResult) { if (filtersCheckCache.size() > MAX_CACHE_SIZE) { filtersCheckCache.clear(); } filtersCheckCache.put(path, filterResult); } // Returns ONLY enabled filters private DebugStepFilter[] getAllEnabledFilters() { IPreferenceStore store = PHPUiPlugin.getDefault().getPreferenceStore(); String[] parsedFilters = parseList(store.getString(IPHPDebugConstants.PREF_STEP_FILTERS_LIST)); ArrayList<DebugStepFilter> list = new ArrayList<DebugStepFilter>(); for (int i = 0; i < parsedFilters.length; i++) { String[] tokens = parsedFilters[i].split("\\" //$NON-NLS-1$ + DebugStepFilter.FILTER_TOKENS_DELIM); if (tokens.length != 4) { return new DebugStepFilter[0]; } DebugStepFilter tempFilter = new DebugStepFilter(Integer.parseInt(tokens[0]), Boolean.parseBoolean(tokens[1]), Boolean.parseBoolean(tokens[2]), tokens[3]); if (tempFilter.isEnabled()) { list.add(tempFilter); } } DebugStepFilter[] extendedFiltersList = getExtendedFiltersList(); for (DebugStepFilter filterExtended : extendedFiltersList) { if (!list.contains(filterExtended)) { list.add(filterExtended); } } DebugStepFilter[] result = new DebugStepFilter[list.size()]; list.toArray(result); return result; } // Parses the comma separated string into an array of strings private String[] parseList(String listString) { ArrayList<String> list = new ArrayList<String>(); StringTokenizer tokenizer = new StringTokenizer(listString, DebugStepFilter.FILTERS_PREF_LIST_DELIM); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); list.add(token); } return (String[]) list.toArray(new String[list.size()]); } public void debugStepFilterModified(DebugStepFilterEvent event) { filtersCheckCache.clear(); ArrayList<DebugStepFilter> list = new ArrayList<DebugStepFilter>(); DebugStepFilter[] newFilters = event.getNewFilters(); for (DebugStepFilter newFilter : newFilters) { if (newFilter.isEnabled()) { list.add(newFilter); } } enabledFilters = new DebugStepFilter[list.size()]; list.toArray(enabledFilters); } private void readExtensionsList() { ArrayList<DebugStepFilter> listToAdd = new ArrayList<DebugStepFilter>(); String stepFilterExtensionName = "org.eclipse.php.debug.core.phpDebugStepFilters"; //$NON-NLS-1$ IConfigurationElement[] elements = Platform.getExtensionRegistry() .getConfigurationElementsFor(stepFilterExtensionName); for (IConfigurationElement element : elements) { if (element.getName().equals("stepFilter")) { //$NON-NLS-1$ Boolean isEnabled = null; String path = null; int filterType = 0; try { isEnabled = Boolean.parseBoolean(element.getAttribute("enabled")); //$NON-NLS-1$ path = element.getAttribute("path"); //$NON-NLS-1$ filterType = getFilterTypeId(element.getAttribute("type")); //$NON-NLS-1$ } catch (InvalidRegistryObjectException ire) { PHPDebugPlugin.log(ire); return; } listToAdd.add(new DebugStepFilter(filterType, isEnabled, true, path)); } } extendedFilters = new DebugStepFilter[listToAdd.size()]; listToAdd.toArray(extendedFilters); } // this is a bit complexed comparison method , but it only occurs for // extension points one-time private int getFilterTypeId(String attribute) { if (attribute.equals("PHP_PROJECT")) { //$NON-NLS-1$ return IStepFilterTypes.PHP_PROJECT; } if (attribute.equals("PHP_PROJECT_FILE")) { //$NON-NLS-1$ return IStepFilterTypes.PHP_PROJECT_FILE; } if (attribute.equals("PHP_PROJECT_FOLDER")) { //$NON-NLS-1$ return IStepFilterTypes.PHP_PROJECT_FOLDER; } if (attribute.equals("PATH_PATTERN")) { //$NON-NLS-1$ return IStepFilterTypes.PATH_PATTERN; } if (attribute.equals("PHP_INCLUDE_PATH_VAR")) { //$NON-NLS-1$ return IStepFilterTypes.PHP_INCLUDE_PATH_VAR; } if (attribute.equals("PHP_INCLUDE_PATH_VAR_FILE")) { //$NON-NLS-1$ return IStepFilterTypes.PHP_INCLUDE_PATH_VAR_FILE; } if (attribute.equals("PHP_INCLUDE_PATH_FOLDER")) { //$NON-NLS-1$ return IStepFilterTypes.PHP_INCLUDE_PATH_VAR_FOLDER; } if (attribute.equals("PHP_INCLUDE_PATH_LIBRARY")) { //$NON-NLS-1$ return IStepFilterTypes.PHP_INCLUDE_PATH_LIBRARY; } if (attribute.equals("PHP_INCLUDE_PATH_LIBRARY_FILE")) { //$NON-NLS-1$ return IStepFilterTypes.PHP_INCLUDE_PATH_LIBRARY_FILE; } if (attribute.equals("PHP_INCLUDE_PATH_LIBRARY_FOLDER")) { //$NON-NLS-1$ return IStepFilterTypes.PHP_INCLUDE_PATH_LIBRARY_FOLDER; } return 0; } public DebugStepFilter[] getExtendedFiltersList() { if (extendedFilters == null) { readExtensionsList(); } return extendedFilters; } }