Initial Commit
[packages] / xemacs-packages / jde / lisp / jde-ant.el
1 ;; jde-ant.el --- Use Apache Ant to build your JDE projects
2
3 ;; $Revision: 1.76.2.1 $ $Date: 2006/03/05 04:40:14 $ 
4
5 ;;
6 ;; Author: Jason Stell | jason.stell@globalone.net
7 ;; Author: Kevin A. Burton ( burton@openprivacy.org )
8 ;; Created: 19 Oct 2000
9 ;; Version 1.4.4
10 ;;
11
12 ;; This file is not part of Emacs
13
14 ;; This program is free software; you can redistribute it and/or
15 ;; modify it under the terms of the GNU General Public License as
16 ;; published by the Free Software Foundation; either version 2, or (at
17 ;; your option) any later version.
18
19 ;; This program is distributed in the hope that it will be useful, but
20 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22 ;; General Public License for more details.
23
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with this program; see the file COPYING.  If not, write to
26 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27 ;; Boston, MA 02111-1307, USA.
28
29 ;; Commentary:
30 ;; This file defines jde-ant-build and some helper functions.
31 ;; jde-ant-build uses the specified ant program/shell script to 
32 ;; execute a specified build file (in the project root). 
33 ;; 
34 ;;
35 ;; TODO:
36 ;;
37 ;; Notes:
38 ;; -- The JDE (Java Development Environment for Emacs) can be
39 ;;    downloaded at http://jdee.sunsite.dk
40 ;;
41 ;; -- Apache Ant is a Java & XML build system that can be downloaded 
42 ;;    at http://jakarta.apache.org/ant/
43 ;;
44 ;;
45 ;;; History:
46 ;;
47 ;; - Version 1.4.4 Thu Jan 17 2002 03:51 PM (burton@openprivacy.org):
48 ;;
49 ;;    - We now have `jde-ant-build-hook' that runs hooks after a build is
50 ;;      started.
51 ;;
52 ;; - Version 1.4.3 Thu Jan 17 2002 03:37 PM (burton@openprivacy.org): 
53 ;;
54 ;;    - fixed a bug with target completion.  We were not using initial-input
55 ;;      correctly.
56 ;;
57 ;;    - fixed a bug with jde-ant-build-classpath which wasn't using ant-home
58 ;;      correctly.  (Thanks to Javier S. Lopez)
59 ;; 
60 ;; - Version 1.4.2 Wed Jan 16 2002 05:46 PM (burton@openprivacy.org): added
61 ;; `jde-ant-use-global-classpath' (which is disabled by default) so that the
62 ;; `jde-global-classpath' can be used.
63 ;; 
64 ;; -- Version 1.3 (19 June 2001)
65 ;;    : Addition of jde-ant-projecthelp to display list of targets for
66 ;;      the current buildfile.
67 ;; -- Version 1.2 (4 June 2001) 
68 ;;    : Addition of jde-ant-read-buildfile option to prompt for the buildfile 
69 ;;      name -- contributed by Rob Shaw <shaw@servidium.com>
70 ;;    : Various Bug fixes contributed by Rob Shaw <shaw@servidium.com> 
71 ;;        - The setting of the system property in a format other
72 ;;          than -Dname=value had the side effect of negating the -emacs 
73 ;;          command line argument.
74 ;;        - The setting of the current directory to the location of the 
75 ;;          JDE project file is now taking place when
76 ;;          jde-ant-enable-find is nil.
77 ;;        - The ant target is now the last thing to be appended to
78 ;;          ant command to avoid any possible confusion for ANT
79 ;;          as to what is the desired target.
80 ;; -- Version 1.2b2 (25 May 2001) 
81 ;;    : Fix to properly use the -find <buildfile> Ant switch--contributed
82 ;;      by Rob Shaw <shaw@servidium.com>.
83 ;; -- Version 1.2b1 (23 May 2001) 
84 ;;    : Added jde-ant-enable-find custom flag to use the -find switch
85 ;;      available in Ant. This overrides the requirement for a JDE
86 ;;      project file
87 ;;    : Fixed minor bug missing whitespace before -buildfile switch
88 ;;      when building the ant compile command
89 ;; -- Version 1.1 (20 October 2000)
90 ;;    : Added interactive prompts (optional, based on customizable
91 ;;      toggles) for Ant target and additional args. Removed the 
92 ;;      jde-ant-target custom variable, since this is really
93 ;;      represented by the default target in the build file.
94 ;;    : The -f switch seems to be causing problems. Removed it from
95 ;;      the default jde-ant-args.
96 ;;    : Basic changes to the way the ant command is assembled.
97 ;;
98 ;; -- Version 1.0 (19 October 2000)
99 ;;    Initial Version
100 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
101
102 (defgroup jde-ant nil
103   "JDE Ant"
104   :group 'jde
105   :prefix "jde-ant-")
106
107 ;;; start of Douglas WF Acheson mod
108 ;;; The next three custom variables and defun added by Douglas WF Acheson to
109 ;;; allow a user to select how ant is invoked, either by script or via Java
110
111 (defcustom jde-ant-invocation-method (list "Script")
112   "*Specifies how to invoke ant. Ant can be invoked in one of three
113 ways. The first is via the ant script/program that comes with ant.
114 The second is via java and the third is via the Ant Server." 
115   :group 'jde-ant
116   :type '(list
117            (radio-button-choice
118              (const "Script")
119              (const "Java")
120              (const "Ant Server"))))
121
122 (defcustom jde-ant-home ""
123   "*Directory where ant is installed."
124   :group 'jde-ant
125   :type  'file)
126
127 (defcustom jde-ant-user-jar-files nil
128   "*Specifies jar files that hold user-defined tasks."
129   :group 'jde-ant
130   :type '(repeat (file :tag "Path")))
131
132 (defcustom jde-ant-program "ant"
133   "*Specifies name of ant program/script."
134  :group 'jde-ant
135  :type 'string)
136
137 (defcustom jde-ant-args "-emacs"
138   "*Specifies arguments to be passed to make program."
139   :group 'jde-ant
140   :type 'string)
141
142 (defcustom jde-ant-buildfile "build.xml"
143   "*Specifies the default buildfile to use."
144   :group 'jde-ant
145   :type 'string)
146
147 (defcustom jde-ant-read-buildfile nil
148 "*Specify whether to prompt for a buildfile. If non-nil, the jde-ant-build
149 command prompts you for an ant buildfile.  Note that when `jde-ant-enable-find'
150 is enable the value entered for `jde-ant-read-buildfile' is used as a
151 default. If no value is entered, or the file is non-existent, or is a
152 directory, the code tries to find the buildfile."
153
154   :group 'jde-ant
155   :type 'boolean)
156
157 (defcustom jde-ant-read-target nil
158 "*Specify whether to prompt for a build target. If non-nil, the 
159 jde-ant-build command prompts you for an ant target."
160   :group 'jde-ant
161   :type 'boolean)
162
163 (defvar jde-ant-interactive-buildfile nil
164   "Defauilt buildfile to use when prompting interactively.")
165
166 (defvar jde-ant-interactive-target-history nil
167   "History of targets entered in the minibuffer.")
168
169 (defcustom jde-ant-read-args nil
170 "*Specify whether to prompt for additional arguments to pass to ant. If
171 non-nil, the jde-ant-build command prompts you for the additional arguments."
172   :group 'jde-ant
173   :type 'boolean)
174
175 (defvar jde-ant-interactive-args-history nil
176 "History of targets entered in the minibuffer.")
177
178 (defvar jde-ant-buildfile-history nil
179  "History of targets entered in the minibuffer.")
180
181 (defvar jde-ant-passed-security-exception nil
182   "This variable is used to indicate that we have passed the
183 java.lang.SecurityException in the output. The JDESecurityManager throws an
184 exception when ANT tries exiting the JVM using System.exit(0). This exception
185 causes an stack trace in the compilation buffer. This variable is used to
186 indicate the start of the exception, therefore no more output should be
187 inserted into the buffer")
188
189 (defvar jde-ant-build-status nil
190   "Used to indicated the status of build, success or failure")
191
192  
193 (defcustom jde-ant-enable-find nil
194 "*Specify whether jde-ant find the build.xml file based on your current
195 directory. If non-nil, we will search up the directory hierarchy from the
196 current directory for the build definition file. Also note that, if non-nil,
197 this will relax the requirement for an explicit jde project file.  If
198 `jde-ant-read-buildfile' is enable that value is used as a default if valid."
199    :group 'jde-ant
200    :type 'boolean)
201
202 (defcustom jde-ant-complete-target t
203   "*Specify whether to enable completion of build target names in the
204 minibuffer.
205
206 If non-nil, the jde-ant-build command allows you to use tab completion
207 in the minibuffer to specify the build target name.  This list of
208 valid build targets is determined by parsing the Ant build file.  This
209 option has no effect if jde-ant-read-target is nil."
210   :group 'jde-ant
211   :type 'boolean)
212
213 (defcustom jde-ant-use-global-classpath nil
214   "*Specify whether to enable use of `jde-global-classpath' when running jde-ant."
215   :group 'jde-ant
216   :type 'boolean)
217
218 (defcustom jde-ant-target-regexp "<\\s-*target\\s-[^...]*?name\\s-*=\\s-*\"\\s-*\\([^\"]+\\)"
219   "*Regular expression used to match target names in Ant build files."
220   :group 'jde-ant
221   :type 'string)
222
223 (defcustom jde-ant-build-hook '(jde-compile-finish-kill-buffer
224                                 jde-compile-finish-refresh-speedbar
225                                 jde-compile-finish-update-class-info)
226   "*List of hook functions run by `jde-ant-build' (see `run-hooks'). Each
227 function should accept two arguments: the compilation buffer and a string
228 describing how the compilation finished"
229   :group 'jde-ant
230   :type 'hook)
231
232 (defcustom jde-ant-working-directory ""
233   "*Path of the working directory to use in 'ant' build mode. This string must
234 end in a slash, for example, c:/foo/bar/ or ./ . If this string is empty, the
235 'ant' build mode uses the current file location as its working directory."
236   :group 'jde-ant
237   :type 'string)
238
239 (defun jde-build-ant-command (target more-args &optional buildfile)
240   "Constructs the java ant command. The variable `jde-ant-home' is used
241 if it is set, otherwise it gets the ant home from the environment
242 variable ANT_HOME."
243
244   ;;provide a default buildfile.
245   (when (null buildfile)
246     (setq buildfile jde-ant-buildfile))
247     
248   (let* ((ant-home (jde-ant-get-ant-home))
249          (delimiter (if (or
250                          (string= (car jde-ant-invocation-method) "Java")
251                          (and (string= (car jde-ant-invocation-method)
252                                        "Script")
253                               (not (featurep 'xemacs))))
254                         "'"
255                       "\""))
256          (ant-program (if (or (string-match "\\\\" jde-ant-program)
257                               (string-match "/" jde-ant-program))
258                           (jde-normalize-path jde-ant-program)
259                         jde-ant-program))
260          (ant-command
261           (concat 
262            (if (string= (car jde-ant-invocation-method) "Script") ant-program)
263            (if (string= (car jde-ant-invocation-method) "Java")
264                (concat
265                 (jde-get-jdk-prog 'java)
266                 " -classpath "
267                 (if (and (or (eq system-type 'windows-nt)
268                               (eq system-type 'cygwin32))
269                          (string-match "sh$" shell-file-name))
270                     delimiter)
271                 (jde-ant-build-classpath)
272             (if (and (or (eq system-type 'windows-nt)
273                          (eq system-type 'cygwin32))
274                      (string-match "sh$" shell-file-name))
275                 delimiter)))
276            (if ant-home 
277                (concat 
278                 " -Dant.home=" 
279                 (if (or 
280                      (string-match " " ant-home) ;; Quote path if it
281                      (string-match "." ant-home));; contains a space
282                     (concat "\"" ant-home "\"")  ;; or period.
283                   ant-home)))
284           (if (string= (car jde-ant-invocation-method) "Java")
285               (concat
286                " "
287                "org.apache.tools.ant.Main")))))
288           
289     (if (not (string= buildfile ""))
290         (setq ant-command 
291               (concat ant-command 
292                       " -buildfile " delimiter
293                       (jde-normalize-path buildfile)
294                       delimiter)))
295
296     (if (not (string= jde-ant-args ""))
297         (setq ant-command (concat ant-command " " jde-ant-args)))
298
299     (if (and (not (null more-args))
300              (not (string= more-args "")))
301         (setq ant-command (concat ant-command " " more-args)))
302
303     (if (not (string= target ""))
304         (setq ant-command (concat ant-command " " target " ")))
305     
306     ant-command))
307
308 (defun jde-ant-build-classpath()
309   "Build the classpath we should use when running ant.  This returns a
310 classpath normalized with `jde-build-classpath'."
311
312   (let* ((ant-home (jde-ant-get-ant-home))
313          classpath)
314
315     (setq classpath (append (list (expand-file-name "lib" ant-home)
316                                   (jde-get-tools-jar))
317                             jde-ant-user-jar-files))
318
319     (when jde-ant-use-global-classpath
320       (setq classpath (append classpath jde-global-classpath)))
321
322     (jde-build-classpath classpath)))
323
324 (defun jde-ant-get-ant-home ()
325   "Calculate an appropriate ant home."
326   (let ((ant-home
327          (if (string= jde-ant-home "")
328              (getenv "ANT_HOME")
329            jde-ant-home)))
330     (if ant-home
331         (jde-normalize-path ant-home))))
332
333 (defun jde-ant-interactive-get-buildfile ()
334   "Get a buildfile interactively.  This is used so that code that needs to read
335   a buildfile from interactive can share the same type of behavior.  This will
336   return a new filename which points to the build.xml file to use."
337
338   (let (buildfile)
339
340     (if jde-ant-read-buildfile
341         ;;read the buildfile from the user.
342
343         ;;figure out which directory to execute from.
344         (let (prompt-directory prompt-filename)
345
346           (if jde-ant-interactive-buildfile
347               (progn
348                 (setq prompt-directory
349                       (file-name-directory jde-ant-interactive-buildfile))
350                 (setq prompt-filename
351                       (file-name-nondirectory jde-ant-interactive-buildfile)))
352
353             (setq prompt-directory (jde-ant-get-default-directory))
354             (setq prompt-filename ""))
355           
356           (setq buildfile
357                 (read-file-name "Buildfile: " prompt-directory nil t
358                                 prompt-filename))))
359     (if (or (and jde-ant-enable-find (not jde-ant-read-buildfile)) ;enable only
360             (and jde-ant-enable-find jde-ant-read-buildfile 
361                  (or (null buildfile)   ;no buildfile
362                      (string= "" buildfile)
363                      (and (file-exists-p buildfile) ;buildfile is a directory
364                           (file-directory-p buildfile)))))
365         (progn 
366           (setq buildfile (jde-ant-find-build-file
367                            (jde-ant-get-default-directory)))
368           
369           (when (null buildfile)
370             (error "Could not find Ant build file"))
371           
372           (when (not (file-exists-p buildfile))
373             (error "File does not exist %s " buildfile))))
374       
375     (if (and (not jde-ant-enable-find)
376              (not jde-ant-read-buildfile))
377         ;;use the default buildfile.
378         (setq buildfile (jde-normalize-path jde-ant-buildfile)))
379     buildfile))
380
381 ;;;###autoload
382 (defun jde-ant-build(buildfile target &optional interactive-args)
383   "Build the current project using Ant.  If interactive, we try to prompt the
384   user for certain variables.."
385   (interactive
386    (let* ((buildfile (jde-ant-interactive-get-buildfile))
387           (build-history (jde-ant-get-from-history buildfile))
388           (targets 
389            (if jde-ant-read-target
390                (if jde-ant-complete-target
391                    (if (fboundp 'completing-read-multiple)
392                        (completing-read-multiple
393                         "Target to build: "
394                         (jde-ant-get-target-alist buildfile)
395                         nil
396                         nil
397                         (car build-history)
398                         'build-history)
399                      (list (completing-read
400                             "Target to build: "
401                             (jde-ant-get-target-alist buildfile)
402                             nil
403                             t
404                             (car build-history)
405                             'build-history)))
406                  (list (read-from-minibuffer
407                         "Target to build: "
408                         (car build-history)
409                         nil
410                         nil
411                         'build-history)))))
412           (target 
413            (jde-ant-escape (mapconcat 'identity targets " ")))
414           (interactive-args
415            (if jde-ant-read-args
416                (read-from-minibuffer
417                 "Additional build args: "
418                 (nth 0 jde-ant-interactive-args-history)
419                 nil nil
420                 '(jde-ant-interactive-args-history . 1)))))
421
422                
423      ;; Setting the history for future use
424      (jde-ant-add-to-history buildfile build-history)
425      
426
427      ;;some of these global variables are defaults.  We should restore then for
428      ;;every request.  IE jde-ant-interactive-target and
429      ;;jde-ant-interactive-args
430
431      (setq jde-ant-interactive-buildfile buildfile)
432
433      ;;return our new arguments.  
434      ;;This should be a list of buildfile, target and optional-args.
435      (list buildfile target interactive-args)))
436   
437   (let ((compile-command 
438          (jde-build-ant-command target interactive-args buildfile))
439         process-connection-type)
440
441     (when compile-command
442       ;; Force save-some-buffers to use the minibuffer
443       ;; to query user about whether to save modified buffers.
444       ;; Otherwise, when user invokes the command from
445       ;; menu, save-some-buffers tries to popup a menu
446       ;; which seems not to be supported--at least on
447       ;; the PC.
448       (if (and (eq system-type 'windows-nt)
449                (not jde-xemacsp))
450           (let ((temp last-nonmenu-event))
451             ;; The next line makes emacs think that the command
452             ;; was invoked from the minibuffer, even when it
453             ;; is actually invoked from the menu-bar.
454             (setq last-nonmenu-event t)
455             (save-some-buffers (not compilation-ask-about-save) nil)
456             (setq last-nonmenu-event temp))
457         (save-some-buffers (not compilation-ask-about-save) nil))
458       
459       (setq compilation-finish-function
460             (lambda (buf msg)
461               (run-hook-with-args 'jde-ant-build-hook buf msg)
462               (setq compilation-finish-function nil)))
463
464       (if (string= (car jde-ant-invocation-method) "Ant Server")
465           (progn
466             (while (string-match "\"" compile-command)
467               (setq compile-command (replace-match "" nil nil
468                                                    compile-command)))
469             (jde-ant-compile-internal compile-command 
470                                       "No more errors"))
471         (let ((default-directory (jde-ant-get-default-directory)))
472           (compile-internal compile-command "No more errors"))))))
473
474 (defvar jde-ant-comint-filter nil)
475
476 (defun jde-ant-escape (target)
477   "Looks for \ characters and escape them, i.e. \\"
478   (if (not (null target))
479       (let (temp c)
480         (while (not (string= target ""))
481           (setq c (substring target 0 1)) 
482           (if (string= c "\\") 
483               (setq temp (concat temp c)))
484           (setq temp (concat temp c))
485           (setq target (substring target 1)))
486         temp)))
487      
488 (defun jde-ant-compile-internal (command error-message) 
489   "This method displays ant output in a compilation buffer.
490 error-message is a string to print if the user asks to see another error
491 and there are no more errors. "
492   (let* (error-regexp-alist
493          enter-regexp-alist
494          leave-regexp-alist
495          file-regexp-alist
496          nomessage-regexp-alist
497          (parser compilation-parse-errors-function)
498           outbuf)
499     
500     (save-excursion                                    ;;getting or creating
501       (setq outbuf (get-buffer-create "*compilation*"));;the compilation buffer
502       (set-buffer outbuf) ;;setting the compilation buffer
503       
504       ;; In case the compilation buffer is current, make sure we get the global
505       ;; values of compilation-error-regexp-alist, etc.
506       (kill-all-local-variables))
507         (setq error-regexp-alist compilation-error-regexp-alist)
508         (setq enter-regexp-alist
509               (if (boundp 'compilation-enter-directory-regexp-alist)
510                   compilation-enter-directory-regexp-alist))
511         (setq leave-regexp-alist
512               (if (boundp 'compilation-leave-directory-regexp-alist)
513                   compilation-leave-directory-regexp-alist))
514         (setq file-regexp-alist
515               (if (boundp 'compilation-file-regexp-alist)
516                   compilation-file-regexp-alist))
517         (setq nomessage-regexp-alist
518               (if (boundp 'compilation-nomessage-regexp-alist)
519                   compilation-nomessage-regexp-alist))
520   
521         (let* (proc (thisdir (jde-ant-get-default-directory)) outwin)
522           (save-excursion
523             ;; Clear out the compilation buffer and make it writable.
524             (if (not (jde-bsh-running-p))
525                 (progn
526                   (bsh-launch (oref 'jde-bsh the-bsh))
527                   (bsh-eval (oref 'jde-bsh the-bsh) (jde-create-prj-values-str))))
528             (setq proc (bsh-get-process (oref 'jde-bsh the-bsh)))
529             (set-buffer outbuf)
530             (compilation-mode)
531             (setq buffer-read-only nil)
532             (buffer-disable-undo (current-buffer))
533             (erase-buffer)
534             (buffer-enable-undo (current-buffer))
535             (display-buffer outbuf)
536             (insert "AntServer output:\n")
537             (insert command "\n")
538             (set-buffer-modified-p nil)
539             (setq jde-ant-comint-filter (process-filter proc))
540             (set-process-filter proc 'jde-ant-filter)
541             ;;resets the jde-ant-passed-security-exception flag
542             (setq jde-ant-passed-security-exception nil)
543             (process-send-string proc (concat "jde.util.AntServer.start(\"" 
544                                               command "\");" "\n")))
545           (setq outwin (display-buffer outbuf))
546           (save-excursion
547             ;; (setq buffer-read-only t)  ;;; Non-ergonomic.
548             (set (make-local-variable 'compilation-parse-errors-function)
549                  parser)
550             (set (make-local-variable 'compilation-error-message)
551                  error-message)
552             (set (make-local-variable 'compilation-error-regexp-alist)
553                  error-regexp-alist)
554             (if (not jde-xemacsp)
555                 (progn
556                   (set (make-local-variable
557                         'compilation-enter-directory-regexp-alist)
558                        enter-regexp-alist)
559                   (set (make-local-variable
560                         'compilation-leave-directory-regexp-alist)
561                        leave-regexp-alist)
562                   (set (make-local-variable 'compilation-file-regexp-alist)
563                        file-regexp-alist)
564                   (set (make-local-variable
565                         'compilation-nomessage-regexp-alist)
566                        nomessage-regexp-alist)))
567             (setq default-directory thisdir
568                   compilation-directory-stack (list default-directory))
569             (compilation-set-window-height outwin)
570             
571             (if (not jde-xemacsp)
572                 (if compilation-process-setup-function
573                     (funcall compilation-process-setup-function)))))
574         ;; Make it so the next C-x ` will use this buffer.
575         (setq compilation-last-buffer outbuf)))
576
577 (defun jde-ant-filter (proc string) 
578   "This filter prints out the result of the process without buffering.
579 The result is inserted as it comes in the compilation buffer."
580   (let ((compilation-buffer (get-buffer "*compilation*")))
581     (if (not (null compilation-buffer))
582         (with-current-buffer compilation-buffer
583           (let ((stack-trace
584                  (string-match "java.lang.SecurityException" string))
585                 (end-of-result (string-match ".*bsh % " string))
586                 (win (get-buffer-window "*compilation*")))
587       
588             (save-excursion
589               ;;Insert the text, advancing the process marker
590               (goto-char (point-max))
591         
592               ;;if the security exception has been thrown set the
593               ;;jde-ant-passed-security-exception flag and filter the stack
594               ;;trace out of the ouput
595               (if stack-trace 
596                   (progn
597                     (setq jde-ant-passed-security-exception t)
598                     (insert (substring string 0 stack-trace))
599                     (set-buffer-modified-p nil)
600                     (compilation-mode)
601                     (jde-ant-set-build-status (buffer-string))
602                     (jde-ant-handle-exit)))
603         
604               (if end-of-result
605                   (progn
606                     (if (not jde-ant-passed-security-exception)
607                         (progn 
608                           (insert (substring string 0 end-of-result))
609                           (set-buffer-modified-p nil)
610                           (compilation-mode)
611                           (jde-ant-set-build-status (buffer-string))
612                           (jde-ant-handle-exit)))
613                     (set-process-filter proc jde-ant-comint-filter)))
614               (if (and (not end-of-result)
615                        (not jde-ant-passed-security-exception))
616                   (insert string)))
617             (if (not jde-xemacsp)
618                 (if compilation-scroll-output
619                     (save-selected-window
620                       (if win
621                           (progn 
622                             (select-window win)
623                             (goto-char (point-max))))))))))))
624
625 (defun jde-ant-handle-exit ()
626   "Handles the compilation exit"
627   (compilation-handle-exit 
628    'exit jde-ant-build-status
629    (if (string= "0" jde-ant-build-status)
630        "finished\n"
631      "exited abnormally with code 1\n")))
632
633 (defun jde-ant-set-build-status (buffer-contents)
634   "Sets the build status based on the BUFFER-CONTENTS"
635   (if (string-match ".*BUILD SUCCESSFUL.*" buffer-contents)
636       (setq jde-ant-build-status "0"))
637   (if (string-match ".*BUILD FAILED.*" buffer-contents)
638       (setq jde-ant-build-status "1")))
639
640 ;;;###autoload
641 (defun jde-ant-projecthelp(buildfile)
642   "Display Ant project help for the current project.
643 This will execute the Ant program with the `-projecthelp' switch to output
644 available targets with their descriptions for the current buildfile. This
645 function uses the same rules as `jde-ant-build' for finding the buildfile."
646   (interactive
647    (list
648     (jde-ant-interactive-get-buildfile)))
649
650   (jde-ant-build buildfile nil "-projecthelp"))
651   
652 (defun jde-ant-find-build-file (dir)
653   "Find the next Ant build file upwards in the directory tree from DIR.
654 Returns nil if it cannot find a project file in DIR or an ascendant directory."
655   (let ((file (find (cond ((string= jde-ant-buildfile "") "build.xml")
656                           (t jde-ant-buildfile))
657                     (directory-files dir) :test 'string=)))
658     
659     (if file
660         (setq file (expand-file-name file dir))
661       (if (not (jde-root-dir-p dir))
662           (setq file (jde-ant-find-build-file (concat dir "../")))))
663
664     file))
665
666 (defun jde-ant-get-target-alist (buildfile)
667   "Returns asociation list of valid Ant project targets."
668
669   (let ((targets nil )
670         (temp-buf (get-buffer-create "*jde-ant-get-target-list-temp-buffer*")))
671     (unwind-protect
672         (save-excursion
673           (set-buffer temp-buf)
674           (erase-buffer)
675           (insert-file-contents buildfile)
676           (goto-char (point-min))
677           (while (re-search-forward jde-ant-target-regexp (point-max) t)
678             (setq targets (append targets (list (list (match-string 1)))))))
679       (kill-buffer temp-buf))
680
681     targets))
682
683 ;;;###autoload
684 (defun jde-ant-show-options ()
685   "Show the JDE Ant Options panel."
686   (interactive)
687   (customize-apropos "jde-ant" 'groups))
688
689 (defun jde-ant-get-default-directory ()
690   "Gets the default-directory according to the value of
691 'jde-ant-working-directory."
692   (if (string= jde-ant-working-directory "")
693       default-directory
694     jde-ant-working-directory))
695
696 (defun jde-ant-add-to-history (buildfile build-history)
697   (let ((temp (nth 0 jde-ant-interactive-target-history))
698         (index -1) (found nil))
699     (while (and temp (not found))
700       (setq index (1+ index))
701       (setq temp (nth index jde-ant-interactive-target-history))
702       (if (string= (car temp) buildfile)
703           (setq found t)))
704     (if found
705         (setcdr temp build-history)
706       (setq jde-ant-interactive-target-history 
707             (append 
708              jde-ant-interactive-target-history 
709              (list (list buildfile (car build-history))))))))
710
711 (defun jde-ant-get-from-history (buildfile)
712   (let ((temp (nth 0 jde-ant-interactive-target-history))
713         (index -1) (found nil))
714     (while (and temp (not found))
715       (setq index (1+ index))
716       (setq temp (nth index jde-ant-interactive-target-history))
717       (if (string= (car temp) buildfile)
718           (setq found t)))
719     (if found
720         (cdr temp)
721       nil)))
722
723 ;; Register and initialize the customization variables defined
724 ;; by this package.
725 (jde-update-autoloaded-symbols)
726
727 (provide 'jde-ant)
728
729 ;; Change History 
730
731 ;;
732 ;; $Log: jde-ant.el,v $
733 ;; Revision 1.76.2.1  2006/03/05 04:40:14  paulk
734 ;; Quote ant.home path if it contains a period. Thanks to Troy Daniels.
735 ;;
736 ;; Revision 1.76  2004/11/20 05:51:04  paulk
737 ;; Fix regression in jde-ant-build command. Thanks to Jon Schewe.
738 ;;
739 ;; Revision 1.75  2004/11/16 13:48:43  jslopez
740 ;; Fixes typo, indentity->identity.
741 ;;
742 ;; Revision 1.74  2004/11/16 05:34:48  paulk
743 ;; Updated jde-ant-build to force use of pipes on Linux to interact with Ant. Also, simplified the code.
744 ;;
745 ;; Revision 1.73  2004/08/21 04:31:55  paulk
746 ;; Update the wizard class list after building a project.
747 ;;
748 ;; Revision 1.72  2004/07/01 14:04:39  jslopez
749 ;; Compatibility fix for emacs in CVS. Replaces jde-xemacsp check for boundp for
750 ;; the following variables: compilation-nomessage-regexp-alist,
751 ;; compilation-file-regexp-alist, compilation-leave-directory-regexp-alist,
752 ;; compilation-enter-directory-regexp-alist. Uses the compilation-mode without a
753 ;; parameter. The emacs in CVS does not contain the variables, or the parameter
754 ;; for compilation mode.
755 ;;
756 ;; Revision 1.71  2004/05/28 04:42:49  paulk
757 ;; Quote ant-home on the command line if it contains a space.
758 ;;
759 ;; Revision 1.70  2004/02/09 05:00:54  paulk
760 ;; Setting jde-ant-working-directory now works when invoking ant via a script or a vm.
761 ;; Thanks to Stan Lanning.
762 ;;
763 ;; Revision 1.69  2003/12/06 15:50:29  jslopez
764 ;; Fixes problem where jde-ant-program was being normalized unless it was set to
765 ;; ant or ant.bat. Now it only gets normalized if it contains '/' or a '\'.
766 ;;
767 ;; Revision 1.68  2003/10/19 14:25:32  jslopez
768 ;; Removes sit-for from jde-ant-filter. It causes the tool-bar and menu bar to
769 ;; redisplay annoyingly, plus it is not needed.
770 ;;
771 ;; Revision 1.67  2003/10/19 14:19:34  jslopez
772 ;; Fixes error in the jde-ant-filter.
773 ;;
774 ;; Revision 1.66  2003/06/24 13:00:51  paulk
775 ;; Fixed bug that caused noncompleting prompting for target to fail. Thanks to Christian Schmitt.
776 ;;
777 ;; Revision 1.65  2003/05/15 03:28:21  paulk
778 ;; Fix jde-ant-get-ant-home.
779 ;;
780 ;; Revision 1.64  2003/03/28 05:33:29  andyp
781 ;; XEmacs optimizations for JDEbug and efc.
782 ;;
783 ;; Revision 1.63  2003/03/04 10:15:07  paulk
784 ;; Updated to use the new bsh-get-process method provided
785 ;; by bsh to get its process. This is necessary to insulate
786 ;; clients from the fact that bsh now uses a bsh-buffer
787 ;; object to wrap the Emacs Lisp buffer object that specifies
788 ;; the associated process.
789 ;;
790 ;; Revision 1.62  2003/02/28 15:33:54  jslopez
791 ;; Adds support to jde-ant-complete-target to complete multiple targets.
792 ;;
793 ;; Revision 1.61  2003/02/17 21:38:04  jslopez
794 ;; Fixes regression bug.
795 ;;
796 ;; Revision 1.60  2003/02/17 08:13:05  paulk
797 ;; Changes required to support new package-independent version of beanshell.el
798 ;;
799 ;; Revision 1.59  2003/01/31 21:58:31  jslopez
800 ;; Fixes regression bug for XEmacs. "'" Causes in XEmacs not to be able to
801 ;; find the buildfile.
802 ;;
803 ;; Revision 1.58  2003/01/23 02:45:26  jslopez
804 ;; Fixes bug when using ant.bat, double quotes seem to cause problems.
805 ;; Fix to use jde-normalize-path when jde-ant-program is not ant or ant.bat.
806 ;;
807 ;; Revision 1.57  2003/01/22 03:23:39  jslopez
808 ;; Normalizes jde-ant-program.
809 ;;
810 ;; Revision 1.56  2003/01/21 13:39:13  jslopez
811 ;; XEmacs compatibility fix, history seems to be a reserve word
812 ;; in XEmacs.
813 ;;
814 ;; Revision 1.55  2003/01/04 17:31:09  jslopez
815 ;; Fixes regression bug.
816 ;; Uncomments jde-ant-interactive-args-history definition.
817 ;;
818 ;; Revision 1.54  2002/12/14 18:37:36  jslopez
819 ;; Fixes regression bug.
820 ;;
821 ;; Revision 1.53  2002/12/14 18:24:03  jslopez
822 ;; Removes incompatibility between jde-ant-enable-find and jde-ant-read-buildfile.
823 ;;
824 ;; Revision 1.52  2002/12/14 17:49:04  jslopez
825 ;; Changes the target history to be specific to each buildfile.
826 ;;
827 ;; Revision 1.51  2002/12/14 03:35:07  jslopez
828 ;; Fixes quoting the classpath for the Java invocation method.
829 ;; Fixes the jde-ant-build-classpath command to grab the jar files
830 ;; in the ANT_HOME/lib directory.
831 ;;
832 ;; Revision 1.50  2002/12/06 03:47:36  ahyatt
833 ;; Changes to support Mac OS X, which does not use tools.jar
834 ;;
835 ;; Revision 1.49  2002/12/05 19:34:15  jslopez
836 ;; Readds normalizing jde-ant-buildfile. The problem with normalizing occurs only
837 ;; when using the Emacs that comes with the cygwin distribution.  In that emacs a
838 ;; path that starts with a drive letter, i.e. C: is not properly interpreted by
839 ;; emacs.
840 ;;
841 ;; Revision 1.48  2002/12/02 14:26:22  jslopez
842 ;; Adds jde-ant-working-directory.
843 ;; Rollbacks previous change of normalizing the jde-ant-buildfile.
844 ;; In certain instances you endup with a wrong buildfile path.
845 ;;
846 ;; Revision 1.47  2002/12/01 13:52:24  jslopez
847 ;; Normalizes jde-ant-buildfile before using it.
848 ;; Thanks to Luis Miguel Hernanz <luish@germinus.com> for the patch.
849 ;;
850 ;; Revision 1.46  2002/11/21 04:18:41  paulk
851 ;; These packages, when autoloaded, now register and initialize the customization variables
852 ;; that they define to the values specified in the current project file.
853 ;;
854 ;; Revision 1.45  2002/11/05 07:51:18  paulk
855 ;; Mac OS X (darwin) compatibility fix: find path of JDK java program on Macintosh. Thanks to Andrew Hyatt.
856 ;;
857 ;; Revision 1.44  2002/09/18 16:07:33  jslopez
858 ;; Removes dependency on having ANT_HOME or jde-ant-home to use the
859 ;; script method of jde-ant.
860 ;;
861 ;; Revision 1.43  2002/09/18 15:50:01  jslopez
862 ;; Fixes bug retrieving build status.
863 ;;
864 ;; Revision 1.42  2002/09/18 15:34:01  jslopez
865 ;; Modifies some regexps in the jde-ant-filter.
866 ;;
867 ;; Revision 1.41  2002/09/15 14:34:43  jslopez
868 ;; Fixes bug in jde-ant-build that was trying to escape a nil target.
869 ;;
870 ;; Revision 1.40  2002/09/06 13:04:21  jslopez
871 ;; Fixes use of the correct jvm.
872 ;;
873 ;; Revision 1.39  2002/08/30 22:41:30  jslopez
874 ;; Fixes jde-ant-filter to avoid having a partial stack trace in the bsh buffer.
875 ;;
876 ;; Revision 1.38  2002/08/29 12:38:55  jslopez
877 ;; Updates jde-ant-build-hook to take the buffer and a message as parameters.
878 ;; Updates jde-ant-build-hook to run as the compilation-finish-function.
879 ;; Adds to the jde-ant-build-hook the same hooks that jde-compile-finish-hook runs.
880 ;;
881 ;; Revision 1.37  2002/08/29 11:20:24  jslopez
882 ;; Improves the jde-ant-filter to filter the java.lang.SecurityException
883 ;; stack trace at the end of the compilation.
884 ;;
885 ;; Revision 1.36  2002/08/07 06:36:20  paulk
886 ;; Removed code intended to eliminate spurious warnings when byte-compiling the JDEE. The
887 ;; removed code now resides in a separate package, jde-compat.el. Thanks to Andy Piper
888 ;; for suggesting this restructuring. Also fixed a number of compiler warnings caused
889 ;; by genuine bugs.
890 ;;
891 ;; Revision 1.35  2002/06/25 16:10:59  jslopez
892 ;; Enhance jde-ant-build to escape \ from targets.
893 ;;
894 ;; Revision 1.34  2002/05/12 06:19:34  paulk
895 ;; Docstring spelling correction.
896 ;;
897 ;; Revision 1.33  2002/02/25 20:09:59  jslopez
898 ;; The Ant Server now uses its own filter.
899 ;;
900 ;; Revision 1.32  2002/02/16 16:10:19  jslopez
901 ;; Adds jde-ant-build-hook.
902 ;;
903 ;; Revision 1.31  2002/02/15 14:11:52  jslopez
904 ;; Updates from CompileServer to AntServer.
905 ;;
906 ;; Revision 1.30  2002/02/15 02:50:57  jslopez
907 ;; Updates the ant server to be interactive.
908 ;;
909 ;; Revision 1.29  2002/01/31 03:27:59  jslopez
910 ;; Changes:
911 ;;
912 ;; - jde-build-ant-command now takes an optional argument buildfile which
913 ;; - The jde-ant-buildfile variable is now deprecated as anything but providing
914 ;;   a default
915 ;; - jde-ant-projecthelp now uses an interactive prompt and also shares a
916 ;;   function with jde-ant-build for reading the buildfile.
917 ;; - jde-ant-find-build-file uses jde-ant-buildfile as a default reference and
918 ;;   returns a string for the buildfile to use or nil.
919 ;; - jde-ant-get-target-alist now accepts a buildfile instead of using find. We
920 ;; now parameterize the filename.
921 ;; - jde-ant-interactive-buildfile is saved for every use of jde-ant-build and
922 ;; used as the default next time we enter.
923 ;; - We no longer use the Ant version of -find.  We now have a lisp version of
924 ;; this.  This was necessary in order to support jde-ant-read-target and since
925 ;; we already have an implementation it doesn't make sense to have Ant find the
926 ;; file a second time.
927 ;; - documentation updates.
928 ;; - history variables now just use -history instead arg-history
929 ;; - jde-ant-interactive-target is now gone, this is no longer needed.
930 ;; - jde-ant-interactive-args is now gone, this is no longer needed.
931 ;; - Adds`jde-ant-use-global-classpath' (which is disabled by default) so that the
932 ;;  `jde-global-classpath' can be used.
933 ;; Thanks to Kevin Burton.
934 ;;
935 ;; Revision 1.28  2001/12/03 16:35:44  jslopez
936 ;; Fixes bug when setting jde-ant-invocation-method to Script.
937 ;;
938 ;; Revision 1.27  2001/11/28 13:22:14  jslopez
939 ;; JDE ant uses jde-normalize-path with
940 ;; jde-ant-home and jde-ant-buildfile.
941 ;;
942 ;; Revision 1.26  2001/11/27 14:04:43  jslopez
943 ;; XEmacs compatability fix.
944 ;;
945 ;; Revision 1.25  2001/11/27 02:23:08  jslopez
946 ;; Adds jde-ant-buildfile-arg-history variable.
947 ;; Fixes jde-ant-target-regexp to match the name attribute
948 ;; when it is in a different ine than the target.
949 ;; i.e. <target description="foo"
950 ;;              name="compile">
951 ;; Removes unnecessary messages.
952 ;; XEmacs compatibility fix.
953 ;;
954 ;; Revision 1.24  2001/11/21 15:35:56  jslopez
955 ;; Modifies the jde-ant-target-regexp to
956 ;; match the targets name anywhere in the line.
957 ;; It stills fails if the target name is in a different
958 ;; line.
959 ;;
960 ;; Revision 1.23  2001/11/18 21:42:06  jslopez
961 ;; Updating documentation.
962 ;;
963 ;; Revision 1.22  2001/11/18 21:39:07  jslopez
964 ;; Modifies jde-build-ant-command to get the
965 ;; ant home value from the
966 ;; environment if jde-ant-home is not set.
967 ;;
968 ;; Revision 1.21  2001/11/11 23:27:41  jslopez
969 ;; Fixed bug in jde-ant-build-command, causing jde-ant-args getting
970 ;; appending without a space to the ant command if
971 ;; jde-ant-buildfile is not specified.
972 ;; Update the documentation for the methods jde-ant-invocation-method
973 ;; and jde-ant-home.
974 ;;
975 ;; Revision 1.20  2001/11/09 02:05:36  jslopez
976 ;; Fixing the output's display.
977 ;;
978 ;; Revision 1.19  2001/11/05 02:15:28  jslopez
979 ;; Adds an option to use AntServer for builds.
980 ;;
981 ;; Revision 1.18  2001/11/04 19:22:33  jslopez
982 ;; Fixes bug using Ant target completion
983 ;; cause when jde-ant-enable-find is not enabled.
984 ;;
985 ;; Revision 1.17  2001/10/30 15:20:41  jslopez
986 ;; Replaces the custom variable jde-ant-dir with jde-ant-home.
987 ;; Enclose the classpath with double quotes for Windows machines
988 ;; using cygwin as a shell.
989 ;; Include the flag ant.home as an argument to ant.
990 ;;
991 ;; Revision 1.16  2001/10/29 12:50:29  jslopez
992 ;; Removed the installation instructions from the top of the file
993 ;; since it was obsolete. Jde-ant can be used out of the box with
994 ;; JDE without having to any other installation.
995 ;; Finished moving all the ant customization variables to the
996 ;; customization group jde-ant.
997 ;;
998 ;; Revision 1.15  2001/10/29 06:27:40  paulk
999 ;; Fixed minor bug in last submission.
1000 ;;
1001 ;; Revision 1.14  2001/10/29 06:21:28  paulk
1002 ;; Added support for invoking Ant directly from java or via the ant script.
1003 ;; Thanks to Douglas WF Acheson <dwfa@yahoo.com> for some help on this.
1004 ;;
1005 ;; Revision 1.13  2001/10/21 14:36:56  jslopez
1006 ;; Added jde-ant customization group and
1007 ;; moved all its customization variables under
1008 ;; that group.
1009 ;;
1010 ;; Revision 1.12  2001/10/21 05:52:24  paulk
1011 ;; Added support auto completion of Ant targets in mini-buffer.
1012 ;; Added the following defuns and variables:
1013 ;;     defun jde-ant-find-build-file
1014 ;;     defun jde-ant-get-target-alist
1015 ;;     defcustom jde-ant-complete-target
1016 ;;     defcustom jde-ant-target-regexp
1017 ;; Modified defun jde-ant-read-target to use auto-completion, if
1018 ;; jde-ant-complete-target is non-nil. Thanks to Stephen Molitor.
1019 ;;
1020 ;; Revision 1.11  2001/10/21 05:17:54  paulk
1021 ;; Restored changes from Revison 1.9.
1022 ;;
1023 ;; Revision 1.9  2001/10/05 15:04:32  jslopez
1024 ;; Removed calls that were setting the defaul-directory in
1025 ;; jde-ant-projecthelp and jde-ant-build. There are not needed.
1026 ;;
1027 ;; Revision 1.8  2001/10/04 04:33:54  paulk
1028 ;; Start change history.
1029 ;;
1030 ;;
1031
1032 ;; End of jde-ant.el