KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > izforge > izpack > event > RegistryInstallerListener


1 /*
2  * IzPack - Copyright 2001-2007 Julien Ponge, All Rights Reserved.
3  *
4  * http://www.izforge.com/izpack/
5  * http://developer.berlios.de/projects/izpack/
6  *
7  * Copyright 2004 Klaus Bartz
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */

21
22 package com.izforge.izpack.event;
23
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.StringTokenizer JavaDoc;
27 import java.util.Vector JavaDoc;
28
29 import net.n3.nanoxml.XMLElement;
30
31 import com.coi.tools.os.win.NativeLibException;
32 import com.izforge.izpack.Pack;
33 import com.izforge.izpack.installer.AutomatedInstallData;
34 import com.izforge.izpack.installer.UninstallData;
35 import com.izforge.izpack.installer.Unpacker;
36 import com.izforge.izpack.util.AbstractUIProgressHandler;
37 import com.izforge.izpack.util.SpecHelper;
38 import com.izforge.izpack.util.VariableSubstitutor;
39 import com.izforge.izpack.util.os.RegistryDefaultHandler;
40 import com.izforge.izpack.util.os.RegistryHandler;
41 import com.izforge.izpack.util.os.WrappedNativeLibException;
42
43 /**
44  * Installer custom action for handling registry entries on Windows. On Unix nothing will be done.
45  * The actions which should be performed are defined in a resource file named "RegistrySpec.xml".
46  * This resource should be declared in the installation definition file (install.xml), else an
47  * exception will be raised during execution of this custom action. The related DTD is
48  * appl/install/IzPack/resources/registry.dtd.
49  *
50  * @author Klaus Bartz
51  *
52  */

53 public class RegistryInstallerListener extends NativeInstallerListener
54 {
55
56     /** The name of the XML file that specifies the registry entries. */
57     private static final String JavaDoc SPEC_FILE_NAME = "RegistrySpec.xml";
58
59     private static final String JavaDoc REG_KEY = "key";
60
61     private static final String JavaDoc REG_VALUE = "value";
62
63     private static final String JavaDoc REG_ROOT = "root";
64
65     private static final String JavaDoc REG_BASENAME = "name";
66
67     private static final String JavaDoc REG_KEYPATH = "keypath";
68
69     private static final String JavaDoc REG_DWORD = "dword";
70
71     private static final String JavaDoc REG_STRING = "string";
72
73     private static final String JavaDoc REG_MULTI = "multi";
74
75     private static final String JavaDoc REG_BIN = "bin";
76
77     private static final String JavaDoc REG_DATA = "data";
78
79     private static final String JavaDoc REG_OVERRIDE = "override";
80
81     /**
82      * Default constructor.
83      */

84     public RegistryInstallerListener()
85     {
86         super(true);
87     }
88
89     /*
90      * (non-Javadoc)
91      *
92      * @see com.izforge.izpack.compiler.InstallerListener#beforePacks(com.izforge.izpack.installer.AutomatedInstallData,
93      * int, com.izforge.izpack.util.AbstractUIProgressHandler)
94      */

95     public void beforePacks(AutomatedInstallData idata, Integer JavaDoc npacks,
96             AbstractUIProgressHandler handler) throws Exception JavaDoc
97     {
98         super.beforePacks(idata, npacks, handler);
99         initializeRegistryHandler(idata);
100     }
101
102     /*
103      * (non-Javadoc)
104      *
105      * @see com.izforge.izpack.compiler.InstallerListener#afterPacks(com.izforge.izpack.installer.AutomatedInstallData,
106      * com.izforge.izpack.util.AbstractUIProgressHandler)
107      */

108     public void afterPacks(AutomatedInstallData idata, AbstractUIProgressHandler handler)
109             throws Exception JavaDoc
110     {
111         try
112         {
113             // Start logging
114
RegistryHandler rh = RegistryDefaultHandler.getInstance();
115             if (rh == null) return;
116             XMLElement uninstallerPack = null;
117             // No interrupt desired after writing registry entries.
118
Unpacker.setDiscardInterrupt(true);
119             rh.activateLogging();
120             if (getSpecHelper().getSpec() != null)
121             {
122                 VariableSubstitutor substitutor = new VariableSubstitutor(idata.getVariables());
123                 Iterator JavaDoc iter = idata.selectedPacks.iterator();
124                 // Get the special pack "UninstallStuff" which contains values
125
// for the uninstaller entry.
126
uninstallerPack = getSpecHelper().getPackForName("UninstallStuff");
127                 performPack(uninstallerPack, substitutor);
128
129                 // Now perform the selected packs.
130
while (iter != null && iter.hasNext())
131                 {
132                     // Resolve data for current pack.
133
XMLElement pack = getSpecHelper().getPackForName(((Pack) iter.next()).name);
134                     performPack(pack, substitutor);
135
136                 }
137             }
138             String JavaDoc uninstallSuffix = idata.getVariable("UninstallKeySuffix");
139             if (uninstallSuffix != null)
140             {
141                 rh.setUninstallName(rh.getUninstallName() + " " + uninstallSuffix);
142             }
143             // Generate uninstaller key automatically if not defined in spec.
144
if (uninstallerPack == null) rh.registerUninstallKey();
145             // Get the logging info from the registry class and put it into
146
// the uninstaller. The RegistryUninstallerListener loads that data
147
// and rewind the made entries.
148
// This is the common way to transport informations from an
149
// installer CustomAction to the corresponding uninstaller
150
// CustomAction.
151
List JavaDoc info = rh.getLoggingInfo();
152             if (info != null)
153                 UninstallData.getInstance().addAdditionalData("registryEntries", info);
154
155         }
156         catch (Exception JavaDoc e)
157         {
158             if (e instanceof NativeLibException)
159                 throw new WrappedNativeLibException(e);
160             else
161                 throw e;
162         }
163     }
164
165     /**
166      * Performs the registry settings for the given pack.
167      *
168      * @param pack XML elemtent which contains the registry settings for one pack
169      * @throws Exception
170      */

171     private void performPack(XMLElement pack, VariableSubstitutor substitutor) throws Exception JavaDoc
172     {
173         if (pack == null) return;
174         // Get all entries for registry settings.
175
Vector JavaDoc regEntries = pack.getChildren();
176         if (regEntries == null) return;
177         Iterator JavaDoc entriesIter = regEntries.iterator();
178         while (entriesIter != null && entriesIter.hasNext())
179         {
180             XMLElement regEntry = (XMLElement) entriesIter.next();
181             // Perform one registry entry.
182
String JavaDoc type = regEntry.getName();
183             if (type.equalsIgnoreCase(REG_KEY))
184             {
185                 performKeySetting(regEntry, substitutor);
186             }
187             else if (type.equalsIgnoreCase(REG_VALUE))
188             {
189                 performValueSetting(regEntry, substitutor);
190             }
191             else
192                 // No valid type.
193
getSpecHelper().parseError(regEntry,
194                         "Non-valid type of entry; only 'key' and 'value' are allowed.");
195
196         }
197
198     }
199
200     /**
201      * Perform the setting of one value.
202      *
203      * @param regEntry element which contains the description of the value to be set
204      * @param substitutor variable substitutor to be used for revising the regEntry contents
205      */

206     private void performValueSetting(XMLElement regEntry, VariableSubstitutor substitutor)
207             throws Exception JavaDoc
208     {
209         SpecHelper specHelper = getSpecHelper();
210         String JavaDoc name = specHelper.getRequiredAttribute(regEntry, REG_BASENAME);
211         name = substitutor.substitute(name, null);
212         String JavaDoc keypath = specHelper.getRequiredAttribute(regEntry, REG_KEYPATH);
213         keypath = substitutor.substitute(keypath, null);
214         String JavaDoc root = specHelper.getRequiredAttribute(regEntry, REG_ROOT);
215         int rootId = resolveRoot(regEntry, root, substitutor);
216
217         RegistryHandler rh = RegistryDefaultHandler.getInstance();
218         if (rh == null) return;
219
220         rh.setRoot(rootId);
221
222         String JavaDoc override = regEntry.getAttribute(REG_OVERRIDE, "true");
223         if (!"true".equalsIgnoreCase(override))
224         { // Do not set value if override is not true and the value exist.
225

226             if (rh.getValue(keypath, name, null) != null) return;
227         }
228
229         String JavaDoc value = regEntry.getAttribute(REG_DWORD);
230         if (value != null)
231         { // Value type is DWord; placeholder possible.
232
value = substitutor.substitute(value, null);
233             rh.setValue(keypath, name, Long.parseLong(value));
234             return;
235         }
236         value = regEntry.getAttribute(REG_STRING);
237         if (value != null)
238         { // Value type is string; placeholder possible.
239
value = substitutor.substitute(value, null);
240             rh.setValue(keypath, name, value);
241             return;
242         }
243         Vector JavaDoc values = regEntry.getChildrenNamed(REG_MULTI);
244         if (values != null && !values.isEmpty())
245         { // Value type is REG_MULTI_SZ; placeholder possible.
246
Iterator JavaDoc multiIter = values.iterator();
247             String JavaDoc[] multiString = new String JavaDoc[values.size()];
248             for (int i = 0; multiIter.hasNext(); ++i)
249             {
250                 XMLElement element = (XMLElement) multiIter.next();
251                 multiString[i] = specHelper.getRequiredAttribute(element, REG_DATA);
252                 multiString[i] = substitutor.substitute(multiString[i], null);
253             }
254             rh.setValue(keypath, name, multiString);
255             return;
256         }
257         values = regEntry.getChildrenNamed(REG_BIN);
258         if (values != null && !values.isEmpty())
259         { // Value type is REG_BINARY; placeholder possible or not ??? why not
260
// ...
261
Iterator JavaDoc multiIter = values.iterator();
262
263             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
264             for (int i = 0; multiIter.hasNext(); ++i)
265             {
266                 XMLElement element = (XMLElement) multiIter.next();
267                 String JavaDoc tmp = specHelper.getRequiredAttribute(element, REG_DATA);
268                 buf.append(tmp);
269                 if (!tmp.endsWith(",") && multiIter.hasNext()) buf.append(",");
270             }
271             byte[] bytes = extractBytes(regEntry, substitutor.substitute(buf.toString(), null));
272             rh.setValue(keypath, name, bytes);
273             return;
274         }
275         specHelper.parseError(regEntry, "No data found.");
276
277     }
278
279     private byte[] extractBytes(XMLElement element, String JavaDoc byteString) throws Exception JavaDoc
280     {
281         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(byteString, ",");
282         byte[] retval = new byte[st.countTokens()];
283         int i = 0;
284         while (st.hasMoreTokens())
285         {
286             byte value = 0;
287             String JavaDoc token = st.nextToken().trim();
288             try
289             { // Unfortenly byte is signed ...
290
int tval = Integer.parseInt(token, 16);
291                 if (tval < 0 || tval > 0xff)
292                     throw new NumberFormatException JavaDoc("Value out of range.");
293                 if (tval > 0x7f) tval -= 0x100;
294                 value = (byte) tval;
295             }
296             catch (NumberFormatException JavaDoc nfe)
297             {
298                 getSpecHelper()
299                         .parseError(element,
300                                 "Bad entry for REG_BINARY; a byte should be written as 2 digit hexvalue followed by a ','.");
301             }
302             retval[i++] = value;
303         }
304         return (retval);
305
306     }
307
308     /**
309      * Perform the setting of one key.
310      *
311      * @param regEntry element which contains the description of the key to be created
312      * @param substitutor variable substitutor to be used for revising the regEntry contents
313      */

314     private void performKeySetting(XMLElement regEntry, VariableSubstitutor substitutor)
315             throws Exception JavaDoc
316     {
317         String JavaDoc keypath = getSpecHelper().getRequiredAttribute(regEntry, REG_KEYPATH);
318         keypath = substitutor.substitute(keypath, null);
319         String JavaDoc root = getSpecHelper().getRequiredAttribute(regEntry, REG_ROOT);
320         int rootId = resolveRoot(regEntry, root, substitutor);
321         RegistryHandler rh = RegistryDefaultHandler.getInstance();
322         if (rh == null) return;
323         rh.setRoot(rootId);
324         if (!rh.keyExist(keypath)) rh.createKey(keypath);
325     }
326
327     private int resolveRoot(XMLElement regEntry, String JavaDoc root, VariableSubstitutor substitutor)
328             throws Exception JavaDoc
329     {
330         String JavaDoc root1 = substitutor.substitute(root, null);
331         Integer JavaDoc tmp = (Integer JavaDoc) RegistryHandler.ROOT_KEY_MAP.get(root1);
332         if (tmp != null) return (tmp.intValue());
333         getSpecHelper().parseError(regEntry, "Unknown value (" + root1 + ")for registry root.");
334         return 0;
335     }
336
337     private void initializeRegistryHandler(AutomatedInstallData idata) throws Exception JavaDoc
338     {
339         RegistryHandler rh = RegistryDefaultHandler.getInstance();
340         if (rh == null) return;
341         rh.verify(idata);
342         getSpecHelper().readSpec(SPEC_FILE_NAME);
343     }
344
345 }
346
Popular Tags