IDEA-99541 New run configuration type to run Ant
authorVassiliy <vassiliy.kudryashov@jetbrains.com>
Thu, 15 May 2014 11:54:19 +0000 (15:54 +0400)
committerVassiliy <vassiliy.kudryashov@jetbrains.com>
Thu, 15 May 2014 11:55:10 +0000 (15:55 +0400)
platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java
plugins/ant/src/META-INF/plugin.xml
plugins/ant/src/com/intellij/lang/ant/config/execution/AntRunConfiguration.java [new file with mode: 0644]
plugins/ant/src/com/intellij/lang/ant/config/execution/AntRunConfigurationType.java [new file with mode: 0644]
plugins/ant/src/com/intellij/lang/ant/config/execution/AntRunProfileState.java [new file with mode: 0644]
plugins/ant/src/com/intellij/lang/ant/config/execution/AntRunner.java [new file with mode: 0644]
plugins/ant/src/com/intellij/lang/ant/config/execution/ExecutionHandler.java
plugins/ant/src/com/intellij/lang/ant/config/explorer/AntExplorer.java
plugins/ant/src/com/intellij/lang/ant/config/impl/AntBeforeRunTaskProvider.java
plugins/ant/src/com/intellij/lang/ant/config/impl/GlobalAntConfiguration.java
resources-en/src/messages/AntBundle.properties

index 60ab050fe9be4995ab67a7d8d1742cfdfe49847d..99766cab33e0a52012739e45d341d36d46afdbb2 100644 (file)
@@ -224,7 +224,9 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
             ExecutionManager.getInstance(project).getContentManager().showRunContent(executor, descriptor, reuseContent);
             final ProcessHandler processHandler = descriptor.getProcessHandler();
             if (processHandler != null) {
-              processHandler.startNotify();
+              if (!processHandler.isStartNotified()) {
+                processHandler.startNotify();
+              }
               project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processStarted(executor.getId(), env, processHandler);
               started = true;
               processHandler.addProcessListener(new ProcessExecutionListener(project, profile, processHandler));
index 6917238d231d312d1a21498d87939f4843309b8a..4e9bd959c1a8e634aa6a45ccc85d2a1fae622c8a 100644 (file)
@@ -2,7 +2,7 @@
   <name>Ant Support</name>
   <id>AntSupport</id>
   <version>1.0</version>
-  <idea-version min="6.0"/>
+  <idea-version since-build="6.0"/>
   <description>Editing, maintaining and running ANT build scripts inside IntelliJ IDEA.</description>
   <vendor>JetBrains</vendor>
 
@@ -70,6 +70,9 @@
 
     <toolWindow anchor="right" icon="AllIcons.Toolwindows.ToolWindowAnt" id="Ant Build"
                 factoryClass="com.intellij.lang.ant.config.impl.AntToolWindowFactory"/>
+    <configurationType implementation="com.intellij.lang.ant.config.execution.AntRunConfigurationType"/>
+    <programRunner implementation="com.intellij.lang.ant.config.execution.AntRunner"/>
+
   </extensions>
 
   <application-components>
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/AntRunConfiguration.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/AntRunConfiguration.java
new file mode 100644 (file)
index 0000000..5f0d38a
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.ant.config.execution;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.*;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.lang.ant.config.AntBuildTarget;
+import com.intellij.lang.ant.config.AntConfiguration;
+import com.intellij.lang.ant.config.impl.GlobalAntConfiguration;
+import com.intellij.lang.ant.config.impl.TargetChooserDialog;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.SettingsEditor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.JDOMExternalizable;
+import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class AntRunConfiguration extends LocatableConfigurationBase implements RunProfileWithCompileBeforeLaunchOption{
+  private AntSettings mySettings = new AntSettings();
+
+  public AntRunConfiguration(Project project,
+                             ConfigurationFactory factory,
+                             String name) {
+    super(project, factory, name);
+  }
+
+  @Override
+  public RunConfiguration clone() {
+    AntRunConfiguration configuration = (AntRunConfiguration)super.clone();
+    configuration.mySettings = mySettings.clone();
+    return configuration;
+  }
+
+  @NotNull
+  @Override
+  public Module[] getModules() {
+    return new Module[0];
+  }
+
+  @NotNull
+  @Override
+  public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
+    return new SettingsEditor<RunConfiguration>() {
+      private String myFileUrl = null;
+      private String myTargetName = null;
+      private final JTextField myTextField = new JTextField();
+      private ActionListener myActionListener = new ActionListener() {
+        @Override
+        public void actionPerformed(ActionEvent e) {
+          AntBuildTarget buildTarget = getTarget();
+          final TargetChooserDialog dlg = new TargetChooserDialog(getProject(), buildTarget);
+          dlg.show();
+          if (dlg.isOK()) {
+            myFileUrl = null;
+            myTargetName = null;
+            buildTarget = dlg.getSelectedTarget();
+            if (buildTarget != null) {
+              final VirtualFile vFile = buildTarget.getModel().getBuildFile().getVirtualFile();
+              if (vFile != null) {
+                myFileUrl = vFile.getUrl();
+                myTargetName = buildTarget.getName();
+              }
+            }
+            updateTextField();
+          }
+        }
+      };
+
+      private void updateTextField() {
+        myTextField.setText("");
+        if (myFileUrl != null && myTargetName != null) {
+          myTextField.setText(myTargetName);
+        }
+        fireEditorStateChanged();
+      }
+
+      @Override
+      protected void resetEditorFrom(RunConfiguration s) {
+        AntRunConfiguration configuration = (AntRunConfiguration)s;
+        myFileUrl = configuration.mySettings.myFileUrl;
+        myTargetName = configuration.mySettings.myTargetName;
+        updateTextField();
+      }
+
+      @Override
+      protected void applyEditorTo(RunConfiguration s) throws ConfigurationException {
+        AntRunConfiguration configuration = (AntRunConfiguration)s;
+        configuration.mySettings.myFileUrl = myFileUrl;
+        configuration.mySettings.myTargetName = myTargetName;
+      }
+
+      @NotNull
+      @Override
+      protected JComponent createEditor() {
+        myTextField.setEditable(false);
+        return new TextFieldWithBrowseButton(myTextField, myActionListener);
+      }
+    };
+  }
+
+  @Override
+  public void checkConfiguration() throws RuntimeConfigurationException {
+    if (!AntConfiguration.getInstance(getProject()).isInitialized()) {
+      throw new RuntimeConfigurationException("Ant Configuration still haven't been initialized");
+    }
+    if (getTarget() == null)
+      throw new RuntimeConfigurationException("Target is not specified", "Missing parameters");
+  }
+
+  @Override
+  public String suggestedName() {
+    AntBuildTarget target = getTarget();
+    return target != null ? target.getDisplayName() : "";
+  }
+
+
+  @Nullable
+  @Override
+  public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
+    return new AntRunProfileState(env);
+  }
+
+  @Override
+  public void readExternal(Element element) throws InvalidDataException {
+    super.readExternal(element);
+    mySettings.readExternal(element);
+  }
+
+  @Override
+  public void writeExternal(Element element) throws WriteExternalException {
+    super.writeExternal(element);
+    mySettings.writeExternal(element);
+  }
+
+  public AntBuildTarget getTarget() {
+    return GlobalAntConfiguration.getInstance().findTarget(getProject(), mySettings.myFileUrl, mySettings.myTargetName);
+  }
+
+  public boolean acceptSettings(AntBuildTarget target) {
+    VirtualFile virtualFile = target.getModel().getBuildFile().getVirtualFile();
+    if (virtualFile == null) return false;
+    mySettings.myFileUrl = virtualFile.getUrl();
+    mySettings.myTargetName = target.getName();
+    return true;
+  }
+
+  public static class AntSettings implements Cloneable, JDOMExternalizable {
+    private static final String SETTINGS = "antsettings";
+    private static final String FILE = "antfile";
+    private static final String TARGET = "target";
+    private String myFileUrl = null;
+    private String myTargetName = null;
+
+    public AntSettings() {
+    }
+
+    public AntSettings(String fileUrl, String targetName) {
+      myFileUrl = fileUrl;
+      myTargetName = targetName;
+    }
+
+    @Override
+    public String toString() {
+      return myTargetName + "@" + myFileUrl;
+    }
+
+    @Override
+    protected AntSettings clone() {
+      return new AntSettings(myFileUrl, myTargetName);
+    }
+
+    @Override
+    public void readExternal(Element element) throws InvalidDataException {
+      element = element.getChild(SETTINGS);
+      if (element != null) {
+        myFileUrl = element.getAttributeValue(FILE);
+        myTargetName = element.getAttributeValue(TARGET);
+      }
+    }
+
+    @Override
+    public void writeExternal(Element element) throws WriteExternalException {
+      if (myFileUrl != null && myTargetName != null) {
+        Element child = new Element(SETTINGS);
+        child.setAttribute(FILE, myFileUrl);
+        child.setAttribute(TARGET, myTargetName);
+        element.addContent(child);
+      }
+    }
+  }
+}
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/AntRunConfigurationType.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/AntRunConfigurationType.java
new file mode 100644 (file)
index 0000000..d5dde7d
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.ant.config.execution;
+
+import com.intellij.execution.configurations.ConfigurationFactory;
+import com.intellij.execution.configurations.ConfigurationType;
+import com.intellij.execution.configurations.ConfigurationTypeUtil;
+import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.openapi.project.Project;
+import icons.AntIcons;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+public class AntRunConfigurationType implements ConfigurationType {
+  private final ConfigurationFactory myFactory = new ConfigurationFactory(this) {
+    @Override
+    public RunConfiguration createTemplateConfiguration(Project project) {
+      return new AntRunConfiguration(project, this, "");
+    }
+  };
+
+  public static AntRunConfigurationType getInstance() {
+    return ConfigurationTypeUtil.findConfigurationType(AntRunConfigurationType.class);
+  }
+
+
+  @Override
+  public String getDisplayName() {
+    return "Ant Target";
+  }
+
+  @Override
+  public String getConfigurationTypeDescription() {
+    return "Run Ant Target";
+  }
+
+  @Override
+  public Icon getIcon() {
+    return AntIcons.Build;
+  }
+
+  @NotNull
+  @Override
+  public String getId() {
+    return "AntRunConfiguration";
+  }
+
+  @Override
+  public ConfigurationFactory[] getConfigurationFactories() {
+    return new ConfigurationFactory[]{myFactory};
+  }
+
+  public ConfigurationFactory getFactory() {
+    return myFactory;
+  }
+}
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/AntRunProfileState.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/AntRunProfileState.java
new file mode 100644 (file)
index 0000000..14ab1f7
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.ant.config.execution;
+
+import com.intellij.execution.DefaultExecutionResult;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionResult;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.ProgramRunner;
+import com.intellij.lang.ant.config.AntBuildListener;
+import com.intellij.lang.ant.config.AntBuildTarget;
+import com.intellij.lang.ant.config.impl.BuildFileProperty;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+
+public class AntRunProfileState implements RunProfileState {
+  private final ExecutionEnvironment myEnvironment;
+
+  public AntRunProfileState(ExecutionEnvironment environment) {
+    myEnvironment = environment;
+  }
+
+  @Nullable
+  @Override
+  public ExecutionResult execute(Executor executor, @NotNull ProgramRunner runner) throws ExecutionException {
+    RunProfile profile = myEnvironment.getRunProfile();
+    if (profile instanceof AntRunConfiguration) {
+      AntRunConfiguration antRunConfiguration = (AntRunConfiguration)profile;
+      AntBuildTarget target = antRunConfiguration.getTarget();
+      if (target == null) return null;
+      ProcessHandler processHandler = ExecutionHandler
+        .runTarget(antRunConfiguration, myEnvironment.getDataContext(), new ArrayList<BuildFileProperty>(), new AntBuildListener() {
+          @Override
+          public void buildFinished(int state, int errorCount) {
+
+          }
+        });
+      if (processHandler == null) return null;
+      return new DefaultExecutionResult(null, processHandler);
+    }
+    return null;
+  }
+}
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/AntRunner.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/AntRunner.java
new file mode 100644 (file)
index 0000000..1398718
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.ant.config.execution;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.executors.DefaultRunExecutor;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.GenericProgramRunner;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class AntRunner extends GenericProgramRunner {
+  public static final String EXECUTOR_ID = "AntRunConfigurationRunner";
+
+  @Nullable
+  @Override
+  protected RunContentDescriptor doExecute(@NotNull Project project,
+                                           @NotNull RunProfileState state,
+                                           @Nullable RunContentDescriptor contentToReuse,
+                                           @NotNull ExecutionEnvironment environment) throws ExecutionException {
+    FileDocumentManager.getInstance().saveAllDocuments();
+    state.execute(environment.getExecutor(), this);
+    return null;
+  }
+
+  @NotNull
+  @Override
+  public String getRunnerId() {
+    return EXECUTOR_ID;
+  }
+
+  @Override
+  public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) {
+    return DefaultRunExecutor.EXECUTOR_ID.equals(executorId) && profile instanceof AntRunConfiguration;
+  }
+}
index a0a075fa74c99108a8ef7862793181b9dd0e9487..85f1c390e7f133a52162c8c4adc23ba8c30f0b9f 100644 (file)
@@ -22,10 +22,7 @@ import com.intellij.execution.configurations.CommandLineBuilder;
 import com.intellij.execution.configurations.GeneralCommandLine;
 import com.intellij.execution.junit.JUnitProcessHandler;
 import com.intellij.execution.junit2.segments.OutputPacketProcessor;
-import com.intellij.execution.process.OSProcessHandler;
-import com.intellij.execution.process.ProcessAdapter;
-import com.intellij.execution.process.ProcessEvent;
-import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.execution.process.*;
 import com.intellij.execution.testframework.Printable;
 import com.intellij.execution.testframework.Printer;
 import com.intellij.execution.util.ExecutionErrorDialog;
@@ -34,6 +31,7 @@ import com.intellij.ide.macro.Macro;
 import com.intellij.lang.ant.AntBundle;
 import com.intellij.lang.ant.config.AntBuildFileBase;
 import com.intellij.lang.ant.config.AntBuildListener;
+import com.intellij.lang.ant.config.AntBuildTarget;
 import com.intellij.lang.ant.config.impl.BuildFileProperty;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.application.ApplicationManager;
@@ -44,10 +42,11 @@ import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Key;
-import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.encoding.EncodingProjectManager;
 import com.intellij.openapi.wm.StatusBar;
 import com.intellij.openapi.wm.WindowManager;
+import com.intellij.util.concurrency.FutureResult;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -63,6 +62,31 @@ public final class ExecutionHandler {
   private ExecutionHandler() {
   }
 
+  @Nullable
+  public static ProcessHandler runTarget(AntRunConfiguration antRunConfiguration,
+                                         final DataContext dataContext,
+                                         List<BuildFileProperty> additionalProperties, @NotNull final AntBuildListener antBuildListener) {
+    AntBuildTarget target = antRunConfiguration.getTarget();
+    if (target == null) return null;
+    FutureResult<ProcessHandler> result = runBuildImpl((AntBuildFileBase)target.getModel().getBuildFile(),
+                                                       new String[]{target.getName()},
+                                                       null,
+                                                       dataContext,
+                                                       additionalProperties, antBuildListener);
+    if (result != null) {
+      try {
+        return result.get();
+      }
+      catch (InterruptedException e) {
+        LOG.warn(e);
+      }
+      catch (java.util.concurrent.ExecutionException e) {
+        LOG.warn(e);
+      }
+    }
+    return null;
+  }
+
   /**
    * @param antBuildListener should not be null. Use {@link com.intellij.lang.ant.config.AntBuildListener#NULL}
    */
@@ -71,6 +95,34 @@ public final class ExecutionHandler {
                               @Nullable final AntBuildMessageView buildMessageViewToReuse,
                               final DataContext dataContext,
                               List<BuildFileProperty> additionalProperties, @NotNull final AntBuildListener antBuildListener) {
+    FutureResult<ProcessHandler> futureResult =
+      runBuildImpl(buildFile, targets, buildMessageViewToReuse, dataContext, additionalProperties, antBuildListener);
+    if (futureResult != null) {
+      try {
+        ProcessHandler processHandler = futureResult.get();
+        if (processHandler != null) {
+          processHandler.waitFor();
+        }
+      }
+      catch (InterruptedException e) {
+        LOG.warn(e);
+      }
+      catch (java.util.concurrent.ExecutionException e) {
+        LOG.warn(e);
+      }
+    }
+  }
+
+  /**
+   * @param antBuildListener should not be null. Use {@link com.intellij.lang.ant.config.AntBuildListener#NULL}
+   */
+  @Nullable
+  public static FutureResult<ProcessHandler> runBuildImpl(final AntBuildFileBase buildFile,
+                                                          String[] targets,
+                                                          @Nullable final AntBuildMessageView buildMessageViewToReuse,
+                                                          final DataContext dataContext,
+                                                          List<BuildFileProperty> additionalProperties,
+                                                          @NotNull final AntBuildListener antBuildListener) {
     final AntBuildMessageView messageView;
     final GeneralCommandLine commandLine;
     final Project project = buildFile.getProject();
@@ -78,7 +130,7 @@ public final class ExecutionHandler {
       FileDocumentManager.getInstance().saveAllDocuments();
       final AntCommandLineBuilder builder = new AntCommandLineBuilder();
 
-      builder.setBuildFile(buildFile.getAllOptions(), VfsUtil.virtualToIoFile(buildFile.getVirtualFile()));
+      builder.setBuildFile(buildFile.getAllOptions(), VfsUtilCore.virtualToIoFile(buildFile.getVirtualFile()));
       builder.calculateProperties(dataContext, additionalProperties);
       builder.addTargets(targets);
 
@@ -89,25 +141,25 @@ public final class ExecutionHandler {
       messageView.setBuildCommandLine(commandLine.getCommandLineString());
     }
     catch (RunCanceledException e) {
-      e.showMessage(project, AntBundle.message("run.ant.erorr.dialog.title"));
+      e.showMessage(project, AntBundle.message("run.ant.error.dialog.title"));
       antBuildListener.buildFinished(AntBuildListener.FAILED_TO_RUN, 0);
-      return;
+      return null;
     }
     catch (CantRunException e) {
-      ExecutionErrorDialog.show(e, AntBundle.message("cant.run.ant.erorr.dialog.title"), project);
+      ExecutionErrorDialog.show(e, AntBundle.message("cant.run.ant.error.dialog.title"), project);
       antBuildListener.buildFinished(AntBuildListener.FAILED_TO_RUN, 0);
-      return;
+      return null;
     }
     catch (Macro.ExecutionCancelledException e) {
       antBuildListener.buildFinished(AntBuildListener.ABORTED, 0);
-      return;
+      return null;
     }
     catch (Throwable e) {
       antBuildListener.buildFinished(AntBuildListener.FAILED_TO_RUN, 0);
       LOG.error(e);
-      return;
+      return null;
     }
-
+    final FutureResult<ProcessHandler> future = new FutureResult<ProcessHandler>();
     new Task.Backgroundable(buildFile.getProject(), AntBundle.message("ant.build.progress.dialog.title"), true) {
 
       public boolean shouldStartInBackground() {
@@ -116,11 +168,12 @@ public final class ExecutionHandler {
 
       public void onCancel() {
         antBuildListener.buildFinished(AntBuildListener.ABORTED, 0);
+        future.set(null);
       }
 
       public void run(@NotNull final ProgressIndicator indicator) {
         try {
-          runBuild(indicator, messageView, buildFile, antBuildListener, commandLine);
+          future.set(runBuild(indicator, messageView, buildFile, antBuildListener, commandLine));
         }
         catch (Throwable e) {
           LOG.error(e);
@@ -128,13 +181,15 @@ public final class ExecutionHandler {
         }
       }
     }.queue();
+    return future;
   }
 
-  private static void runBuild(final ProgressIndicator progress,
-                               @NotNull final AntBuildMessageView errorView,
-                               @NotNull final AntBuildFileBase buildFile,
-                               @NotNull final AntBuildListener antBuildListener,
-                               @NotNull GeneralCommandLine commandLine) {
+  @Nullable
+  private static ProcessHandler runBuild(final ProgressIndicator progress,
+                                         @NotNull final AntBuildMessageView errorView,
+                                         @NotNull final AntBuildFileBase buildFile,
+                                         @NotNull final AntBuildListener antBuildListener,
+                                         @NotNull GeneralCommandLine commandLine) {
     final Project project = buildFile.getProject();
 
     final long startTime = System.currentTimeMillis();
@@ -146,15 +201,15 @@ public final class ExecutionHandler {
     catch (final ExecutionException e) {
       ApplicationManager.getApplication().invokeLater(new Runnable() {
         public void run() {
-          ExecutionErrorDialog.show(e, AntBundle.message("could.not.start.process.erorr.dialog.title"), project);
+          ExecutionErrorDialog.show(e, AntBundle.message("could.not.start.process.error.dialog.title"), project);
         }
       });
       antBuildListener.buildFinished(AntBuildListener.FAILED_TO_RUN, 0);
-      return;
+      return null;
     }
 
     processRunningAnt(progress, handler, errorView, buildFile, startTime, antBuildListener);
-    handler.waitFor();
+    return handler;
   }
 
   private static void processRunningAnt(final ProgressIndicator progress,
index 1f8fa6091678b96c933ace40ee191ac8d9760d36..6d9a055a4f2b457e6beb5e1b27a8cba37d4e020d 100644 (file)
@@ -15,8 +15,9 @@
  */
 package com.intellij.lang.ant.config.explorer;
 
-import com.intellij.execution.RunManagerAdapter;
-import com.intellij.execution.RunManagerEx;
+import com.intellij.execution.*;
+import com.intellij.execution.impl.RunDialog;
+import com.intellij.execution.impl.RunManagerImpl;
 import com.intellij.icons.AllIcons;
 import com.intellij.ide.CommonActionsManager;
 import com.intellij.ide.DataManager;
@@ -27,6 +28,8 @@ import com.intellij.lang.ant.AntBundle;
 import com.intellij.lang.ant.config.*;
 import com.intellij.lang.ant.config.actions.AntBuildFilePropertiesAction;
 import com.intellij.lang.ant.config.actions.RemoveBuildFileAction;
+import com.intellij.lang.ant.config.execution.AntRunConfiguration;
+import com.intellij.lang.ant.config.execution.AntRunConfigurationType;
 import com.intellij.lang.ant.config.execution.ExecutionHandler;
 import com.intellij.lang.ant.config.impl.*;
 import com.intellij.lang.ant.config.impl.configuration.BuildFilePropertiesPanel;
@@ -57,6 +60,7 @@ import com.intellij.util.ui.tree.TreeUtil;
 import com.intellij.util.xml.DomEventListener;
 import com.intellij.util.xml.DomManager;
 import com.intellij.util.xml.events.DomEvent;
+import icons.AntIcons;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.Nullable;
 
@@ -398,6 +402,7 @@ public class AntExplorer extends SimpleToolWindowPanel implements DataProvider,
     final DefaultActionGroup group = new DefaultActionGroup();
     group.add(new RunAction());
     group.add(new CreateMetaTargetAction());
+    group.add(new MakeAntRunConfigurationAction());
     group.add(new RemoveMetaTargetsOrBuildFileAction());
     group.add(ActionManager.getInstance().getAction(IdeActions.ACTION_EDIT_SOURCE));
     if (userObject instanceof AntBuildFileNodeDescriptor) {
@@ -582,6 +587,59 @@ public class AntExplorer extends SimpleToolWindowPanel implements DataProvider,
       presentation.setEnabled(canRunSelection());
     }
   }
+  private final class MakeAntRunConfigurationAction extends AnAction {
+    public MakeAntRunConfigurationAction() {
+      super(AntBundle.message("make.ant.runconfiguration.name"), null, AntIcons.Build);
+    }
+
+    @Override
+    public void update(AnActionEvent e) {
+      super.update(e);
+
+      final Presentation presentation = e.getPresentation();
+      presentation.setEnabled(myTree.getSelectionCount() == 1 && canRunSelection());
+    }
+
+    @Override
+    public void actionPerformed(AnActionEvent e) {
+      final AntBuildFile buildFile = getCurrentBuildFile();
+      if (buildFile == null || !buildFile.exists()) {
+        return;
+      }
+
+      TreePath selectionPath = myTree.getSelectionPath();
+      if (selectionPath == null) return;
+      final DefaultMutableTreeNode node = (DefaultMutableTreeNode) selectionPath.getLastPathComponent();
+      final Object userObject = node.getUserObject();
+      AntBuildTarget target = null;
+      if (userObject instanceof AntTargetNodeDescriptor) {
+        AntTargetNodeDescriptor targetNodeDescriptor = (AntTargetNodeDescriptor)userObject;
+        target = targetNodeDescriptor.getTarget();
+      }
+      else if (userObject instanceof AntBuildFileNodeDescriptor){
+        AntBuildModel model = ((AntBuildFileNodeDescriptor)userObject).getBuildFile().getModel();
+        target = model.findTarget(model.getDefaultTargetName());
+      }
+      String name = target != null ? target.getDisplayName() : null;
+      if (target == null || name == null) {
+        return;
+      }
+
+      RunManagerImpl runManager = (RunManagerImpl)RunManager.getInstance(e.getProject());
+      RunnerAndConfigurationSettings settings =
+        runManager.createRunConfiguration(name, AntRunConfigurationType.getInstance().getFactory());
+      AntRunConfiguration configuration  = (AntRunConfiguration)settings.getConfiguration();
+      configuration.acceptSettings(target);
+      if (RunDialog.editConfiguration(e.getProject(), settings, ExecutionBundle
+        .message("create.run.configuration.for.item.dialog.title", configuration.getName()))) {
+        runManager.addConfiguration(settings,
+                                    runManager.isConfigurationShared(settings),
+                                    runManager.getBeforeRunTasks(settings.getConfiguration()), false);
+        runManager.setSelectedConfiguration(settings);
+      }
+    }
+  }
+
 
   private final class ShowAllTargetsAction extends ToggleAction {
     public ShowAllTargetsAction() {
index 0201736f89eaccb4aa2ca5d3f3aa784dd1116f67..57e5d175adddd46b7f164ad063bb1c9aa94e29e0 100644 (file)
@@ -20,15 +20,13 @@ import com.intellij.execution.RunManagerEx;
 import com.intellij.execution.configurations.RunConfiguration;
 import com.intellij.execution.runners.ExecutionEnvironment;
 import com.intellij.lang.ant.AntBundle;
-import com.intellij.lang.ant.config.AntBuildFile;
 import com.intellij.lang.ant.config.AntBuildTarget;
-import com.intellij.lang.ant.config.AntConfiguration;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.VirtualFileManager;
 import icons.AntIcons;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
@@ -115,32 +113,8 @@ public class AntBeforeRunTaskProvider extends BeforeRunTaskProvider<AntBeforeRun
   }
 
   @Nullable
-  private AntBuildTarget findTargetToExecute(AntBeforeRunTask task) {
-    final String fileUrl = task.getAntFileUrl();
-    final String targetName = task.getTargetName();
-    if (fileUrl == null || targetName == null) {
-      return null;
-    }
-    final VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(fileUrl);
-    if (vFile == null) {
-      return null;
-    }
-    final AntConfigurationImpl antConfiguration = (AntConfigurationImpl)AntConfiguration.getInstance(myProject);
-    for (AntBuildFile buildFile : antConfiguration.getBuildFiles()) {
-      if (vFile.equals(buildFile.getVirtualFile())) {
-        final AntBuildTarget target = buildFile.getModel().findTarget(targetName);
-        if (target != null) {
-          return target;
-        }
-        for (AntBuildTarget metaTarget : antConfiguration.getMetaTargets(buildFile)) {
-          if (targetName.equals(metaTarget.getName())) {
-            return metaTarget;
-          }
-        }
-        return null;
-      }
-    }
-    return null;
+  private AntBuildTarget findTargetToExecute(@NotNull AntBeforeRunTask task) {
+    return GlobalAntConfiguration.getInstance().findTarget(myProject, task.getAntFileUrl(), task.getTargetName());
   }
 
   public void handleTargetRename(String oldName, String newName) {
index cad92954ea022f1838547c7a26ae28b5c384e83a..bf71e49b112e69c58e468ebb1522a70fa230c716 100644 (file)
@@ -17,6 +17,9 @@ package com.intellij.lang.ant.config.impl;
 
 import com.intellij.ide.macro.MacroManager;
 import com.intellij.lang.ant.AntBundle;
+import com.intellij.lang.ant.config.AntBuildFile;
+import com.intellij.lang.ant.config.AntBuildTarget;
+import com.intellij.lang.ant.config.AntConfiguration;
 import com.intellij.lang.ant.config.AntConfigurationBase;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.PathManager;
@@ -29,6 +32,8 @@ import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.InvalidDataException;
 import com.intellij.openapi.util.JDOMExternalizable;
 import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.util.config.*;
 import com.intellij.util.containers.ContainerUtil;
 import org.jdom.Element;
@@ -144,4 +149,30 @@ public class GlobalAntConfiguration implements ApplicationComponent, JDOMExterna
   public static MacroManager getMacroManager() {
     return MacroManager.getInstance();
   }
+
+  public AntBuildTarget findTarget(Project project, String fileUrl, String targetName) {
+    if (fileUrl == null || targetName == null || project == null) {
+      return null;
+    }
+    final VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(fileUrl);
+    if (vFile == null) {
+      return null;
+    }
+    final AntConfigurationImpl antConfiguration = (AntConfigurationImpl)AntConfiguration.getInstance(project);
+    for (AntBuildFile buildFile : antConfiguration.getBuildFiles()) {
+      if (vFile.equals(buildFile.getVirtualFile())) {
+        final AntBuildTarget target = buildFile.getModel().findTarget(targetName);
+        if (target != null) {
+          return target;
+        }
+        for (AntBuildTarget metaTarget : antConfiguration.getMetaTargets(buildFile)) {
+          if (targetName.equals(metaTarget.getName())) {
+            return metaTarget;
+          }
+        }
+        return null;
+      }
+    }
+    return null;
+  }
 }
index 80d351f7e6e20741c631d3010d56fa345d41f5f0..8c98c67e4997aec4b2b0b1d647f6adf5deae93be 100644 (file)
@@ -46,9 +46,9 @@ cancel.button=Cancel
 background.button=&Background
 ant.build.progress.dialog.title=Ant Build Progress
 ant.build.local.history.label=Running Ant: ''{0}''
-run.ant.erorr.dialog.title=Run ANT
-cant.run.ant.erorr.dialog.title=Cannot Run ANT
-could.not.start.process.erorr.dialog.title=Could Not Start Process
+run.ant.error.dialog.title=Run ANT
+cant.run.ant.error.dialog.title=Cannot Run ANT
+could.not.start.process.error.dialog.title=Could Not Start Process
 ant.build.started.status.message=Ant build started
 canceled.by.user.error.message=Canceled by user
 user.inout.request.ant.build.input.dialog.title=Ant Build Input
@@ -76,6 +76,7 @@ run.ant.file.or.target.action.description=Run the selected build file or selecte
 run.ant.build.action.name=Run Build
 run.ant.target.action.name=Run Target
 run.ant.targets.action.name=Run Targets
+make.ant.runconfiguration.name=Create run configuration
 filter.ant.targets.action.name=Filter targets
 filter.ant.targets.action.description=Filter targets
 executes.before.run.debug.acton.name=Before Run/Debug...