/******************************************************************************* * Copyright (c) 2009 xored software, Inc. * * 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: * xored software, Inc. - initial API and Implementation (Alex Panchenko) *******************************************************************************/ package org.eclipse.dltk.tcl.activestatedebugger; import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.dltk.core.IExternalSourceModule; import org.eclipse.dltk.core.IProjectFragment; import org.eclipse.dltk.core.IScriptFolder; import org.eclipse.dltk.core.IScriptProject; import org.eclipse.dltk.core.ISourceModule; import org.eclipse.dltk.core.environment.EnvironmentPathUtils; import org.eclipse.dltk.core.environment.IEnvironment; import org.eclipse.dltk.core.environment.IFileHandle; public class InstrumentationSetup { protected static class Entry { final IPath path; final IFileHandle fileHandle; boolean include; boolean exclude; Boolean leaf; public final Map<IPath, Entry> children = new HashMap<IPath, Entry>(); public boolean directory; public Entry(IPath path, IFileHandle fileHandle) { this.path = path; this.fileHandle = fileHandle; } public IPath getPath() { return path; } @Override public String toString() { return path.toString() + (include ? "[include]" : "") //$NON-NLS-1$ //$NON-NLS-2$ + (exclude ? "[exclude]" : ""); //$NON-NLS-1$ //$NON-NLS-2$ } } final IEnvironment environment; protected final Map<IPath, Entry> entries = new HashMap<IPath, Entry>(); protected final Entry root = new Entry(Path.ROOT, null); public InstrumentationSetup(IEnvironment environment) { this.environment = environment; } /** * @param pattern * @return */ public void addWorkspace(IPath path, boolean isDirectory, boolean include) { final IResource resource = InstrumentationUtils.getWorkspaceRoot() .findMember(path); if (resource != null) { final URI uri = resource.getLocationURI(); final IFileHandle file = environment.getFile(uri); addFileHandle(file, isDirectory, include); } } /** * @param environment * @param pattern * @return */ public void addExternal(IPath path, boolean isDirectory, boolean include) { addFileHandle(environment.getFile(EnvironmentPathUtils .getLocalPath(path)), isDirectory, include); } protected void addFileHandle(IFileHandle file, boolean isDirectory, boolean include) { if (file != null) { IPath path = file.getPath(); Entry entry = entries.get(path); if (entry != null) { entry.leaf = Boolean.valueOf(include); if (include) { entry.include = true; } else { entry.exclude = true; } return; } entry = new Entry(path, file); entry.leaf = Boolean.valueOf(include); entries.put(path, entry); entry.directory = isDirectory; if (include) { entry.include = true; } else { entry.exclude = true; } for (;;) { file = file.getParent(); if (file == null) { root.children.put(entry.getPath(), entry); break; } path = file.getPath(); Entry dirEntry = entries.get(path); if (dirEntry == null) { dirEntry = new Entry(path, file); entries.put(path, dirEntry); } dirEntry.children.put(entry.getPath(), entry); dirEntry.directory = true; if (include) { dirEntry.include = true; } else { dirEntry.exclude = true; } entry = dirEntry; } } } public static class PatternEntry { private final IPath path; private final boolean directory; private final boolean include; public PatternEntry(IPath path, boolean directory, boolean include) { this.path = path; this.directory = directory; this.include = include; } public boolean isInclude() { return include; } public String getPatternText() { return directory ? path.toString() + "/*" : path.toString(); //$NON-NLS-1$ } @Override public String toString() { return (include ? "+" : "-") + getPatternText(); //$NON-NLS-1$ //$NON-NLS-2$ } } private static void walk(Entry entry, List<PatternEntry> patterns) { if (entry.fileHandle == null || entry.leaf == null) { for (Entry e : entry.children.values()) { walk(e, patterns); } } else if (entry.include && entry.exclude) { final IFileHandle[] children = entry.fileHandle.getChildren(); if (children != null) { for (IFileHandle child : children) { final IPath path = child.getPath(); final Entry childEntry = entry.children.get(path); if (childEntry == null) { patterns .add(new PatternEntry(path, child.isDirectory(), entry.leaf .booleanValue())); } else { walk(childEntry, patterns); } } } } else if (entry.exclude) { patterns.add(new PatternEntry(entry.getPath(), entry.directory, false)); } else if (entry.include) { patterns.add(new PatternEntry(entry.getPath(), entry.directory, true)); } } public IPath[] getExcludes() { final List<PatternEntry> patterns = new ArrayList<PatternEntry>(); walk(root, patterns); Collections.sort(patterns, createPatternEntryComparator()); final List<IPath> result = new ArrayList<IPath>(); for (PatternEntry entry : patterns) { if (!entry.include) { result.add(entry.path); } } return result.toArray(new IPath[result.size()]); } public IPath[] getIncludes() { final List<PatternEntry> patterns = new ArrayList<PatternEntry>(); walk(root, patterns); Collections.sort(patterns, createPatternEntryComparator()); final List<IPath> result = new ArrayList<IPath>(); for (PatternEntry entry : patterns) { if (entry.include) { result.add(entry.path); } } return result.toArray(new IPath[result.size()]); } private static Comparator<PatternEntry> createPatternEntryComparator() { return new Comparator<PatternEntry>() { public int compare(PatternEntry o1, PatternEntry o2) { return o1.path.toString().compareTo(o2.path.toString()); } }; } /** * @since 2.0 */ public List<PatternEntry> getPatterns() { final List<PatternEntry> patterns = new ArrayList<PatternEntry>(); walk(root, patterns); Collections.sort(patterns, createPatternEntryComparator()); return patterns; } /** * @param module */ public void addSourceModule(ISourceModule module, boolean include) { if (module instanceof IExternalSourceModule) { if (!module.isBuiltin()) return; addExternal(module.getPath(), false, include); } else { addWorkspace(module.getPath(), false, include); } } /** * @param folder * @param include */ public void addScriptFolder(IScriptFolder folder, boolean include) { if (folder.isReadOnly()) { addExternal(folder.getPath(), true, include); } else { addWorkspace(folder.getPath(), true, include); } } /** * @param fragment * @param include */ public void addProjectFragment(IProjectFragment fragment, boolean include) { if (fragment.isExternal()) { if (fragment.isBuiltin()) return; addExternal(fragment.getPath(), true, include); } else { addWorkspace(fragment.getPath(), true, include); } } /** * @param project * @param include */ public void addProject(IScriptProject project, boolean include) { addWorkspace(project.getPath(), true, include); } }