--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.debug.ui/src/org/chromium/debug/ui/actions/V8ScriptAction.java Mon Jun 07 16:51:19 2010 -0700
@@ -0,0 +1,193 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.debug.ui.actions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.chromium.debug.core.model.DebugTargetImpl;
+import org.chromium.debug.core.model.VmResource;
+import org.chromium.debug.core.util.ChromiumDebugPluginUtil;
+import org.chromium.sdk.JavascriptVm;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.resources.mapping.ResourceMapping;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.ui.IActionDelegate2;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+
+/**
+ * A base class for all LiveEdit actions that are scoped to a working file from user workspace.
+ * It makes all necessary checks and prepares data in form of {@link FilePair} class.
+ * The concrete actions implement the {@link #execute(FilePair)} method.
+ */
+abstract class V8ScriptAction implements IObjectActionDelegate, IActionDelegate2 {
+ private Runnable currentRunnable = null;
+
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ }
+
+ public void run(IAction action) {
+ if (currentRunnable == null) {
+ return;
+ }
+ currentRunnable.run();
+ currentRunnable = null;
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ currentRunnable = createRunnable(selection);
+ action.setEnabled(currentRunnable != null);
+ }
+
+ private Runnable createRunnable(ISelection selection) {
+ if (selection instanceof IStructuredSelection == false) {
+ return null;
+ }
+ IStructuredSelection structured = (IStructuredSelection) selection;
+ if (structured.size() != 1) {
+ return null;
+ }
+
+ Object firstElement = structured.getFirstElement();
+ if (firstElement instanceof ResourceMapping == false) {
+ return null;
+ }
+ ResourceMapping resourceMapping = (ResourceMapping) firstElement;
+ final List<IResource> resourceList = new ArrayList<IResource>(1);
+ IResourceVisitor visitor = new IResourceVisitor() {
+ public boolean visit(IResource resource) throws CoreException {
+ resourceList.add(resource);
+ return false;
+ }
+ };
+ try {
+ resourceMapping.accept(null, visitor, null);
+ } catch (CoreException e) {
+ throw new RuntimeException(e);
+ }
+ if (resourceList.size() != 1) {
+ return null;
+ }
+ if (resourceList.get(0) instanceof IFile == false) {
+ return null;
+ }
+ final IFile file = (IFile) resourceList.get(0);
+ if (!filterFileName(file.getName())) {
+ return null;
+ }
+ return new Runnable() {
+ public void run() {
+ try {
+ execute(file);
+ } catch (RuntimeException e) {
+ // TODO(peter.rybin): Handle it.
+ throw e;
+ }
+ }
+ };
+ }
+
+ private void execute(IFile file) {
+ List<? extends FilePair> filePairList = getFilePairs(file);
+ FilePair filePair = getSingleFilePair(filePairList);
+ execute(filePair);
+ }
+
+ protected abstract void execute(FilePair filePair);
+
+ /**
+ * A temporary method that excludes all cases when there are more than one file pair for a
+ * user file. The proper solution ought to provide a UI for user so that he could review
+ * which debug sessions should be included in action.
+ */
+ private static FilePair getSingleFilePair(List<? extends FilePair> pairs) {
+ if (pairs.size() == 0) {
+ throw new RuntimeException("File is not associated with any V8 VM");
+ }
+ if (pairs.size() != 1) {
+ throw new RuntimeException(
+ "File is associated with several V8 VMs, this is not supported yet.");
+ }
+ return pairs.get(0);
+ }
+
+ /**
+ * Finds all file pairs for a user working file. One working file may correspond to several
+ * scripts if there are more than one debug sessions.
+ */
+ private static List<? extends FilePair> getFilePairs(IFile localFile) {
+ List<DebugTargetImpl> targetList = DebugTargetImpl.getAllDebugTargetImpls();
+ ArrayList<FilePair> result = new ArrayList<FilePair>(targetList.size());
+
+ for (DebugTargetImpl target : targetList) {
+ VmResource script;
+ try {
+ script = target.getVmResource(localFile);
+ } catch (CoreException e) {
+ throw new RuntimeException("Failed to resolve script from the file " + localFile, e);
+ }
+ if (script == null) {
+ continue;
+ }
+ result.add(new FilePair(localFile, script, target));
+ }
+ return result;
+ }
+
+ protected static class FilePair {
+ private final IFile file;
+ private final VmResource vmResource;
+ private final DebugTargetImpl debugTargetImpl;
+
+ FilePair(IFile file, VmResource vmResource, DebugTargetImpl debugTargetImpl) {
+ this.file = file;
+ this.vmResource = vmResource;
+ this.debugTargetImpl = debugTargetImpl;
+ }
+ protected IFile getFile() {
+ return file;
+ }
+ protected VmResource getVmResource() {
+ return vmResource;
+ }
+ protected JavascriptVm getJavascriptVm() {
+ return debugTargetImpl.getJavascriptEmbedder().getJavascriptVm();
+ }
+ protected DebugTargetImpl getDebugTarget() {
+ return debugTargetImpl;
+ }
+ }
+
+ /**
+ * @return true if action should be enabled for this file name
+ */
+ private boolean filterFileName(String name) {
+ for (String suffix : ChromiumDebugPluginUtil.SUPPORTED_EXTENSIONS_SUFFIX_LIST) {
+ if (name.endsWith(suffix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void dispose() {
+ currentRunnable = null;
+ }
+
+ public void init(IAction action) {
+ }
+
+ public void runWithEvent(IAction action, Event event) {
+ run(action);
+ }
+}
+