001/*
002 * IzPack - Copyright 2001-2005 Julien Ponge, All Rights Reserved.
003 * 
004 * http://www.izforge.com/izpack/
005 * http://developer.berlios.de/projects/izpack/
006 * 
007 * Copyright 2004 Klaus Bartz
008 * Copyright 2004 Thomas Guenter
009 * 
010 * Licensed under the Apache License, Version 2.0 (the "License");
011 * you may not use this file except in compliance with the License.
012 * You may obtain a copy of the License at
013 * 
014 *     http://www.apache.org/licenses/LICENSE-2.0
015 *     
016 * Unless required by applicable law or agreed to in writing, software
017 * distributed under the License is distributed on an "AS IS" BASIS,
018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
019 * See the License for the specific language governing permissions and
020 * limitations under the License.
021 */
022
023package com.izforge.izpack.event;
024
025import java.io.File;
026import java.io.FileInputStream;
027import java.io.PrintStream;
028import java.util.ArrayList;
029import java.util.Iterator;
030import java.util.List;
031import java.util.Properties;
032
033import org.apache.tools.ant.BuildLogger;
034import org.apache.tools.ant.DefaultLogger;
035import org.apache.tools.ant.DemuxOutputStream;
036import org.apache.tools.ant.Project;
037import org.apache.tools.ant.Target;
038import org.apache.tools.ant.input.DefaultInputHandler;
039import org.apache.tools.ant.taskdefs.Ant;
040import org.apache.tools.ant.util.JavaEnvUtils;
041
042/**
043 * This class contains data and 'perform' logic for ant action listeners.
044 * 
045 * @author Thomas Guenter
046 * @author Klaus Bartz
047 * 
048 */
049public class AntAction extends ActionBase
050{
051
052    // --------AntAction specific String constants for ------------
053    // --- parsing the XML specification ------------
054
055    private static final long serialVersionUID = 3258131345250005557L;
056
057    public static final String ANTACTIONS = "antactions";
058
059    public static final String ANTACTION = "antaction";
060
061    public static final String ANTCALL = "antcall";
062
063    private boolean quiet = false;
064
065    private boolean verbose = false;
066
067    private Properties properties = null;
068
069    private List targets = null;
070
071    private List uninstallTargets = null;
072
073    private String logFile = null;
074
075    private String buildFile = null;
076
077    private List propertyFiles = null;
078
079    /**
080     * Default constructor
081     */
082    public AntAction()
083    {
084        super();
085        properties = new Properties();
086        targets = new ArrayList();
087        uninstallTargets = new ArrayList();
088        propertyFiles = new ArrayList();
089    }
090
091    /**
092     * Performs all defined install actions.
093     * 
094     * Calls {#performAction performAction(false)}.
095     * 
096     * @throws Exception
097     */
098    public void performInstallAction() throws Exception
099    {
100        performAction(false);
101    }
102
103    /**
104     * Performs all defined uninstall actions.
105     * 
106     * Calls {#performAction performAction(true)}.
107     * 
108     * @throws Exception
109     */
110    public void performUninstallAction() throws Exception
111    {
112        performAction(true);
113    }
114
115    /**
116     * Performs all defined actions.
117     * 
118     * @param uninstall An install/uninstall switch. If this is <tt>true</tt> only the uninstall
119     * actions, otherwise only the install actions are being performed.
120     * 
121     * @see #performInstallAction() for calling all install actions.
122     * @see #performUninstallAction() for calling all uninstall actions.
123     * 
124     * @throws Exception
125     */
126    public void performAction(boolean uninstall) throws Exception
127    {
128        if (verbose) System.out.println("Calling ANT with buildfile: " + buildFile);
129        SecurityManager oldsm = null;
130        if (!JavaEnvUtils.isJavaVersion("1.0") && !JavaEnvUtils.isJavaVersion("1.1"))
131            oldsm = System.getSecurityManager();
132        PrintStream err = System.err;
133        PrintStream out = System.out;
134        try
135        {
136            Project antProj = new Project();
137            antProj.setName("antcallproject");
138            antProj.addBuildListener(createLogger());
139            antProj.setInputHandler(new DefaultInputHandler());
140            antProj.setSystemProperties();
141            addProperties(antProj, getProperties());
142            addPropertiesFromPropertyFiles(antProj);
143            // TODO: propertyfiles, logFile
144            antProj.fireBuildStarted();
145            antProj.init();
146            List antcalls = new ArrayList();
147            List choosenTargets = (uninstall) ? uninstallTargets : targets;
148            if (choosenTargets.size() > 0)
149            {
150                Ant antcall = null;
151                for (int i = 0; i < choosenTargets.size(); i++)
152                {
153                    antcall = (Ant) antProj.createTask("ant");
154                    antcall.setAntfile(getBuildFile());
155                    antcall.setTarget((String) choosenTargets.get(i));
156                    antcalls.add(antcall);
157                }
158            }
159            Target target = new Target();
160            target.setName("calltarget");
161
162            for (int i = 0; i < antcalls.size(); i++)
163            {
164                target.addTask((Ant) antcalls.get(i));
165            }
166            antProj.addTarget(target);
167            System.setOut(new PrintStream(new DemuxOutputStream(antProj, false)));
168            System.setErr(new PrintStream(new DemuxOutputStream(antProj, true)));
169            antProj.executeTarget("calltarget");
170        }
171        finally
172        {
173            if (oldsm != null) System.setSecurityManager(oldsm);
174            System.setOut(out);
175            System.setErr(err);
176        }
177    }
178
179    /**
180     * Returns the build file.
181     * 
182     * @return the build file
183     */
184    public String getBuildFile()
185    {
186        return buildFile;
187    }
188
189    /**
190     * Sets the build file to be used to the given string.
191     * 
192     * @param buildFile build file path to be used
193     */
194    public void setBuildFile(String buildFile)
195    {
196        this.buildFile = buildFile;
197    }
198
199    /**
200     * Returns the current logfile path as string.
201     * 
202     * @return current logfile path
203     */
204    public String getLogFile()
205    {
206        return logFile;
207    }
208
209    /**
210     * Sets the logfile path to the given string.
211     * 
212     * @param logFile to be set
213     */
214    public void setLogFile(String logFile)
215    {
216        this.logFile = logFile;
217    }
218
219    /**
220     * Returns the property file paths as list of strings.
221     * 
222     * @return the property file paths
223     */
224    public List getPropertyFiles()
225    {
226        return propertyFiles;
227    }
228
229    /**
230     * Adds one property file path to the internal list of property file paths.
231     * 
232     * @param propertyFile to be added
233     */
234    public void addPropertyFile(String propertyFile)
235    {
236        this.propertyFiles.add(propertyFile);
237    }
238
239    /**
240     * Sets the property file path list to the given list. Old settings will be lost.
241     * 
242     * @param propertyFiles list of property file paths to be set
243     */
244    public void setPropertyFiles(List propertyFiles)
245    {
246        this.propertyFiles = propertyFiles;
247    }
248
249    /**
250     * Returns the properties.
251     * 
252     * @return the properties
253     */
254    public Properties getProperties()
255    {
256        return properties;
257    }
258
259    /**
260     * Sets the internal properties to the given properties. Old settings will be lost.
261     * 
262     * @param properties properties to be set
263     */
264    public void setProperties(Properties properties)
265    {
266        this.properties = properties;
267    }
268
269    /**
270     * Sets the given value to the property identified by the given name.
271     * 
272     * @param name key of the property
273     * @param value value to be used for the property
274     */
275    public void setProperty(String name, String value)
276    {
277        this.properties.put(name, value);
278    }
279
280    /**
281     * Returns the value for the property identified by the given name.
282     * 
283     * @param name name of the property
284     * @return value of the property
285     */
286    public String getProperty(String name)
287    {
288        return this.properties.getProperty(name);
289    }
290
291    /**
292     * Returns the quiet state.
293     * 
294     * @return quiet state
295     */
296    public boolean isQuiet()
297    {
298        return quiet;
299    }
300
301    /**
302     * Sets whether the associated ant task should be performed quiet or not.
303     * 
304     * @param quiet quiet state to set
305     */
306    public void setQuiet(boolean quiet)
307    {
308        this.quiet = quiet;
309    }
310
311    /**
312     * Returns the targets.
313     * 
314     * @return the targets
315     */
316    public List getTargets()
317    {
318        return targets;
319    }
320
321    /**
322     * Sets the targets which should be performed at installation time. Old settings are lost.
323     * 
324     * @param targets list of targets
325     */
326    public void setTargets(ArrayList targets)
327    {
328        this.targets = targets;
329    }
330
331    /**
332     * Adds the given target to the target list which should be performed at installation time.
333     * 
334     * @param target target to be add
335     */
336    public void addTarget(String target)
337    {
338        this.targets.add(target);
339    }
340
341    /**
342     * Returns the uninstaller targets.
343     * 
344     * @return the uninstaller targets
345     */
346    public List getUninstallTargets()
347    {
348        return uninstallTargets;
349    }
350
351    /**
352     * Sets the targets which should be performed at uninstallation time. Old settings are lost.
353     * 
354     * @param targets list of targets
355     */
356    public void setUninstallTargets(ArrayList targets)
357    {
358        this.uninstallTargets = targets;
359    }
360
361    /**
362     * Adds the given target to the target list which should be performed at uninstallation time.
363     * 
364     * @param target target to be add
365     */
366    public void addUninstallTarget(String target)
367    {
368        this.uninstallTargets.add(target);
369    }
370
371    /**
372     * Returns the verbose state.
373     * 
374     * @return verbose state
375     */
376    public boolean isVerbose()
377    {
378        return verbose;
379    }
380
381    /**
382     * Sets the verbose state.
383     * 
384     * @param verbose state to be set
385     */
386    public void setVerbose(boolean verbose)
387    {
388        this.verbose = verbose;
389    }
390
391    private BuildLogger createLogger()
392    {
393        int msgOutputLevel = 2;
394        if (verbose)
395            msgOutputLevel = 4;
396        else if (quiet) msgOutputLevel = 1;
397        BuildLogger logger = new DefaultLogger();
398        logger.setMessageOutputLevel(msgOutputLevel);
399        logger.setOutputPrintStream(System.out);
400        logger.setErrorPrintStream(System.err);
401        return logger;
402    }
403
404    private void addProperties(Project proj, Properties props)
405    {
406        if (proj == null) return;
407        if (props.size() > 0)
408        {
409            Iterator iter = props.keySet().iterator();
410            String key = null;
411            while (iter.hasNext())
412            {
413                key = (String) iter.next();
414                proj.setProperty(key, props.getProperty(key));
415            }
416        }
417    }
418
419    private void addPropertiesFromPropertyFiles(Project proj) throws Exception
420    {
421        if (proj == null) return;
422        Properties props = new Properties();
423        File pf = null;
424        FileInputStream fis = null;
425        try
426        {
427            for (int i = 0; i < propertyFiles.size(); i++)
428            {
429                pf = new File((String) propertyFiles.get(i));
430                if (pf.exists())
431                {
432                    fis = new FileInputStream(pf);
433                    props.load(fis);
434                    fis.close();
435                }
436                else
437                {
438                    throw new Exception("Required propertyfile " + pf
439                            + " for antcall doesn't exist.");
440                }
441            }
442        }
443        finally
444        {
445            if (fis != null) fis.close();
446        }
447        addProperties(proj, props);
448    }
449
450}