001/*
002 *  ProcessRunner.java - Abstracts away OS-specific stuff
003 *  :tabSize=8:indentSize=8:noTabs=false:
004 *  :folding=explicit:collapseFolds=1:
005 *
006 *  Copyright (C) 2001, 2003 Slava Pestov
007 *
008 *  This program is free software; you can redistribute it and/or
009 *  modify it under the terms of the GNU General Public License
010 *  as published by the Free Software Foundation; either version 2
011 *  of the License, or any later version.
012 *
013 *  This program is distributed in the hope that it will be useful,
014 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
015 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 *  GNU General Public License for more details.
017 *
018 *  You should have received a copy of the GNU General Public License
019 *  along with this program; if not, write to the Free Software
020 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
021 */
022package ca.bc.webarts.widgets;
023import java.io.*;
024
025//{{{ Imports
026import java.lang.reflect.*;
027import java.util.*;
028//import org.gjt.sp.jedit.*;
029//import org.gjt.sp.util.Log;
030//}}}
031
032/**
033 *  Description of the Class
034 *
035 */
036public abstract class ProcessRunner
037{//}}}
038
039      /**  Description of the Field */
040  private static ProcessRunner instance;
041
042  //{{{ getProcessRunner() method
043  /**
044   *  Gets the processRunner attribute of the ProcessRunner class
045   *
046   * @return    The processRunner value
047   */
048  public static ProcessRunner getProcessRunner()
049  {
050    if (instance == null)
051    {
052      if (OperatingSystem.isWindows9x())
053      {
054        instance = new Windows9x();
055      }
056      else if (OperatingSystem.isWindowsNT())
057      {
058        instance = new WindowsNT();
059      }
060      else if (OperatingSystem.isUnix())
061      {
062        instance = new Unix();
063      }
064      else
065      {
066        //Log.log(Log.WARNING,ProcessRunner.class,
067        //      "Unknown operating system");
068        instance = new Generic();
069      }
070    }
071
072    return instance;
073  }
074
075
076  /**
077   *  Description of the Method
078   *
079   * @return    Description of the Return Value
080   */
081  public abstract boolean shellExpandsGlobs();
082
083
084  /**
085   *  Description of the Method
086   *
087   * @return    Description of the Return Value
088   */
089  public abstract boolean supportsEnvironmentVariables();
090
091
092  /**
093   *  Gets the environmentVariables attribute of the ProcessRunner object
094   *
095   * @return    The environmentVariables value
096   */
097  public abstract Hashtable getEnvironmentVariables();
098
099
100  /**
101   *  Sets the upDefaultAliases attribute of the ProcessRunner object
102   *
103   * @param  aliases  The new upDefaultAliases value
104   */
105  public void setUpDefaultAliases(Hashtable aliases) { }
106
107
108  /**
109   *  Gets the caseSensitive attribute of the ProcessRunner object
110   *
111   * @return    The caseSensitive value
112   */
113  public abstract boolean isCaseSensitive();
114
115
116  /**
117   *  Description of the Method
118   *
119   * @param  args           Description of the Parameter
120   * @param  env            Description of the Parameter
121   * @param  dir            Description of the Parameter
122   * @return                Description of the Return Value
123   * @exception  Exception  Description of the Exception
124   */
125  public Process exec(String[] args, String[] env, String dir)
126    throws Exception
127  {
128    return Runtime.getRuntime().exec(args, env, new File(dir));
129  }
130
131  //{{{ Generic class
132  /**
133   *  Description of the Class
134   *
135   * @author    TGutwin
136   */
137  public static class Generic extends ProcessRunner
138  {
139    /**
140     *  Description of the Method
141     *
142     * @return    Description of the Return Value
143     */
144    public boolean shellExpandsGlobs()
145    {
146      return true;
147    }
148
149
150    /**
151     *  Description of the Method
152     *
153     * @return    Description of the Return Value
154     */
155    public boolean supportsEnvironmentVariables()
156    {
157      return false;
158    }
159
160
161    /**
162     *  Gets the environmentVariables attribute of the Generic object
163     *
164     * @return    The environmentVariables value
165     */
166    public Hashtable getEnvironmentVariables()
167    {
168      return new Hashtable();
169    }
170
171
172    /**
173     *  Gets the caseSensitive attribute of the Generic object
174     *
175     * @return    The caseSensitive value
176     */
177    public boolean isCaseSensitive()
178    {
179      return true;
180    }
181  }//}}}
182
183  
184  //{{{ Unix class
185  /**
186   *  Description of the Class
187   *
188   * @author    TGutwin
189   */
190  public static class Unix extends ProcessRunner
191  {
192    //{{{ shellExpandsGlobs() method
193    /**
194     *  Description of the Method
195     *
196     * @return    Description of the Return Value
197     */
198    public boolean shellExpandsGlobs()
199    {
200      return true;
201    }//}}}
202
203    
204    //{{{ supportsEnvironmentVariables() method
205    /**
206     *  Description of the Method
207     *
208     * @return    Description of the Return Value
209     */
210    public boolean supportsEnvironmentVariables()
211    {
212      return true;
213    }//}}}
214
215    
216    //{{{ getEnvironmentVariables() method
217    /**
218     *  Gets the environmentVariables attribute of the Unix object
219     *
220     * @return    The environmentVariables value
221     */
222    public Hashtable getEnvironmentVariables()
223    {
224      Hashtable vars = new Hashtable();
225
226      // run env, extract output
227      try
228      {
229        Process env = Runtime.getRuntime().exec("env");
230        BufferedReader in = new BufferedReader(
231            new InputStreamReader(
232            env.getInputStream()));
233
234        String line;
235        while ((line = in.readLine()) != null)
236        {
237          //Log.log(Log.DEBUG,this,line);
238          int index = line.indexOf('=');
239          if (index != -1)
240          {
241            vars.put(line.substring(0, index),
242                line.substring(index + 1));
243          }
244        }
245
246        in.close();
247      }
248      catch (IOException io)
249      {
250        //Log.log(Log.ERROR,this,io);
251      }
252
253      return vars;
254    }//}}}
255    
256
257    //{{{ isCaseSensitive() method
258    /**
259     *  Gets the caseSensitive attribute of the Unix object
260     *
261     * @return    The caseSensitive value
262     */
263    public boolean isCaseSensitive()
264    {
265      return true;
266    }//}}}
267  }//}}}
268
269  //{{{ Windows class
270  /**
271   *  Description of the Class
272   *
273   * @author    TGutwin
274   */
275  public abstract static class Windows extends ProcessRunner
276  {
277    //{{{ shellExpandsGlobs() method
278    /**
279     *  Description of the Method
280     *
281     * @return    Description of the Return Value
282     */
283    public boolean shellExpandsGlobs()
284    {
285      return false;
286    }//}}}
287
288    //{{{ isCaseSensitive() method
289    /**
290     *  Gets the caseSensitive attribute of the Windows object
291     *
292     * @return    The caseSensitive value
293     */
294    public boolean isCaseSensitive()
295    {
296      return false;
297    }//}}}
298  }//}}}
299
300  //{{{ Windows9x class
301  /**
302   *  Description of the Class
303   *
304   * @author    TGutwin
305   */
306  public static class Windows9x extends Windows
307  {
308    //{{{ supportsEnvironmentVariables() method
309    /**
310     *  Description of the Method
311     *
312     * @return    Description of the Return Value
313     */
314    public boolean supportsEnvironmentVariables()
315    {
316      return false;
317    }//}}}
318
319    //{{{ getEnvironmentVariables() method
320    /**
321     *  Gets the environmentVariables attribute of the Windows9x object
322     *
323     * @return    The environmentVariables value
324     */
325    public Hashtable getEnvironmentVariables()
326    {
327      return new Hashtable();
328    }//}}}
329
330
331    /*
332     *  //{{{ exec() method
333     *  Process exec(String[] args, String[] env, String dir)
334     *  throws Exception
335     *  {
336     *  String[] prefix = new String[] { "command.com", "/c" };
337     *  String[] actualArgs = new String[prefix.length
338     *  + args.length];
339     *  System.arraycopy(prefix,0,actualArgs,0,prefix.length);
340     *  System.arraycopy(args,0,actualArgs,prefix.length,
341     *  args.length);
342     *  return super.exec(actualArgs,env,dir);
343     *  } //}}}
344     */
345    //{{{ setUpDefaultAliases() method
346    /**
347     *  Sets the upDefaultAliases attribute of the Windows9x object
348     *
349     * @param  aliases  The new upDefaultAliases value
350     */
351    public void setUpDefaultAliases(Hashtable aliases)
352    {
353      String[] builtins = {"md", "rd", "del", "dir", "copy",
354          "move", "erase", "mkdir", "rmdir", "start", "echo",
355          "path", "ver", "vol", "ren", "type"};
356      for (int i = 0; i < builtins.length; i++)
357      {
358        aliases.put(builtins[i], "command.com /c " + builtins[i]);
359      }
360    }//}}}
361
362    //{{{ exec() method
363    /**
364     *  Description of the Method
365     *
366     * @param  args           Description of the Parameter
367     * @param  env            Description of the Parameter
368     * @param  dir            Description of the Parameter
369     * @return                Description of the Return Value
370     * @exception  Exception  Description of the Exception
371     */
372    public Process exec(String[] args, String[] env, String dir)
373      throws Exception
374    {
375      String commandName = args[0];
376
377      String[] extensionsToTry;
378      if (commandName.indexOf('.') == -1)
379      {
380        extensionsToTry = getExtensionsToTry();
381      }
382      else
383      {
384        extensionsToTry = new String[]{""};
385      }
386
387      for (int i = 0; i < extensionsToTry.length; i++)
388      {
389        args[0] = commandName + extensionsToTry[i];
390
391        try
392        {
393          return Runtime.getRuntime().exec(args, null, new File(dir));
394        }
395        catch (Exception e)
396        {
397          if (i == extensionsToTry.length - 1)
398          {
399            // throw a new exception cos
400            // Windows error messages are
401            // a bit cryptic
402            throw e;  /*new Exception(
403                jEdit.getProperty(
404                "console.shell.not-found-win",
405                new String[]{commandName,}));*/
406          }
407        }
408      }
409
410      // can't happen
411      return null;
412    }//}}}
413
414    //{{{ getExtensionsToTry() method
415    /**
416     *  Gets the extensionsToTry attribute of the Windows9x object
417     *
418     * @return    The extensionsToTry value
419     */
420    public String[] getExtensionsToTry()
421    {
422      return new String[]{".exe", ".com"};
423    }//}}}
424  }//}}}
425
426  //{{{ WindowsNT class
427  /**
428   *  Description of the Class
429   *
430   */
431  public static class WindowsNT extends Windows
432  {
433    //{{{ supportsEnvironmentVariables() method
434    /**
435     *  Description of the Method
436     *
437     * @return    Description of the Return Value
438     */
439    public boolean supportsEnvironmentVariables()
440    {
441      return true;
442    }//}}}
443
444    //{{{ getEnvironmentVariables() method
445    /**
446     *  Gets the environmentVariables attribute of the WindowsNT object
447     *
448     * @return    The environmentVariables value
449     */
450    public Hashtable getEnvironmentVariables()
451    {
452      Hashtable vars = new Hashtable();
453
454      // run env, extract output
455      try
456      {
457        Process env = Runtime.getRuntime().exec(
458            "cmd.exe /c set");
459        BufferedReader in = new BufferedReader(
460            new InputStreamReader(
461            env.getInputStream()));
462
463        String line;
464        while ((line = in.readLine()) != null)
465        {
466          //Log.log(Log.DEBUG,this,line);
467          int index = line.indexOf('=');
468          if (index != -1)
469          {
470            vars.put(line.substring(0, index),
471                line.substring(index + 1));
472          }
473        }
474
475        in.close();
476      }
477      catch (IOException io)
478      {
479        //Log.log(Log.ERROR,this,io);
480      }
481
482      return vars;
483    }//}}}
484
485    //{{{ exec() method
486    /**
487     *  Description of the Method
488     *
489     * @param  args           Command Args.
490     * @param  env            System Environment.
491     * @param  dir            The commands working dir. 
492     * @return                Description of the Return Value
493     * @exception  Exception  Description of the Exception
494     */
495    public Process exec(String[] args, String[] env, String dir)
496      throws Exception
497    {
498      String[] prefix = new String[]{"cmd.exe", "/c"};
499      String[] actualArgs = new String[prefix.length
500           + args.length];
501      System.arraycopy(prefix, 0, actualArgs, 0, prefix.length);
502      System.arraycopy(args, 0, actualArgs, prefix.length,
503          args.length);
504
505      return super.exec(actualArgs, env, dir);
506    }//}}}
507  }//}}}
508}
509