001/*
002 * $Id: RegistryHandler.java,v 1.6 2005/09/23 15:24:42 bartzkau Exp $
003 * IzPack - Copyright 2001-2005 Julien Ponge, All Rights Reserved.
004 * 
005 * http://www.izforge.com/izpack/
006 * http://developer.berlios.de/projects/izpack/
007 * 
008 * Copyright 2005 Klaus Bartz
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.util.os;
024
025import java.io.File;
026import java.io.FileOutputStream;
027import java.io.InputStream;
028import java.util.HashMap;
029import java.util.List;
030import java.util.Map;
031
032import com.coi.tools.os.win.NativeLibException;
033import com.coi.tools.os.win.RegDataContainer;
034import com.coi.tools.os.win.RegistryImpl;
035import com.izforge.izpack.installer.AutomatedInstallData;
036import com.izforge.izpack.installer.ResourceManager;
037import com.izforge.izpack.util.Debug;
038import com.izforge.izpack.util.OSClassHelper;
039
040/**
041 * This class represents a registry handler in a operating system independent way. OS specific
042 * subclasses are used to implement the necessary mapping from this generic API to the classes that
043 * reflect the system dependent AIP.
044 * 
045 * @author Klaus Bartz
046 * 
047 */
048public class RegistryHandler extends OSClassHelper
049{
050
051    public static final String UNINSTALL_ROOT = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
052
053    public static final Map ROOT_KEY_MAP = new HashMap();
054
055    protected String uninstallName = null;
056
057    private static final String UNINSTALLER_ICON = "UninstallerIcon";
058
059    private static RegistryHandler defaultHandler = null;
060    static
061    {
062        ROOT_KEY_MAP.put("HKCR", new Integer(RegistryImpl.HKEY_CLASSES_ROOT));
063        ROOT_KEY_MAP.put("HKEY_CLASSES_ROOT", new Integer(RegistryImpl.HKEY_CLASSES_ROOT));
064        ROOT_KEY_MAP.put("HKCU", new Integer(RegistryImpl.HKEY_CURRENT_USER));
065        ROOT_KEY_MAP.put("HKEY_CURRENT_USER", new Integer(RegistryImpl.HKEY_CURRENT_USER));
066        ROOT_KEY_MAP.put("HKLM", new Integer(RegistryImpl.HKEY_LOCAL_MACHINE));
067        ROOT_KEY_MAP.put("HKEY_LOCAL_MACHINE", new Integer(RegistryImpl.HKEY_LOCAL_MACHINE));
068        ROOT_KEY_MAP.put("HKU", new Integer(RegistryImpl.HKEY_USERS));
069        ROOT_KEY_MAP.put("HKEY_USERS", new Integer(RegistryImpl.HKEY_USERS));
070        ROOT_KEY_MAP.put("HKPD", new Integer(RegistryImpl.HKEY_PERFORMANCE_DATA));
071        ROOT_KEY_MAP.put("HKEY_PERFORMANCE_DATA", new Integer(RegistryImpl.HKEY_PERFORMANCE_DATA));
072        ROOT_KEY_MAP.put("HKCC", new Integer(RegistryImpl.HKEY_CURRENT_CONFIG));
073        ROOT_KEY_MAP.put("HKEY_CURRENT_CONFIG", new Integer(RegistryImpl.HKEY_CURRENT_CONFIG));
074        ROOT_KEY_MAP.put("HKDDS", new Integer(RegistryImpl.HKEY_DYN_DATA));
075        ROOT_KEY_MAP.put("HKEY_DYN_DATA", new Integer(RegistryImpl.HKEY_DYN_DATA));
076
077    }
078
079    /**
080     * Default constructor.
081     */
082    public RegistryHandler()
083    {
084        super();
085    }
086
087    /**
088     * Creates an registry handler which uses an oblect of the given class as worker.
089     * 
090     * @param className full qualified class name of the class which should be used as worker
091     */
092    public RegistryHandler(String className)
093    {
094        super(className);
095        setDefault();
096    }
097
098    /**
099     * Set this object as default handler if it is not done earlier.
100     */
101    private synchronized void setDefault()
102    {
103        if (defaultHandler == null) defaultHandler = this;
104    }
105
106    /**
107     * Sets the given contents to the given registry value. If a sub key or the registry value does
108     * not exist, it will be created. The return value is a String array which contains the names of
109     * the keys and values which are created. REG_SZ is used as registry value type.
110     * 
111     * @param key the registry key which should be used or created
112     * @param value the registry value into which the contents should be set
113     * @param contents the contents for the value
114     * @throws NativeLibException
115     */
116    public void setValue(String key, String value, String contents) throws NativeLibException
117    {
118        return;
119    }
120
121    public void setValue(String key, String value, String[] contents) throws NativeLibException
122    {
123        return;
124    }
125
126    /**
127     * Sets the given contents to the given registry value. If a sub key or the registry value does
128     * not exist, it will be created. The return value is a String array which contains the names of
129     * the keys and values which are created. REG_BINARY is used as registry value type.
130     * 
131     * @param key the registry key which should be used or created
132     * @param value the registry value into which the contents should be set
133     * @param contents the contents for the value
134     * @throws NativeLibException
135     */
136    public void setValue(String key, String value, byte[] contents) throws NativeLibException
137    {
138        return;
139    }
140
141    /**
142     * Sets the given contents to the given registry value. If a sub key or the registry value does
143     * not exist, it will be created. The return value is a String array which contains the names of
144     * the keys and values which are created. REG_DWORD is used as registry value type.
145     * 
146     * @param key the registry key which should be used or created
147     * @param value the registry value into which the contents should be set
148     * @param contents the contents for the value
149     * @throws NativeLibException
150     */
151    public void setValue(String key, String value, long contents) throws NativeLibException
152    {
153        return;
154    }
155
156    /**
157     * Returns the contents of the key/value pair if value exist, else the given default value.
158     * 
159     * @param key the registry key which should be used
160     * @param value the registry value from which the contents should be requested
161     * @param defaultVal value to be used if no value exist in the registry
162     * @return requested value if exist, else the default value
163     * @throws NativeLibException
164     */
165    public RegDataContainer getValue(String key, String value, RegDataContainer defaultVal) throws NativeLibException
166    {
167        return (null);
168    }
169
170    /**
171     * Returns whether a key exist or not.
172     * 
173     * @param key key to be evaluated
174     * @return whether a key exist or not
175     * @throws NativeLibException
176     */
177    public boolean keyExist(String key) throws NativeLibException
178    {
179        return (false);
180    }
181
182    /**
183     * Returns whether a the given value under the given key exist or not.
184     * 
185     * @param key key to be used as path for the value
186     * @param value value name to be evaluated
187     * @return whether a the given value under the given key exist or not
188     * @throws NativeLibException
189     */
190    public boolean valueExist(String key, String value) throws NativeLibException
191    {
192        return (false);
193    }
194
195    /**
196     * Returns all keys which are defined under the given key.
197     * 
198     * @param key key to be used as path for the sub keys
199     * @return all keys which are defined under the given key
200     * @throws NativeLibException
201     */
202    public String[] getSubkeys(String key) throws NativeLibException
203    {
204        return (null);
205    }
206
207    /**
208     * Returns all value names which are defined under the given key.
209     * 
210     * @param key key to be used as path for the value names
211     * @return all value names which are defined under the given key
212     * @throws NativeLibException
213     */
214    public String[] getValueNames(String key) throws NativeLibException
215    {
216        return (null);
217    }
218
219    /**
220     * Returns the contents of the key/value pair if value exist, else an exception is raised.
221     * 
222     * @param key the registry key which should be used
223     * @param value the registry value from which the contents should be requested
224     * @return requested value if exist, else an exception
225     * @throws NativeLibException
226     */
227    public RegDataContainer getValue(String key, String value) throws NativeLibException
228    {
229        return (null);
230    }
231
232    /**
233     * Creates the given key in the registry.
234     * 
235     * @param key key to be created
236     * @throws NativeLibException
237     */
238    public void createKey(String key) throws NativeLibException
239    {
240        return;
241    }
242    
243    /**
244     * Deletes the given key if exist, else throws an exception.
245     * @param key key to be deleted
246     * @throws NativeLibException
247     */
248    public void deleteKey( String key) throws NativeLibException
249    {
250        return;
251    }
252
253    /**
254     * Deletes a key under the current root if it is empty, else do nothing.
255     * 
256     * @param key key to be deleted
257     * @throws NativeLibException
258     */
259    public void deleteKeyIfEmpty(String key) throws NativeLibException
260    {
261        return;
262    }
263    
264    /**
265     * Deletes a value.
266     * 
267     * @param key key of the value which should be deleted
268     * @param value value name to be deleted
269     * @throws NativeLibException
270     */
271    public void deleteValue(String key, String value) throws NativeLibException
272    {
273        return;
274    }
275
276    /**
277     * Sets the root for the next registry access.
278     * 
279     * @param i an integer which refers to a HKEY
280     * @throws NativeLibException
281     */
282    public void setRoot(int i) throws NativeLibException
283    {
284        return;
285    }
286
287    /**
288     * Return the root as integer (HKEY_xxx).
289     * 
290     * @return the root as integer
291     * @throws NativeLibException
292     */
293    public int getRoot() throws NativeLibException
294    {
295        return (0);
296    }
297
298    /**
299     * Activates logging of registry changes.
300     * 
301     * @throws NativeLibException
302     */
303    public void activateLogging() throws NativeLibException
304    {
305        return;
306    }
307
308    /**
309     * Suspends logging of registry changes.
310     * 
311     * @throws NativeLibException
312     */
313    public void suspendLogging() throws NativeLibException
314    {
315        return;
316    }
317
318    /**
319     * Resets logging of registry changes.
320     * 
321     * @throws NativeLibException
322     */
323    public void resetLogging() throws NativeLibException
324    {
325        return;
326    }
327
328    public List getLoggingInfo() throws NativeLibException
329    {
330        return (null);
331    }
332
333    public void setLoggingInfo(List info) throws NativeLibException
334    {
335        return;
336    }
337
338    public void addLoggingInfo(List info) throws NativeLibException
339    {
340        return;
341    }
342
343    public void rewind() throws NativeLibException
344    {
345        return;
346    }
347
348    public String getUninstallName()
349    {
350        if (uninstallName != null) return (uninstallName);
351        if (installdata == null) return (null);
352        return (installdata.getVariable("APP_NAME") + " " + installdata.getVariable("APP_VER"));
353    }
354
355    public boolean isProductRegistered() throws NativeLibException
356    {
357        String uninstallName = getUninstallName();
358        if (uninstallName == null) return (false);
359        String keyName = UNINSTALL_ROOT + uninstallName;
360        int oldVal = getRoot();
361        setRoot(RegistryImpl.HKEY_LOCAL_MACHINE);
362        boolean retval = keyExist(keyName);
363        setRoot(oldVal);
364        return (retval);
365    }
366
367    public void setUninstallName(String name)
368    {
369        uninstallName = name;
370    }
371
372    public void registerUninstallKey() throws NativeLibException
373    {
374        String uninstallName = getUninstallName();
375        if (uninstallName == null) return;
376        String keyName = UNINSTALL_ROOT + uninstallName;
377        String cmd = "\"" + installdata.getVariable("JAVA_HOME") + "\\bin\\javaw.exe\" -jar \""
378                + installdata.getVariable("INSTALL_PATH") + "\\uninstaller\\uninstaller.jar\"";
379
380        int oldVal = getRoot();
381        setRoot(RegistryImpl.HKEY_LOCAL_MACHINE);
382        setValue(keyName, "DisplayName", uninstallName);
383        setValue(keyName, "UninstallString", cmd);
384        // Try to write the uninstaller icon out.
385        try
386        {
387            InputStream input = ResourceManager.getInstance().getInputStream(UNINSTALLER_ICON);
388            String iconPath = installdata.getVariable("INSTALL_PATH") + File.separator
389                    + "Uninstaller" + File.separator + "UninstallerIcon.ico";
390            FileOutputStream out = new FileOutputStream(iconPath);
391            byte[] buffer = new byte[5120];
392            long bytesCopied = 0;
393            int bytesInBuffer;
394            while ((bytesInBuffer = input.read(buffer)) != -1)
395            {
396                out.write(buffer, 0, bytesInBuffer);
397                bytesCopied += bytesInBuffer;
398            }
399            input.close();
400            out.close();
401            setValue(keyName, "DisplayIcon", iconPath);
402        }
403        catch (Exception exception)
404        { // May be no icon resource defined; ignore it
405            Debug.trace(exception);
406        }
407        setRoot(oldVal);
408    }
409
410    /**
411     * @param idata
412     */
413    public boolean verify(AutomatedInstallData idata) throws Exception
414    {
415        super.verify(idata);
416        return (true);
417
418    }
419
420    /**
421     * Returns whether an action with this handler should be performed or not.
422     * 
423     * @return always true
424     */
425    public boolean doPerform()
426    {
427        return true;
428    }
429
430    /**
431     * Returns the default handler which is the first created registry handler.
432     * 
433     * @return Returns the default handler.
434     */
435    public RegistryHandler getDefaultHandler()
436    {
437        return defaultHandler;
438    }
439
440}