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.util.ArrayList;
026import java.util.HashMap;
027import java.util.Iterator;
028import java.util.Vector;
029
030import net.n3.nanoxml.XMLElement;
031
032import com.izforge.izpack.Pack;
033import com.izforge.izpack.installer.AutomatedInstallData;
034import com.izforge.izpack.installer.InstallerException;
035import com.izforge.izpack.installer.UninstallData;
036import com.izforge.izpack.util.AbstractUIProgressHandler;
037import com.izforge.izpack.util.Debug;
038import com.izforge.izpack.util.ExtendedUIProgressHandler;
039import com.izforge.izpack.util.SpecHelper;
040import com.izforge.izpack.util.VariableSubstitutor;
041
042/**
043 * Installer listener for performing ANT actions. The definition what should be done will be made in
044 * a specification file which is referenced by the resource id "AntActionsSpec.xml". There should be
045 * an entry in the install.xml file in the sub ELEMENT "res" of ELEMENT "resources" which references
046 * it. The specification of the xml file is done in the DTD antaction.dtd. The xml file specifies,
047 * for what pack what ant call should be performed at what time of installation.
048 * 
049 * @author Thomas Guenter
050 * @author Klaus Bartz
051 */
052public class AntActionInstallerListener extends SimpleInstallerListener
053{
054
055    // ------------------------------------------------------------------------
056    // Constant Definitions
057    // ------------------------------------------------------------------------
058    // --------String constants for parsing the XML specification ------------
059    // -------- see class AntAction -----------------------------------------
060    /** Name of the specification file */
061    public static final String SPEC_FILE_NAME = "AntActionsSpec.xml";
062
063    private HashMap actions = null;
064
065    private ArrayList uninstActions = null;
066
067    /**
068     * Default constructor
069     */
070    public AntActionInstallerListener()
071    {
072        super(true);
073        actions = new HashMap();
074        uninstActions = new ArrayList();
075    }
076
077    /**
078     * Returns the actions map.
079     * 
080     * @return the actions map
081     */
082    public HashMap getActions()
083    {
084        return (actions);
085    }
086
087    /*
088     * (non-Javadoc)
089     * 
090     * @see com.izforge.izpack.installer.InstallerListener#beforePacks(com.izforge.izpack.installer.AutomatedInstallData,
091     * java.lang.Integer, com.izforge.izpack.util.AbstractUIProgressHandler)
092     */
093    public void beforePacks(AutomatedInstallData idata, Integer npacks,
094            AbstractUIProgressHandler handler) throws Exception
095    {
096        super.beforePacks(idata, npacks, handler);
097
098        getSpecHelper().readSpec(SPEC_FILE_NAME, new VariableSubstitutor(idata.getVariables()));
099
100        if (getSpecHelper().getSpec() == null) return;
101
102        // Selected packs.
103        Iterator iter = idata.selectedPacks.iterator();
104        Pack p = null;
105        while (iter != null && iter.hasNext())
106        {
107            p = (Pack) iter.next();
108
109            // Resolve data for current pack.
110            XMLElement pack = getSpecHelper().getPackForName(p.name);
111            if (pack == null) continue;
112
113            // Prepare the action cache
114            HashMap packActions = new HashMap();
115            packActions.put(ActionBase.BEFOREPACK, new ArrayList());
116            packActions.put(ActionBase.AFTERPACK, new ArrayList());
117            packActions.put(ActionBase.BEFOREPACKS, new ArrayList());
118            packActions.put(ActionBase.AFTERPACKS, new ArrayList());
119
120            // Get all entries for antcalls.
121            Vector antCallEntries = pack.getChildrenNamed(AntAction.ANTCALL);
122            if (antCallEntries != null && antCallEntries.size() >= 1)
123            {
124                Iterator entriesIter = antCallEntries.iterator();
125                while (entriesIter != null && entriesIter.hasNext())
126                {
127                    AntAction act = readAntCall((XMLElement) entriesIter.next());
128                    if (act != null)
129                    {
130                        ((ArrayList) packActions.get(act.getOrder())).add(act);
131                    }
132                }
133                // Set for progress bar interaction.
134                if (((ArrayList) packActions.get(ActionBase.AFTERPACKS)).size() > 0)
135                    this.setProgressBarCaller();
136            }
137
138            actions.put(p.name, packActions);
139        }
140        iter = idata.availablePacks.iterator();
141        while (iter.hasNext())
142        {
143            String currentPack = ((Pack) iter.next()).name;
144            performAllActions(currentPack, ActionBase.BEFOREPACKS, null);
145        }
146    }
147
148    /*
149     * (non-Javadoc)
150     * 
151     * @see com.izforge.izpack.installer.InstallerListener#beforePack(com.izforge.izpack.Pack,
152     * java.lang.Integer, com.izforge.izpack.util.AbstractUIProgressHandler)
153     */
154    public void beforePack(Pack pack, Integer i, AbstractUIProgressHandler handler)
155            throws Exception
156    {
157        performAllActions(pack.name, ActionBase.BEFOREPACK, handler);
158    }
159
160    /*
161     * (non-Javadoc)
162     * 
163     * @see com.izforge.izpack.installer.InstallerListener#afterPack(com.izforge.izpack.Pack,
164     * java.lang.Integer, com.izforge.izpack.util.AbstractUIProgressHandler)
165     */
166    public void afterPack(Pack pack, Integer i, AbstractUIProgressHandler handler) throws Exception
167    {
168        performAllActions(pack.name, ActionBase.AFTERPACK, handler);
169    }
170
171    /*
172     * (non-Javadoc)
173     * 
174     * @see com.izforge.izpack.compiler.InstallerListener#afterPacks(com.izforge.izpack.installer.AutomatedInstallData,
175     * com.izforge.izpack.util.AbstractUIProgressHandler)
176     */
177    public void afterPacks(AutomatedInstallData idata, AbstractUIProgressHandler handler)
178            throws Exception
179    {
180        if (informProgressBar())
181        {
182            handler.nextStep(getMsg("AntAction.pack"), getProgressBarCallerId(), getActionCount(
183                    idata, ActionBase.AFTERPACKS));
184        }
185        Iterator iter = idata.selectedPacks.iterator();
186        while (iter.hasNext())
187        {
188            String currentPack = ((Pack) iter.next()).name;
189            performAllActions(currentPack, ActionBase.AFTERPACKS, handler);
190        }
191        if (uninstActions.size() > 0)
192        {
193            UninstallData.getInstance().addAdditionalData("antActions", uninstActions);
194        }
195    }
196
197    private int getActionCount(AutomatedInstallData idata, String order)
198    {
199        int retval = 0;
200        Iterator iter = idata.selectedPacks.iterator();
201        while (iter.hasNext())
202        {
203            String currentPack = ((Pack) iter.next()).name;
204            ArrayList actList = getActions(currentPack, order);
205            if (actList != null) retval += actList.size();
206        }
207        return (retval);
208    }
209
210    /**
211     * Returns the defined actions for the given pack in the requested order.
212     * 
213     * @param packName name of the pack for which the actions should be returned
214     * @param order order to be used; valid are <i>beforepack</i> and <i>afterpack</i>
215     * @return a list which contains all defined actions for the given pack and order
216     */
217    // -------------------------------------------------------
218    protected ArrayList getActions(String packName, String order)
219    {
220        if (actions == null) return null;
221
222        HashMap packActions = (HashMap) actions.get(packName);
223        if (packActions == null || packActions.size() == 0) return null;
224
225        return (ArrayList) packActions.get(order);
226    }
227
228    /**
229     * Performs all actions which are defined for the given pack and order.
230     * 
231     * @param packName name of the pack for which the actions should be performed
232     * @param order order to be used; valid are <i>beforepack</i> and <i>afterpack</i>
233     * @throws InstallerException
234     */
235    private void performAllActions(String packName, String order, AbstractUIProgressHandler handler)
236            throws InstallerException
237    {
238        ArrayList actList = getActions(packName, order);
239        if (actList == null || actList.size() == 0) return;
240
241        Debug.trace("******* Executing all " + order + " actions of " + packName + " ...");
242        for (int i = 0; i < actList.size(); i++)
243        {
244            AntAction act = (AntAction) actList.get(i);
245            // Inform progress bar if needed. Works only
246            // on AFTER_PACKS
247            if (informProgressBar() && handler != null
248                    && handler instanceof ExtendedUIProgressHandler
249                    && order.equals(ActionBase.AFTERPACKS))
250            {
251                ((ExtendedUIProgressHandler) handler)
252                        .progress((act.getMessageID() != null) ? getMsg(act.getMessageID()) : "");
253            }
254            try
255            {
256                act.performInstallAction();
257            }
258            catch (Exception e)
259            {
260                throw new InstallerException(e);
261            }
262            if (act.getUninstallTargets().size() > 0) uninstActions.add(act);
263        }
264    }
265
266    /**
267     * Returns an ant call which is defined in the given XML element.
268     * 
269     * @param el XML element which contains the description of an ant call
270     * @return an ant call which is defined in the given XML element
271     * @throws InstallerException
272     */
273    private AntAction readAntCall(XMLElement el) throws InstallerException
274    {
275        if (el == null) return null;
276        SpecHelper spec = getSpecHelper();
277        AntAction act = new AntAction();
278        try
279        {
280            act.setOrder(spec.getRequiredAttribute(el, ActionBase.ORDER));
281            act.setUninstallOrder(el.getAttribute(ActionBase.UNINSTALL_ORDER,
282                    ActionBase.BEFOREDELETION));
283        }
284        catch (Exception e)
285        {
286            throw new InstallerException(e);
287        }
288
289        act.setQuiet(spec.isAttributeYes(el, ActionBase.QUIET, false));
290        act.setVerbose(spec.isAttributeYes(el, ActionBase.VERBOSE, false));
291        act.setBuildFile(spec.getRequiredAttribute(el, ActionBase.BUILDFILE));
292        String str = el.getAttribute(ActionBase.LOGFILE);
293        if (str != null)
294        {
295            act.setLogFile(str);
296        }
297        String msgId = el.getAttribute(ActionBase.MESSAGEID);
298        if (msgId != null && msgId.length() > 0) act.setMessageID(msgId);
299
300        // read propertyfiles
301        Iterator iter = el.getChildrenNamed(ActionBase.PROPERTYFILE).iterator();
302        while (iter.hasNext())
303        {
304            XMLElement propEl = (XMLElement) iter.next();
305            act.addPropertyFile(spec.getRequiredAttribute(propEl, ActionBase.PATH));
306        }
307
308        // read properties
309        iter = el.getChildrenNamed(ActionBase.PROPERTY).iterator();
310        while (iter.hasNext())
311        {
312            XMLElement propEl = (XMLElement) iter.next();
313            act.setProperty(spec.getRequiredAttribute(propEl, ActionBase.NAME), spec
314                    .getRequiredAttribute(propEl, ActionBase.VALUE));
315        }
316
317        // read targets
318        iter = el.getChildrenNamed(ActionBase.TARGET).iterator();
319        while (iter.hasNext())
320        {
321            XMLElement targEl = (XMLElement) iter.next();
322            act.addTarget(spec.getRequiredAttribute(targEl, ActionBase.NAME));
323        }
324
325        // read uninstall rules
326        iter = el.getChildrenNamed(ActionBase.UNINSTALL_TARGET).iterator();
327        while (iter.hasNext())
328        {
329            XMLElement utargEl = (XMLElement) iter.next();
330            act.addUninstallTarget(spec.getRequiredAttribute(utargEl, ActionBase.NAME));
331        }
332
333        return act;
334    }
335
336}