Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/fudaa/dodico/objet/CExec.java


1   /*
2    * @file         CExec.java
3    * @creation     1999-07-21
4    * @modification $Date: 2003/01/21 14:36:50 $
5    * @license      GNU General Public License 2
6    * @copyright    (c)1998-2001 CETMEF 2 bd Gambetta F-60231 Compiegne
7    * @mail         devel@fudaa.org
8    */
9   
10  package org.fudaa.dodico.objet;
11  
12  import java.io.BufferedReader;
13  import java.io.IOException;
14  import java.io.InputStreamReader;
15  import java.io.PrintStream;
16  
17  import org.fudaa.dodico.commun.DodicoLib;
18  
19  /**
20   * Un lanceur de processus externes.
21   * Lance la commande contenue dans le tableau de String[] dans un nouveau
22   * process. 2 Threads autres sont lances
23   * pour lire les flux de sortie standard et d'erreur. Ils sont arretes
24   * a la fin du process. Ces threads sont obligatoire pour vider les buffers
25   * de sorties du processus ( surtout sous windows). Il se peut qu'un thread
26   * soit bloque : si un flux n'est pas ouvert la methode readline() reste
27   * bloqué. Dans ce cas, le thread concerné sera interrompu.
28   * 
29   * @version      $Id: CExec.java,v 1.10 2003/01/21 14:36:50 deniger Exp $
30   * @author       Axel von Arnim 
31   */
32  public class CExec
33  {
34    String[] cmd;
35    PrintStream out_, err_;
36    private Process p;
37    boolean catchE;
38    MyReaderThread thOut_, thErr_;
39  
40    /**
41     * Commandes a null et les exceptions seront catchés et ecrites sur la sortie
42     * d'erreur.
43     */
44    public CExec()
45    {
46      cmd = null;
47      catchE = true;
48  
49    }
50  
51    /**
52     * @param les parametres du processus a lancer.
53     * @see java.lang.Runtime#exec(String[])
54     */
55    public CExec(String[] _cmd)
56    {
57      this();
58      setCommand(_cmd);
59    }
60  
61    /**
62     * Initialisation des commandes.
63     */
64    public void setCommand(String[] _cmd)
65    {
66      cmd = _cmd;
67    }
68  
69    /**
70     * Definition du flux recuperant la sortie standard.
71     */
72    public void setOutStream(PrintStream _out)
73    {
74      //out.setStream(_out); 
75      out_ = _out;
76    }
77  
78    /**
79     * Definition du flux recuperant la sortie d'erreur.
80     */
81    public void setErrStream(PrintStream _err)
82    {
83      //     err.setStream(_err); 
84      err_ = _err;
85    }
86  
87    /**
88     * Retourne le processus d'execution.
89     */
90    public Process getProcess()
91    {
92      return p;
93    }
94  
95    /**
96     * Specifie si les exceptions doivent etre "catches" ou non.
97     * Si elles sont catchees une trace est laissée sur la sortie d'erreur.
98     */
99    public void setCatchExceptions(boolean _catchE)
100   {
101     catchE = _catchE;
102   }
103 
104   /**
105    * Permet de fermer les threads de lecture apres l'arret du process.
106    * Si le thread est bloqué, il est
107    * interrompu. Sinon, s'il n'est pas fermé, on attend 50 ms avant de 
108    * l'interrompre. Normalement les thread de lecture doivent s'arreter par
109    * eux-meme avant la fin du process.
110    */
111   private void closeReaderThread(MyReaderThread _th) throws SecurityException
112   {
113     try
114     {
115       if (_th == null)
116         return;
117       if (!_th.isAlive())
118         return;
119       //il est encore vivant, on attend
120       _th.setPriority(Thread.MAX_PRIORITY - 2);
121       //sous windows, il arrivre que la lecture du flux soit bloquee.
122       if (_th.isBlocked())
123       {
124         //        _th.interrupt();
125         if ((DodicoLib.DEBUG) && (err_ != null))
126         {
127           err_.println(_th.getName() + " " + DodicoLib.geti18n("bloqué "));
128         }
129 
130       }
131       else
132       {
133         //le thread n'est pas termine... bizarre
134         if ((DodicoLib.DEBUG) && (err_ != null))
135         {
136           err_.println(
137             "!!" + _th.getName() + " " + DodicoLib.geti18n("non terminé."));
138         }
139         //on a attendu 2 s, on interrompt le thread
140 
141         try
142         {
143           if (_th != null)
144             _th.join(2000);
145         }
146         catch (InterruptedException _e)
147         {
148         }
149       }
150       //on a attendu 50ms, on interrompt le thread
151       if (_th.isAlive())
152       {
153         _th.interrupt();
154         if ((DodicoLib.DEBUG) && (err_ != null))
155           err_.println(
156             _th.getName() + " " + DodicoLib.geti18n("interrompu") + " ok");
157       }
158     }
159     catch (SecurityException _e)
160     {
161       System.err.println(_e.getMessage());
162     }
163   }
164 
165   /**
166    * Cette commande stoppe le processus puis les 2 threads de lecture de flux.
167    * NON TESTEE.
168    */
169   public void stop()
170   {
171     if (p != null)
172     {
173       p.destroy();
174     }
175     closeReaderThread(thOut_);
176     closeReaderThread(thErr_);
177   }
178 
179   /**
180    * Lance la command dans une process. 2 Threads sont lances
181    * pour lire les flux de sortie standard et d'erreur. Ils sont arretes
182    * a la fin du process.
183    */
184   public void exec()
185   {
186     if ((cmd == null) || (cmd.length <= 0))
187     {
188       if (err_ != null)
189         err_.println(DodicoLib.geti18n("Commande nulle"));
190       return;
191     }
192     BufferedReader psIn = null;
193     BufferedReader psErr = null;
194     int oldpriority = Thread.currentThread().getPriority();
195     try
196     {
197       if (err_ != null)
198         err_.println(
199           "*****  " + cmd[0] + " " + DodicoLib.geti18n("lance") + " *****");
200       Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
201       if (DodicoLib.DEBUG)
202         System.out.println("lancement processus");
203       p = Runtime.getRuntime().exec(cmd);
204       psIn = new BufferedReader(new InputStreamReader(p.getInputStream()));
205       psErr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
206       thErr_ = new MyReaderThread(err_, psErr);
207       thErr_.setName(DodicoLib.geti18n("Sortie d'erreur"));
208       thOut_ = new MyReaderThread(out_, psIn);
209       thOut_.setName(DodicoLib.geti18n("Sortie standard"));
210       try
211       {
212         Thread.currentThread().sleep(1000);
213       }
214       catch (InterruptedException e)
215       {
216       }
217       thOut_.start();
218       thErr_.start();
219       boolean interr = true;
220       while (interr)
221       {
222         try
223         {
224           p.waitFor();
225           interr = false;
226         }
227         catch (InterruptedException e)
228         {
229           interr = true;
230         }
231       }
232       if (DodicoLib.DEBUG)
233       {
234         System.out.println("fin processus");
235         System.out.println("fermeture sortie erreur....");
236       }
237       closeReaderThread(thErr_);
238       if (DodicoLib.DEBUG)
239       {
240         System.out.println("sortie erreur fermee");
241         System.out.println("fermeture sortie standard....");
242       }
243       closeReaderThread(thOut_);
244       if (DodicoLib.DEBUG)
245         System.out.println("sortie standard fermée....");
246       if (p.exitValue() != 0)
247         throw new RuntimeException(cmd[0] + ": abnormal exit");
248       if (err_ != null)
249         err_.println(
250           "*****  " + cmd[0] + " " + DodicoLib.geti18n("termine") + "  *****");
251     }
252     catch (IOException io)
253     {
254       if (catchE)
255         System.err.println(io);
256       else
257         throw new RuntimeException(io.getMessage());
258     }
259     catch (RuntimeException r)
260     {
261       if (catchE)
262         System.err.println(r);
263       else
264         throw r;
265     }
266     finally
267     {
268       try
269       {
270         if (DodicoLib.DEBUG)
271           System.out.println("fermeture sortie standard");
272         if (psIn != null)
273           psIn.close();
274         if (DodicoLib.DEBUG)
275           System.out.println("sortie standard fermee");
276       }
277       catch (Exception io)
278       {
279         if (catchE)
280           System.err.println("Severe " + io);
281         else
282           throw new RuntimeException("Severe " + io.getMessage());
283       }
284       try
285       {
286         if (DodicoLib.DEBUG)
287           System.out.println("fermeture sortie erreur");
288         if (psErr != null)
289           psErr.close();
290         if (DodicoLib.DEBUG)
291           System.out.println("sortie erreur fermee");
292         Thread.currentThread().setPriority(oldpriority);
293       }
294       catch (Exception io)
295       {
296         if (catchE)
297           System.err.println("Severe " + io);
298         else
299           throw new RuntimeException("Severe " + io.getMessage());
300       }
301     }
302     if (DodicoLib.DEBUG)
303       System.out.println("CExec.exec() terminee");
304   }
305 
306   /**
307    * Prend les arguments du type ex=cmd1 ex=cmd2 et lance
308    * CExec.
309    */
310   public static void main(String[] args)
311   {
312     if (args == null)
313       return;
314     int n = args.length;
315     String[] execArg = new String[n];
316     String prefix = "ex=";
317     int prefL = prefix.length();
318     int index = 0;
319     String temp;
320     for (int i = 0; i < n; i++)
321     {
322       temp = args[i];
323       if (temp.startsWith(prefix))
324       {
325         execArg[index++] = temp.substring(prefL);
326       }
327     }
328     if (index == 0)
329     {
330       System.out.println("pas d'argument trouvé");
331       System.out.println("syntaxe ex=arg1 ex=arg2 ex=arg3 ....");
332     }
333     if (index != n)
334     {
335       String[] execArgTemp = new String[index];
336       System.arraycopy(execArg, 0, execArgTemp, 0, index);
337       execArg = execArgTemp;
338     }
339     CExec c = new CExec(execArg);
340     c.setErrStream(System.err);
341     c.setOutStream(System.out);
342     c.exec();
343     if (DodicoLib.DEBUG)
344       System.out.println("exec terminé");
345   }
346 }
347 
348 /**
349  * Thread qui permet de lire les donnees d'un BufferReader et de les ecrire
350  * dans un PrintStream. Il se peut que ce thread soit bloqué si le flux d'entree
351  * du BufferedReader ne soit jamais initialise
352  * @see isBlocked();
353  */
354 class MyReaderThread extends Thread
355 {
356   private PrintStream str_;
357   private BufferedReader br_;
358   private boolean blocked_;
359 
360   /**
361    *
362    * @param _str le flux dans lequel les donnees du buffer seront ecrites
363    * @param _br  le buffer lu ( en general un buffer de sortie de process).
364    */
365   public MyReaderThread(PrintStream _str, BufferedReader _br)
366   {
367     super();
368     blocked_ = true;
369     str_ = _str;
370     br_ = _br;
371     setPriority(Thread.MAX_PRIORITY - 2);
372   }
373 
374   /**
375    * Si le thread est lance et si cette commande renvoie true, cela signifie
376    * que le thread est bloque sur la premiere commande readLine. Dans ce cas,
377    * il est conseille d'interrompre le thread.
378    */
379   public boolean isBlocked()
380   {
381     return blocked_;
382   }
383 
384   /**
385    * Lancement du thread de lecture: tant que le buffer contient des lignes
386    * elles sont renvoyees dans le PrintStream.
387    */
388   public void run()
389   {
390     String line = null;
391     try
392     {
393       blocked_ = true;
394       //sous windows le thread de lecture peut bloquer.
395       //On attend que le buffer puisse etre lu.
396       while (!br_.ready())
397       {
398         try
399         {
400           this.sleep(50);
401         }
402         catch (InterruptedException e)
403         {
404         }
405       }
406 
407       blocked_ = false;
408       if (br_.ready())
409         line = br_.readLine();
410       else
411         line = null;
412 
413       if (str_ != null)
414       {
415         while (line != null)
416         {
417           str_.println(line);
418           line = br_.readLine();
419         }
420       }
421       else
422       {
423         while (line != null)
424         {
425           line = br_.readLine();
426         }
427       }
428     }
429     catch (IOException _io)
430     {
431       System.err.println(_io.getMessage());
432     }
433 
434   }
435   /**
436    * Ferme le flux avant d'interrompre le thread.
437    * @see java.lang.Thread#interrupt()
438    */
439   public void interrupt()
440   {
441     super.interrupt();
442   }
443 
444   /**
445    * Ferme simplement le buffer. Cette methode doit avoir pour resultat
446    * d'arreter le thread par lui-meme.
447    */
448   private void closeBuffer()
449   {
450     try
451     {
452       if (br_ != null)
453         br_.close();
454     }
455     catch (IOException e)
456     {
457     }
458   }
459 
460   /**
461    * @see java.lang.Thread#destroy()
462    */
463   public void destroy()
464   {
465     super.destroy();
466   }
467 
468 }