ed_mann's fix for ticket #322
[phpeclipse.git] / net.sourceforge.phpeclipse.externaltools / src / net / sourceforge / phpdt / externaltools / launchConfigurations / ExternalToolsUtil.java
1 package net.sourceforge.phpdt.externaltools.launchConfigurations;
2
3 /**********************************************************************
4  Copyright (c) 2002 IBM Corp. and others. All rights reserved.
5  This file is made available under the terms of the Common Public License v1.0
6  which accompanies this distribution, and is available at
7  http://www.eclipse.org/legal/cpl-v10.html
8  �
9  Contributors:
10  **********************************************************************/
11
12 import java.io.File;
13 import java.text.MessageFormat;
14 import java.util.Map;
15
16 import net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsModelMessages;
17 import net.sourceforge.phpdt.externaltools.internal.model.VariableContextManager;
18 import net.sourceforge.phpdt.externaltools.internal.registry.ExternalToolMigration;
19 import net.sourceforge.phpdt.externaltools.internal.registry.RefreshScopeVariable;
20 import net.sourceforge.phpdt.externaltools.internal.registry.RefreshScopeVariableRegistry;
21 import net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
22 import net.sourceforge.phpdt.externaltools.model.ToolUtil;
23 import net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
24 import net.sourceforge.phpeclipse.externaltools.ExternalToolsPlugin;
25
26 import org.eclipse.jface.dialogs.MessageDialog;
27 import org.eclipse.ui.IWorkbenchWindow;
28 import org.eclipse.ui.PlatformUI;
29 import org.eclipse.core.resources.IResource;
30 import org.eclipse.core.runtime.CoreException;
31 import org.eclipse.core.runtime.IPath;
32 import org.eclipse.core.runtime.IProgressMonitor;
33 import org.eclipse.core.runtime.IStatus;
34 import org.eclipse.core.runtime.MultiStatus;
35 import org.eclipse.core.runtime.Path;
36 import org.eclipse.core.runtime.Status;
37 import org.eclipse.debug.core.DebugPlugin;
38 import org.eclipse.debug.core.ILaunchConfiguration;
39 import org.eclipse.debug.core.ILaunchConfigurationType;
40 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
41 import org.eclipse.debug.core.ILaunchManager;
42
43 /**
44  * Utilities for external tool launch configurations.
45  * <p>
46  * This class it not intended to be instantiated.
47  * </p>
48  */
49 public class ExternalToolsUtil {
50
51         private static final String LAUNCH_CONFIG_HANDLE = "LaunchConfigHandle"; //$NON-NLS-1$
52
53         /**
54          * Not to be instantiated.
55          */
56         private ExternalToolsUtil() {
57         };
58
59         /**
60          * Throws a core exception with an error status object built from the given
61          * message, lower level exception, and error code.
62          * 
63          * @param message
64          *            the status message
65          * @param exception
66          *            lower level exception associated with the error, or
67          *            <code>null</code> if none
68          * @param code
69          *            error code
70          */
71         protected static void abort(String message, Throwable exception, int code)
72                         throws CoreException {
73                 throw new CoreException(new Status(IStatus.ERROR,
74                                 IExternalToolConstants.PLUGIN_ID, code, message, exception));
75         }
76
77         /**
78          * Returns active variable context. The active variable context is used to
79          * expand variable expressions. If the workspace is currently being built,
80          * the context is associated with the project being built. Otherwise, the
81          * context is associated with the selected resource.
82          * 
83          * @return active variable context
84          */
85         public static ExpandVariableContext getVariableContext() {
86                 return VariableContextManager.getDefault().getVariableContext();
87         }
88
89         /**
90          * Expands and returns the location attribute of the given launch
91          * configuration, based on the given variable context. The location is
92          * verified to point to an existing file, in the local file system.
93          * 
94          * @param configuration
95          *            launch configuration
96          * @param context
97          *            context used to expand variables
98          * @return an absolute path to a file in the local file system
99          * @throws CoreException
100          *             if unable to retrieve the associated launch configuration
101          *             attribute, if unable to resolve any variables, or if the
102          *             resolved location does not point to an existing file in the
103          *             local file system
104          */
105         public static IPath getLocation(ILaunchConfiguration configuration,
106                         ExpandVariableContext context) throws CoreException {
107                 String location = configuration.getAttribute(
108                                 IExternalToolConstants.ATTR_LOCATION, (String) null);
109                 if (location == null) {
110                         abort(
111                                         MessageFormat
112                                                         .format(
113                                                                         ExternalToolsLaunchConfigurationMessages
114                                                                                         .getString("ExternalToolsUtil.Location_not_specified_by_{0}_1"), new String[] { configuration.getName() }), null, 0); //$NON-NLS-1$
115                 } else {
116                         MultiStatus status = new MultiStatus(
117                                         IExternalToolConstants.PLUGIN_ID,
118                                         0,
119                                         ExternalToolsModelMessages
120                                                         .getString("RunExternalToolAction.runProblem"), null); //$NON-NLS-1$;
121                         String expandedLocation = ToolUtil.expandFileLocation(location,
122                                         context, status);
123                         if (status.isOK()) {
124                                 if (expandedLocation == null || expandedLocation.length() == 0) {
125                                         String msg = ExternalToolsModelMessages
126                                                         .format(
127                                                                         "DefaultRunnerContext.invalidLocation", new Object[] { configuration.getName() }); //$NON-NLS-1$
128                                         abort(msg, null, 0);
129                                 } else {
130                                         File file = new File(expandedLocation);
131                                         if (file.isFile()) {
132                                                 return new Path(expandedLocation);
133                                         } else {
134                                                 String msg = ExternalToolsModelMessages
135                                                                 .format(
136                                                                                 "DefaultRunnerContext.invalidLocation", new Object[] { configuration.getName() }); //$NON-NLS-1$
137                                                 abort(msg, null, 0);
138                                         }
139                                 }
140                         } else {
141                                 throw new CoreException(status);
142                         }
143                 }
144                 // execution will not reach here
145                 return null;
146         }
147
148         /**
149          * Expands and returns the working directory attribute of the given launch
150          * configuration, based on the given variable context. Returns
151          * <code>null</code> if a working directory is not specified. If
152          * specified, the working is verified to point to an existing directory in
153          * the local file system.
154          * 
155          * @param configuration
156          *            launch configuration
157          * @param context
158          *            context used to expand variables
159          * @return an absolute path to a direcoty in the local file system, or
160          *         <code>null</code> if unspecified
161          * @throws CoreException
162          *             if unable to retrieve the associated launch configuration
163          *             attribute, if unable to resolve any variables, or if the
164          *             resolved location does not point to an existing directory in
165          *             the local file system
166          */
167         public static IPath getWorkingDirectory(ILaunchConfiguration configuration,
168                         ExpandVariableContext context) throws CoreException {
169                 String location = configuration.getAttribute(
170                                 IExternalToolConstants.ATTR_WORKING_DIRECTORY, (String) null);
171                 if (location != null) {
172                         MultiStatus status = new MultiStatus(
173                                         IExternalToolConstants.PLUGIN_ID,
174                                         0,
175                                         ExternalToolsModelMessages
176                                                         .getString("RunExternalToolAction.runProblem"), null); //$NON-NLS-1$;
177                         String expandedLocation = ToolUtil.expandDirectoryLocation(
178                                         location, context, status);
179                         if (status.isOK()) {
180                                 if (expandedLocation != null && expandedLocation.length() > 0) {
181                                         File path = new File(expandedLocation);
182                                         if (path.isDirectory()) {
183                                                 return new Path(expandedLocation);
184                                         } else {
185                                                 String msg = ExternalToolsModelMessages
186                                                                 .format(
187                                                                                 "DefaultRunnerContext.invalidDirectory", new Object[] { configuration.getName() }); //$NON-NLS-1$
188                                                 abort(msg, null, 0);
189                                         }
190                                 }
191                         } else {
192                                 throw new CoreException(status);
193                         }
194                 }
195                 return null;
196         }
197
198         /**
199          * Expands and returns the arguments attribute of the given launch
200          * configuration, based on the given variable context. Returns
201          * <code>null</code> if arguments are not specified.
202          * 
203          * @param configuration
204          *            launch configuration
205          * @param context
206          *            context used to expand variables
207          * @return an array of resolved arguments, or <code>null</code> if
208          *         unspecified
209          * @throws CoreException
210          *             if unable to retrieve the associated launch configuration
211          *             attribute, or if unable to resolve any variables
212          */
213         public static String[] getArguments(ILaunchConfiguration configuration,
214                         ExpandVariableContext context) throws CoreException {
215                 String args = configuration.getAttribute(
216                                 IExternalToolConstants.ATTR_TOOL_ARGUMENTS, (String) null);
217                 if (args != null) {
218                         MultiStatus status = new MultiStatus(
219                                         IExternalToolConstants.PLUGIN_ID,
220                                         0,
221                                         ExternalToolsModelMessages
222                                                         .getString("RunExternalToolAction.runProblem"), null); //$NON-NLS-1$;
223                         String[] expandedArgs = ToolUtil.expandArguments(args, context,
224                                         status);
225                         if (status.isOK()) {
226                                 return expandedArgs;
227                         } else {
228                                 throw new CoreException(status);
229                         }
230                 }
231                 return null;
232         }
233
234         /**
235          * Returns the refresh scope specified by the given launch configuration or
236          * <code>null</code> if none.
237          * 
238          * @param configuration
239          * @return refresh scope
240          * @throws CoreException
241          *             if unable to access the associated attribute
242          */
243         public static String getRefreshScope(ILaunchConfiguration configuration)
244                         throws CoreException {
245                 return configuration.getAttribute(
246                                 IExternalToolConstants.ATTR_REFRESH_SCOPE, (String) null);
247         }
248
249         /**
250          * Returns whether the refresh scope specified by the given launch
251          * configuration is recursive.
252          * 
253          * @param configuration
254          * @return whether the refresh scope is recursive
255          * @throws CoreException
256          *             if unable to access the associated attribute
257          */
258         public static boolean isRefreshRecursive(ILaunchConfiguration configuration)
259                         throws CoreException {
260                 return configuration.getAttribute(
261                                 IExternalToolConstants.ATTR_REFRESH_RECURSIVE, false);
262         }
263
264         /**
265          * Refreshes the resources as specified by the given launch configuration.
266          * 
267          * @param configuration
268          *            launch configuration
269          * @param context
270          *            context used to expand variables
271          * @param monitor
272          *            progress monitor
273          * @throws CoreException
274          *             if an exception occurrs while refreshing resources
275          */
276         public static void refreshResources(ILaunchConfiguration configuration,
277                         ExpandVariableContext context, IProgressMonitor monitor)
278                         throws CoreException {
279                 String scope = getRefreshScope(configuration);
280                 if (scope == null)
281                         return;
282
283                 ToolUtil.VariableDefinition varDef = ToolUtil.extractVariableTag(scope,
284                                 0);
285                 if (varDef.start == -1 || varDef.end == -1 || varDef.name == null) {
286                         String msg = ExternalToolsModelMessages
287                                         .format(
288                                                         "DefaultRunnerContext.invalidRefreshVarFormat", new Object[] { configuration.getName() }); //$NON-NLS-1$
289                         abort(msg, null, 0);
290                 }
291
292                 RefreshScopeVariableRegistry registry = ExternalToolsPlugin
293                                 .getDefault().getRefreshVariableRegistry();
294                 RefreshScopeVariable variable = registry
295                                 .getRefreshVariable(varDef.name);
296                 if (variable == null) {
297                         String msg = ExternalToolsModelMessages
298                                         .format(
299                                                         "DefaultRunnerContext.noRefreshVarNamed", new Object[] { configuration.getName(), varDef.name }); //$NON-NLS-1$
300                         abort(msg, null, 0);
301                 }
302
303                 int depth = IResource.DEPTH_ZERO;
304                 if (isRefreshRecursive(configuration))
305                         depth = IResource.DEPTH_INFINITE;
306
307                 if (monitor.isCanceled())
308                         return;
309
310                 IResource[] resources = variable.getExpander().getResources(
311                                 varDef.name, varDef.argument, context);
312                 if (resources == null || resources.length == 0)
313                         return;
314
315                 monitor.beginTask(ExternalToolsModelMessages
316                                 .getString("DefaultRunnerContext.refreshResources"), //$NON-NLS-1$
317                                 resources.length);
318
319                 MultiStatus status = new MultiStatus(
320                                 IExternalToolConstants.PLUGIN_ID,
321                                 0,
322                                 ExternalToolsLaunchConfigurationMessages
323                                                 .getString("ExternalToolsUtil.Exception(s)_occurred_during_refresh._2"), null); //$NON-NLS-1$
324                 for (int i = 0; i < resources.length; i++) {
325                         if (monitor.isCanceled())
326                                 break;
327                         if (resources[i] != null && resources[i].isAccessible()) {
328                                 try {
329                                         resources[i].refreshLocal(depth, null);
330                                 } catch (CoreException e) {
331                                         status.merge(e.getStatus());
332                                 }
333                         }
334                         monitor.worked(1);
335                 }
336
337                 monitor.done();
338                 if (!status.isOK()) {
339                         throw new CoreException(status);
340                 }
341         }
342
343         /**
344          * Returns whether this tool is to be run in the background..
345          * 
346          * @param configuration
347          * @return whether this tool is to be run in the background
348          * @throws CoreException
349          *             if unable to access the associated attribute
350          */
351         public static boolean isBackground(ILaunchConfiguration configuration)
352                         throws CoreException {
353                 return configuration.getAttribute(
354                                 IExternalToolConstants.ATTR_RUN_IN_BACKGROUND, false);
355         }
356
357         /**
358          * Returns a launch configuration from the given ICommand arguments. If the
359          * given arguments are from an old-style external tool, an unsaved working
360          * copy will be created from the arguments and returned.
361          * 
362          * @param commandArgs
363          *            the builder ICommand arguments
364          * @param newName
365          *            a new name for the config if the one in the command is invalid
366          * @return a launch configuration, a launch configuration working copy, or
367          *         <code>null</code> if not possible.
368          */
369         public static ILaunchConfiguration configFromBuildCommandArgs(
370                         Map commandArgs) {
371                 String configHandle = (String) commandArgs.get(LAUNCH_CONFIG_HANDLE);
372                 if (configHandle == null) {
373                         // Probably an old-style external tool. Try to migrate.
374                         return ExternalToolMigration.configFromArgumentMap(commandArgs);
375                 }
376                 try {
377                         return DebugPlugin.getDefault().getLaunchManager()
378                                         .getLaunchConfiguration(configHandle);
379                 } catch (CoreException e) {
380                         return null;
381                 }
382         }
383
384         /**
385          * Executes an external progam and saves the LaunchConfiguration under
386          * external tools
387          * 
388          * @param command
389          *            external tools command name
390          * @param executable
391          *            executable path i.e.c:\apache\apache.exe
392          * @param arguments
393          *            arguments for this configuration
394          * @param background
395          *            run this configuration in background mode
396          */
397         public static void execute(String command, String executable,
398                         String arguments, boolean background) {
399                 execute(command, executable, null, arguments, background);
400         }
401
402         public static void execute(String command, String executable,
403                         String workingDirectory, String arguments, boolean background) {
404                 ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
405                 ILaunchConfigurationType type = manager
406                                 .getLaunchConfigurationType(IExternalToolConstants.ID_PROGRAM_LAUNCH_CONFIGURATION_TYPE);
407
408                 ILaunchConfigurationWorkingCopy wc = null;
409                 try {
410                         wc = type.newInstance(null, command);
411                 } catch (CoreException e) {
412                         // some exception handling
413                 }
414                 wc.setAttribute(IExternalToolConstants.ATTR_LOCATION, executable);
415                 if (workingDirectory != null) {
416                         wc.setAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY,
417                                         workingDirectory);
418                 }
419                 if (arguments != null) {
420                         wc.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS,
421                                         arguments);
422                 }
423                 wc.setAttribute(IExternalToolConstants.ATTR_RUN_IN_BACKGROUND,
424                                 background);
425
426                 // saving will add the configuration to the external tools
427                 // configurations
428                 ILaunchConfiguration config;
429                 try {
430                         config = wc.doSave();
431                         config.launch(ILaunchManager.RUN_MODE, null);
432                 } catch (CoreException e) {
433                         alertDialog(executable);
434                 }
435
436         }
437
438         /**
439          * Shows an alert dialog with a warning message
440          * 
441          * @param executable external tools command name
442          */
443         private static void alertDialog(String executable) {
444                 IWorkbenchWindow window = PlatformUI.getWorkbench()
445                                 .getActiveWorkbenchWindow();
446                 MessageDialog.openWarning(window.getShell(), "Launch Error",
447                                 "Could not execute external app" + executable);
448         }
449 }