org.chromium.debug.ui/src/org/chromium/debug/ui/actions/V8ScriptAction.java
changeset 355 8726e95bcbba
equal deleted inserted replaced
354:0bceeb415e7f 355:8726e95bcbba
       
     1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
       
     2 // Use of this source code is governed by a BSD-style license that can be
       
     3 // found in the LICENSE file.
       
     4 
       
     5 package org.chromium.debug.ui.actions;
       
     6 
       
     7 import java.util.ArrayList;
       
     8 import java.util.List;
       
     9 
       
    10 import org.chromium.debug.core.model.DebugTargetImpl;
       
    11 import org.chromium.debug.core.model.VmResource;
       
    12 import org.chromium.debug.core.util.ChromiumDebugPluginUtil;
       
    13 import org.chromium.sdk.JavascriptVm;
       
    14 import org.eclipse.core.resources.IFile;
       
    15 import org.eclipse.core.resources.IResource;
       
    16 import org.eclipse.core.resources.IResourceVisitor;
       
    17 import org.eclipse.core.resources.mapping.ResourceMapping;
       
    18 import org.eclipse.core.runtime.CoreException;
       
    19 import org.eclipse.jface.action.IAction;
       
    20 import org.eclipse.jface.viewers.ISelection;
       
    21 import org.eclipse.jface.viewers.IStructuredSelection;
       
    22 import org.eclipse.swt.widgets.Event;
       
    23 import org.eclipse.ui.IActionDelegate2;
       
    24 import org.eclipse.ui.IObjectActionDelegate;
       
    25 import org.eclipse.ui.IWorkbenchPart;
       
    26 
       
    27 /**
       
    28  * A base class for all LiveEdit actions that are scoped to a working file from user workspace.
       
    29  * It makes all necessary checks and prepares data in form of {@link FilePair} class.
       
    30  * The concrete actions implement the {@link #execute(FilePair)} method.
       
    31  */
       
    32 abstract class V8ScriptAction implements IObjectActionDelegate, IActionDelegate2 {
       
    33   private Runnable currentRunnable = null;
       
    34 
       
    35   public void setActivePart(IAction action, IWorkbenchPart targetPart) {
       
    36   }
       
    37 
       
    38   public void run(IAction action) {
       
    39     if (currentRunnable == null) {
       
    40       return;
       
    41     }
       
    42     currentRunnable.run();
       
    43     currentRunnable = null;
       
    44   }
       
    45 
       
    46   public void selectionChanged(IAction action, ISelection selection) {
       
    47     currentRunnable = createRunnable(selection);
       
    48     action.setEnabled(currentRunnable != null);
       
    49   }
       
    50 
       
    51   private Runnable createRunnable(ISelection selection) {
       
    52     if (selection instanceof IStructuredSelection == false) {
       
    53       return null;
       
    54     }
       
    55     IStructuredSelection structured = (IStructuredSelection) selection;
       
    56     if (structured.size() != 1) {
       
    57       return null;
       
    58     }
       
    59 
       
    60     Object firstElement = structured.getFirstElement();
       
    61     if (firstElement instanceof ResourceMapping == false) {
       
    62       return null;
       
    63     }
       
    64     ResourceMapping resourceMapping = (ResourceMapping) firstElement;
       
    65     final List<IResource> resourceList = new ArrayList<IResource>(1);
       
    66     IResourceVisitor visitor = new IResourceVisitor() {
       
    67       public boolean visit(IResource resource) throws CoreException {
       
    68         resourceList.add(resource);
       
    69         return false;
       
    70       }
       
    71     };
       
    72     try {
       
    73       resourceMapping.accept(null, visitor, null);
       
    74     } catch (CoreException e) {
       
    75       throw new RuntimeException(e);
       
    76     }
       
    77     if (resourceList.size() != 1) {
       
    78       return null;
       
    79     }
       
    80     if (resourceList.get(0) instanceof IFile == false) {
       
    81       return null;
       
    82     }
       
    83     final IFile file = (IFile) resourceList.get(0);
       
    84     if (!filterFileName(file.getName())) {
       
    85       return null;
       
    86     }
       
    87     return new Runnable() {
       
    88       public void run() {
       
    89         try {
       
    90           execute(file);
       
    91         } catch (RuntimeException e) {
       
    92           // TODO(peter.rybin): Handle it.
       
    93           throw e;
       
    94         }
       
    95       }
       
    96     };
       
    97   }
       
    98 
       
    99   private void execute(IFile file) {
       
   100     List<? extends FilePair> filePairList = getFilePairs(file);
       
   101     FilePair filePair = getSingleFilePair(filePairList);
       
   102     execute(filePair);
       
   103   }
       
   104 
       
   105   protected abstract void execute(FilePair filePair);
       
   106 
       
   107   /**
       
   108    * A temporary method that excludes all cases when there are more than one file pair for a
       
   109    * user file. The proper solution ought to provide a UI for user so that he could review
       
   110    * which debug sessions should be included in action.
       
   111    */
       
   112   private static FilePair getSingleFilePair(List<? extends FilePair> pairs) {
       
   113     if (pairs.size() == 0) {
       
   114       throw new RuntimeException("File is not associated with any V8 VM");
       
   115     }
       
   116     if (pairs.size() != 1) {
       
   117       throw new RuntimeException(
       
   118           "File is associated with several V8 VMs, this is not supported yet.");
       
   119     }
       
   120     return pairs.get(0);
       
   121   }
       
   122 
       
   123   /**
       
   124    * Finds all file pairs for a user working file. One working file may correspond to several
       
   125    * scripts if there are more than one debug sessions.
       
   126    */
       
   127   private static List<? extends FilePair> getFilePairs(IFile localFile) {
       
   128     List<DebugTargetImpl> targetList = DebugTargetImpl.getAllDebugTargetImpls();
       
   129     ArrayList<FilePair> result = new ArrayList<FilePair>(targetList.size());
       
   130 
       
   131     for (DebugTargetImpl target : targetList) {
       
   132       VmResource script;
       
   133       try {
       
   134         script = target.getVmResource(localFile);
       
   135       } catch (CoreException e) {
       
   136         throw new RuntimeException("Failed to resolve script from the file " + localFile, e);
       
   137       }
       
   138       if (script == null) {
       
   139         continue;
       
   140       }
       
   141       result.add(new FilePair(localFile, script, target));
       
   142     }
       
   143     return result;
       
   144   }
       
   145 
       
   146   protected static class FilePair {
       
   147     private final IFile file;
       
   148     private final VmResource vmResource;
       
   149     private final DebugTargetImpl debugTargetImpl;
       
   150 
       
   151     FilePair(IFile file, VmResource vmResource, DebugTargetImpl debugTargetImpl) {
       
   152       this.file = file;
       
   153       this.vmResource = vmResource;
       
   154       this.debugTargetImpl = debugTargetImpl;
       
   155     }
       
   156     protected IFile getFile() {
       
   157       return file;
       
   158     }
       
   159     protected VmResource getVmResource() {
       
   160       return vmResource;
       
   161     }
       
   162     protected JavascriptVm getJavascriptVm() {
       
   163       return debugTargetImpl.getJavascriptEmbedder().getJavascriptVm();
       
   164     }
       
   165     protected DebugTargetImpl getDebugTarget() {
       
   166       return debugTargetImpl;
       
   167     }
       
   168   }
       
   169 
       
   170   /**
       
   171    * @return true if action should be enabled for this file name
       
   172    */
       
   173   private boolean filterFileName(String name) {
       
   174     for (String suffix : ChromiumDebugPluginUtil.SUPPORTED_EXTENSIONS_SUFFIX_LIST) {
       
   175       if (name.endsWith(suffix)) {
       
   176         return true;
       
   177       }
       
   178     }
       
   179     return false;
       
   180   }
       
   181 
       
   182   public void dispose() {
       
   183     currentRunnable = null;
       
   184   }
       
   185 
       
   186   public void init(IAction action) {
       
   187   }
       
   188 
       
   189   public void runWithEvent(IAction action, Event event) {
       
   190     run(action);
       
   191   }
       
   192 }
       
   193