fixed bug for detecting IFile "include files" outside of the workspace
[phpeclipse.git] / net.sourceforge.phpeclipse / 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.ExternalToolsPlugin;
17 import net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsModelMessages;
18 import net.sourceforge.phpdt.externaltools.internal.model.VariableContextManager;
19 import net.sourceforge.phpdt.externaltools.internal.registry.ExternalToolMigration;
20 import net.sourceforge.phpdt.externaltools.internal.registry.RefreshScopeVariable;
21 import net.sourceforge.phpdt.externaltools.internal.registry.RefreshScopeVariableRegistry;
22 import net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
23 import net.sourceforge.phpdt.externaltools.model.ToolUtil;
24 import net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
25
26 import org.eclipse.core.resources.IResource;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IPath;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.IStatus;
31 import org.eclipse.core.runtime.MultiStatus;
32 import org.eclipse.core.runtime.Path;
33 import org.eclipse.core.runtime.Status;
34 import org.eclipse.debug.core.DebugPlugin;
35 import org.eclipse.debug.core.ILaunchConfiguration;
36 import org.eclipse.debug.core.ILaunchConfigurationType;
37 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
38 import org.eclipse.debug.core.ILaunchManager;
39
40 /**
41  * Utilities for external tool launch configurations.
42  * <p>
43  * This class it not intended to be instantiated.
44  * </p>
45  */
46 public class ExternalToolsUtil {
47
48   private static final String LAUNCH_CONFIG_HANDLE = "LaunchConfigHandle"; //$NON-NLS-1$
49
50   /**
51    * Not to be instantiated.
52    */
53   private ExternalToolsUtil() {
54   };
55
56   /**
57    * Throws a core exception with an error status object built from
58    * the given message, lower level exception, and error code.
59    * 
60    * @param message the status message
61    * @param exception lower level exception associated with the
62    *  error, or <code>null</code> if none
63    * @param code error code
64    */
65   protected static void abort(String message, Throwable exception, int code) throws CoreException {
66     throw new CoreException(new Status(IStatus.ERROR, IExternalToolConstants.PLUGIN_ID, code, message, exception));
67   }
68
69   /**
70    * Returns active variable context. The active variable context is used to
71    * expand variable expressions. If the workspace is currently being built,
72    * the context is associated with the project being built. Otherwise, the
73    * context is associated with the selected resource.
74    * 
75    * @return active variable context
76    */
77   public static ExpandVariableContext getVariableContext() {
78     return VariableContextManager.getDefault().getVariableContext();
79   }
80
81   /**
82    * Expands and returns the location attribute of the given launch
83    * configuration, based on the given variable context. The location is
84    * verified to point to an existing file, in the local file system.
85    * 
86    * @param configuration launch configuration
87    * @param context context used to expand variables
88    * @return an absolute path to a file in the local file system  
89    * @throws CoreException if unable to retrieve the associated launch
90    * configuration attribute, if unable to resolve any variables, or if the
91    * resolved location does not point to an existing file in the local file
92    * system
93    */
94   public static IPath getLocation(ILaunchConfiguration configuration, ExpandVariableContext context) throws CoreException {
95     String location = configuration.getAttribute(IExternalToolConstants.ATTR_LOCATION, (String) null);
96     if (location == null) {
97       abort(MessageFormat.format(ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsUtil.Location_not_specified_by_{0}_1"), new String[] { configuration.getName()}), null, 0); //$NON-NLS-1$
98     } else {
99       MultiStatus status = new MultiStatus(IExternalToolConstants.PLUGIN_ID, 0, ExternalToolsModelMessages.getString("RunExternalToolAction.runProblem"), null); //$NON-NLS-1$;
100       String expandedLocation = ToolUtil.expandFileLocation(location, context, status);
101       if (status.isOK()) {
102         if (expandedLocation == null || expandedLocation.length() == 0) {
103           String msg = ExternalToolsModelMessages.format("DefaultRunnerContext.invalidLocation", new Object[] { configuration.getName()}); //$NON-NLS-1$
104           abort(msg, null, 0);
105         } else {
106           File file = new File(expandedLocation);
107           if (file.isFile()) {
108             return new Path(expandedLocation);
109           } else {
110             String msg = ExternalToolsModelMessages.format("DefaultRunnerContext.invalidLocation", new Object[] { configuration.getName()}); //$NON-NLS-1$
111             abort(msg, null, 0);
112           }
113         }
114       } else {
115         throw new CoreException(status);
116       }
117     }
118     // execution will not reach here
119     return null;
120   }
121
122   /**
123    * Expands and returns the working directory attribute of the given launch
124    * configuration, based on the given variable context. Returns
125    * <code>null</code> if a working directory is not specified. If specified,
126    * the working is verified to point to an existing directory in the local
127    * file system.
128    * 
129    * @param configuration launch configuration
130    * @param context context used to expand variables
131    * @return an absolute path to a direcoty in the local file system, or
132    * <code>null</code> if unspecified
133    * @throws CoreException if unable to retrieve the associated launch
134    * configuration attribute, if unable to resolve any variables, or if the
135    * resolved location does not point to an existing directory in the local
136    * file system
137    */
138   public static IPath getWorkingDirectory(ILaunchConfiguration configuration, ExpandVariableContext context) throws CoreException {
139     String location = configuration.getAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, (String) null);
140     if (location != null) {
141       MultiStatus status = new MultiStatus(IExternalToolConstants.PLUGIN_ID, 0, ExternalToolsModelMessages.getString("RunExternalToolAction.runProblem"), null); //$NON-NLS-1$;
142       String expandedLocation = ToolUtil.expandDirectoryLocation(location, context, status);
143       if (status.isOK()) {
144         if (expandedLocation != null && expandedLocation.length() > 0) {
145           File path = new File(expandedLocation);
146           if (path.isDirectory()) {
147             return new Path(expandedLocation);
148           } else {
149             String msg = ExternalToolsModelMessages.format("DefaultRunnerContext.invalidDirectory", new Object[] { configuration.getName()}); //$NON-NLS-1$
150             abort(msg, null, 0);
151           }
152         }
153       } else {
154         throw new CoreException(status);
155       }
156     }
157     return null;
158   }
159
160   /**
161    * Expands and returns the arguments attribute of the given launch
162    * configuration, based on the given variable context. Returns
163    * <code>null</code> if arguments are not specified.
164    * 
165    * @param configuration launch configuration
166    * @param context context used to expand variables
167    * @return an array of resolved arguments, or <code>null</code> if
168    * unspecified
169    * @throws CoreException if unable to retrieve the associated launch
170    * configuration attribute, or if unable to resolve any variables
171    */
172   public static String[] getArguments(ILaunchConfiguration configuration, ExpandVariableContext context) throws CoreException {
173     String args = configuration.getAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, (String) null);
174     if (args != null) {
175       MultiStatus status = new MultiStatus(IExternalToolConstants.PLUGIN_ID, 0, ExternalToolsModelMessages.getString("RunExternalToolAction.runProblem"), null); //$NON-NLS-1$;
176       String[] expandedArgs = ToolUtil.expandArguments(args, context, status);
177       if (status.isOK()) {
178         return expandedArgs;
179       } else {
180         throw new CoreException(status);
181       }
182     }
183     return null;
184   }
185
186   /**
187    * Returns the refresh scope specified by the given launch configuration or
188    * <code>null</code> if none.
189    * 
190    * @param configuration
191    * @return refresh scope
192    * @throws CoreException if unable to access the associated attribute
193    */
194   public static String getRefreshScope(ILaunchConfiguration configuration) throws CoreException {
195     return configuration.getAttribute(IExternalToolConstants.ATTR_REFRESH_SCOPE, (String) null);
196   }
197
198   /**
199    * Returns whether the refresh scope specified by the given launch
200    * configuration is recursive.
201    * 
202    * @param configuration
203    * @return whether the refresh scope is recursive
204    * @throws CoreException if unable to access the associated attribute
205    */
206   public static boolean isRefreshRecursive(ILaunchConfiguration configuration) throws CoreException {
207     return configuration.getAttribute(IExternalToolConstants.ATTR_REFRESH_RECURSIVE, false);
208   }
209
210   /**
211    * Refreshes the resources as specified by the given launch configuration.
212    * 
213    * @param configuration launch configuration
214    * @param context context used to expand variables
215    * @param monitor progress monitor
216    * @throws CoreException if an exception occurrs while refreshing resources
217    */
218   public static void refreshResources(ILaunchConfiguration configuration, ExpandVariableContext context, IProgressMonitor monitor)
219     throws CoreException {
220     String scope = getRefreshScope(configuration);
221     if (scope == null)
222       return;
223
224     ToolUtil.VariableDefinition varDef = ToolUtil.extractVariableTag(scope, 0);
225     if (varDef.start == -1 || varDef.end == -1 || varDef.name == null) {
226       String msg = ExternalToolsModelMessages.format("DefaultRunnerContext.invalidRefreshVarFormat", new Object[] { configuration.getName()}); //$NON-NLS-1$
227       abort(msg, null, 0);
228     }
229
230     RefreshScopeVariableRegistry registry = ExternalToolsPlugin.getDefault().getRefreshVariableRegistry();
231     RefreshScopeVariable variable = registry.getRefreshVariable(varDef.name);
232     if (variable == null) {
233       String msg = ExternalToolsModelMessages.format("DefaultRunnerContext.noRefreshVarNamed", new Object[] { configuration.getName(), varDef.name }); //$NON-NLS-1$
234       abort(msg, null, 0);
235     }
236
237     int depth = IResource.DEPTH_ZERO;
238     if (isRefreshRecursive(configuration))
239       depth = IResource.DEPTH_INFINITE;
240
241     if (monitor.isCanceled())
242       return;
243
244     IResource[] resources = variable.getExpander().getResources(varDef.name, varDef.argument, context);
245     if (resources == null || resources.length == 0)
246       return;
247
248     monitor.beginTask(ExternalToolsModelMessages.getString("DefaultRunnerContext.refreshResources"), //$NON-NLS-1$
249     resources.length);
250
251     MultiStatus status = new MultiStatus(IExternalToolConstants.PLUGIN_ID, 0, ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsUtil.Exception(s)_occurred_during_refresh._2"), null); //$NON-NLS-1$
252     for (int i = 0; i < resources.length; i++) {
253       if (monitor.isCanceled())
254         break;
255       if (resources[i] != null && resources[i].isAccessible()) {
256         try {
257           resources[i].refreshLocal(depth, null);
258         } catch (CoreException e) {
259           status.merge(e.getStatus());
260         }
261       }
262       monitor.worked(1);
263     }
264
265     monitor.done();
266     if (!status.isOK()) {
267       throw new CoreException(status);
268     }
269   }
270
271   /**
272    * Returns whether this tool is to be run in the background..
273    * 
274    * @param configuration
275    * @return whether this tool is to be run in the background
276    * @throws CoreException if unable to access the associated attribute
277    */
278   public static boolean isBackground(ILaunchConfiguration configuration) throws CoreException {
279     return configuration.getAttribute(IExternalToolConstants.ATTR_RUN_IN_BACKGROUND, false);
280   }
281
282   /**
283    * Returns a launch configuration from the given ICommand arguments. If the
284    * given arguments are from an old-style external tool, an unsaved working
285    * copy will be created from the arguments and returned.
286    * 
287    * @param commandArgs the builder ICommand arguments
288    * @param newName a new name for the config if the one in the command is
289    * invalid
290    * @return a launch configuration, a launch configuration working copy, or
291    * <code>null</code> if not possible.
292    */
293   public static ILaunchConfiguration configFromBuildCommandArgs(Map commandArgs) {
294     String configHandle = (String) commandArgs.get(LAUNCH_CONFIG_HANDLE);
295     if (configHandle == null) {
296       // Probably an old-style external tool. Try to migrate.
297       return ExternalToolMigration.configFromArgumentMap(commandArgs);
298     }
299     try {
300       return DebugPlugin.getDefault().getLaunchManager().getLaunchConfiguration(configHandle);
301     } catch (CoreException e) {
302       return null;
303     }
304   }
305   /**
306    * Executes an external progam and saves the LaunchConfiguration under external tools 
307    * @param command external tools command name
308    * @param executable executable path i.e.c:\apache\apache.exe
309    * @param arguments arguments for this configuration
310    * @param background run this configuration in background mode
311    */
312   public static void execute(String command, String executable, String arguments, boolean background) {
313     ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
314     ILaunchConfigurationType type = manager.getLaunchConfigurationType(IExternalToolConstants.ID_PROGRAM_LAUNCH_CONFIGURATION_TYPE);
315
316     ILaunchConfigurationWorkingCopy wc = null;
317     try {
318       wc = type.newInstance(null, command);
319     } catch (CoreException e) {
320       //some exception handling
321     }
322     wc.setAttribute(IExternalToolConstants.ATTR_LOCATION, executable);
323     wc.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, arguments);
324     wc.setAttribute(IExternalToolConstants.ATTR_RUN_IN_BACKGROUND, background);
325
326     //          saving will add the configuration to the external tools configurations
327     ILaunchConfiguration config;
328     try {
329       config = wc.doSave();
330       config.launch(ILaunchManager.RUN_MODE, null);
331     } catch (CoreException e) {
332     }
333
334   }
335 }