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 2005 Klaus Bartz
008 *
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *     http://www.apache.org/licenses/LICENSE-2.0
014 *     
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 */
021
022package com.coi.tools.os.win;
023
024import java.io.Serializable;
025
026/**
027 * <p>
028 * Data container for Windows registry values. Windows registry values can contain different data
029 * types. It is not possible to map they all to one Java type. Therefore this class contains the
030 * different container types.
031 * </p>
032 * 
033 * @author Klaus Bartz
034 * 
035 */
036public class RegDataContainer implements Cloneable, Serializable
037{
038
039    private static final long serialVersionUID = 3979265850388066865L;
040
041    /*
042     * Registry value types, extracted from winnt.h
043     */
044    public static final int REG_NONE = 0; // No value type
045
046    public static final int REG_SZ = 1; // Unicode nul terminated string
047
048    public static final int REG_EXPAND_SZ = 2; // Unicode nul terminated string
049
050    // (with environment variable references)
051    public static final int REG_BINARY = 3; // Free form binary
052
053    public static final int REG_DWORD = 4; // 32-bit number
054
055    public static final int REG_LINK = 6; // Symbolic Link (unicode)
056
057    public static final int REG_MULTI_SZ = 7; // Multiple Unicode strings
058
059    private static final int[] VALID_TYPES = { 0, 1, 2, 3, 4, 6, 7};
060
061    private long dwordData = 0;
062
063    private String stringData = null;
064
065    private String[] multiStringData = null;
066
067    private byte[] binData = null;
068
069    private int type = 0;
070
071    /**
072     * Default constructor.
073     */
074    public RegDataContainer()
075    {
076        super();
077    }
078
079    /**
080     * Creates a RegDataContainer for a special type The data self is not set. Valid types are
081     * 
082     * @param type
083     * @throws IllegalArgumentException if the type is not valid
084     */
085    public RegDataContainer(int type) throws IllegalArgumentException
086    {
087        super();
088        if (!isValidType(type)) throw new IllegalArgumentException("Type is not valid");
089
090        this.type = type;
091    }
092
093    /**
094     * Creates a RegDataContainer for type REG_DWORD with the given data
095     * 
096     * @param data data which should be used with this object
097     */
098    public RegDataContainer(long data)
099    {
100        super();
101        type = REG_DWORD;
102        dwordData = data;
103    }
104
105    /**
106     * Creates a RegDataContainer for type REG_SZ with the given data
107     * 
108     * @param data data which should be used with this object
109     */
110    public RegDataContainer(String data)
111    {
112        super();
113        type = REG_SZ;
114        stringData = data;
115    }
116
117    /**
118     * Creates a RegDataContainer for type REG_MULTI_SZ with the given data
119     * 
120     * @param data data which should be used with this object
121     */
122    public RegDataContainer(String[] data)
123    {
124        super();
125        type = REG_MULTI_SZ;
126        multiStringData = data;
127    }
128
129    /**
130     * Creates a RegDataContainer for type REG_BINARY with the given data
131     * 
132     * @param data data which should be used with this object
133     */
134    public RegDataContainer(byte[] data)
135    {
136        super();
137        type = REG_BINARY;
138        binData = data;
139    }
140
141    /**
142     * Returns the binary data of this container. It will be contain only data, if the type of this
143     * object is REG_BINARY.
144     * 
145     * @return binary data
146     */
147    public byte[] getBinData()
148    {
149        return binData;
150    }
151
152    /**
153     * Returns the dword data of this container. It will be contain only data, if the type of this
154     * object is REG_DWORD.
155     * 
156     * @return the dword data
157     */
158    public long getDwordData()
159    {
160        return dwordData;
161    }
162
163    /**
164     * Returns the multi string data as string array of this container. It will be contain only
165     * data, if the type of this object is REG_REG_MULTI_SZ.
166     * 
167     * @return the multi string data
168     */
169    public String[] getMultiStringData()
170    {
171        return multiStringData;
172    }
173
174    /**
175     * Returns the string data of this container. It will be contain only data, if the type of this
176     * object is REG_REG_SZ.
177     * 
178     * @return the string data
179     */
180    public String getStringData()
181    {
182        return stringData;
183    }
184
185    /**
186     * Returns the data type handled by this object.
187     * 
188     * @return the data type handled by this object
189     */
190    public int getType()
191    {
192        return type;
193    }
194
195    /**
196     * Sets the binary data to the given byte array.
197     * 
198     * @param bytes data to be set
199     */
200    public void setBinData(byte[] bytes)
201    {
202        binData = bytes;
203    }
204
205    /**
206     * Sets the dword data to the given value.
207     * 
208     * @param i data to be set
209     */
210    public void setDwordData(long i)
211    {
212        dwordData = i;
213    }
214
215    /**
216     * Sets the multi string data to the given string array.
217     * 
218     * @param strings data to be set
219     */
220    public void setMultiStringData(String[] strings)
221    {
222        multiStringData = strings;
223    }
224
225    /**
226     * Sets the string data to the given value.
227     * 
228     * @param string data to be set
229     */
230    public void setStringData(String string)
231    {
232        stringData = string;
233    }
234
235    /**
236     * Sets the type.
237     * 
238     * @param i type to be set
239     */
240    public void setType(int i)
241    {
242        type = i;
243    }
244
245    /**
246     * Verifies whether the given int represents a valid type or not.
247     * 
248     * @param type value to be verified
249     * @return whether the given int represents a valid type or not
250     */
251    public boolean isValidType(int type)
252    {
253        for (int i = 0; i < VALID_TYPES.length; ++i)
254            if (type == VALID_TYPES[i]) return (true);
255        return (false);
256
257    }
258
259    /**
260     * Returns the contained data depending to the type. Dword data are transformed from long to
261     * Long.
262     * 
263     * @return the contained data
264     */
265    public Object getDataAsObject()
266    {
267        switch (type)
268        {
269        case REG_SZ:
270        case REG_EXPAND_SZ:
271            return (getStringData());
272        case REG_BINARY:
273            return (getBinData());
274        case REG_DWORD:
275            return (new Long(getDwordData()));
276        case REG_MULTI_SZ:
277            return (getMultiStringData());
278        default:
279            return (null);
280        }
281    }
282
283    public Object clone() throws CloneNotSupportedException
284    {
285        RegDataContainer retval = (RegDataContainer) super.clone();
286        if (multiStringData != null)
287        {
288            retval.multiStringData = new String[multiStringData.length];
289            System.arraycopy(multiStringData, 0, retval.multiStringData, 0, multiStringData.length);
290        }
291        if (binData != null)
292        {
293            retval.binData = new byte[binData.length];
294            System.arraycopy(binData, 0, retval.binData, 0, binData.length);
295        }
296        return (retval);
297    }
298
299    public boolean equals(Object anObject)
300    {
301        if (this == anObject) return (true);
302        if (anObject instanceof RegDataContainer)
303        {
304            RegDataContainer other = (RegDataContainer) anObject;
305            if (other.type != type) return (false);
306            switch (type)
307            {
308            case REG_DWORD:
309                return (other.dwordData == dwordData);
310            case REG_SZ:
311            case REG_EXPAND_SZ:
312                if (stringData == null) return (other.stringData == null);
313                return (stringData.equals(other.stringData));
314            case REG_BINARY:
315                if (binData == null) return (other.binData == null);
316                if (other.binData != null && binData.length == other.binData.length)
317                {
318                    for (int i = 0; i < binData.length; ++i)
319                    {
320                        if (binData[i] != other.binData[i]) return (false);
321                    }
322                    return (true);
323                }
324                return (false);
325            case REG_MULTI_SZ:
326                if (multiStringData == null) return (other.multiStringData == null);
327                if (other.multiStringData != null
328                        && multiStringData.length == other.multiStringData.length)
329                {
330                    for (int i = 0; i < multiStringData.length; ++i)
331                    {
332                        if (multiStringData[i] != null)
333                        {
334                            if (!multiStringData[i].equals(other.multiStringData[i]))
335                                return (false);
336                        }
337                        else if (other.multiStringData[i] == null) return (false);
338                    }
339                    return (true);
340                }
341                return (false);
342            }
343        }
344        return (false);
345    }
346
347}