1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 package util;
29 
30 // access the implementations via names
31 import com.sun.star.uno.UnoRuntime;
32 import java.io.PrintWriter ;
33 
34 import com.sun.star.registry.XRegistryKey ;
35 import com.sun.star.registry.XSimpleRegistry ;
36 import com.sun.star.registry.RegistryKeyType ;
37 import com.sun.star.registry.RegistryValueType ;
38 import com.sun.star.registry.InvalidRegistryException ;
39 import com.sun.star.lang.XMultiServiceFactory ;
40 import com.sun.star.uno.Exception;
41 
42 public class RegistryTools {
43 
44 	/**
45 	* Creates 'com.sun.star.registry.SimpleRegistry'
46 	* service.
47 	* @param xMSF Multiservice factory.
48 	* @return Service created.
49 	*/
50 	public static XSimpleRegistry createRegistryService
51 		(XMultiServiceFactory xMSF) throws com.sun.star.uno.Exception {
52 
53         Object oInterface = xMSF.createInstance
54         	("com.sun.star.registry.SimpleRegistry");
55         return (XSimpleRegistry) UnoRuntime.queryInterface (
56         	XSimpleRegistry.class, oInterface) ;
57     }
58 
59 	/**
60 	* Opens registry file for reading/writing. If file doesn't
61 	* exist a new one created.
62 	* @param file Registry file name.
63 	* @param xMSF Multiservice factory.
64 	* @return Opened registry.
65 	*/
66     public static XSimpleRegistry openRegistry
67     	(String file, XMultiServiceFactory xMSF)
68     	throws com.sun.star.uno.Exception {
69 
70     	XSimpleRegistry reg = createRegistryService(xMSF) ;
71 
72     	reg.open(file, false, true) ;
73 
74     	return reg ;
75     }
76 
77 	/**
78 	* Compares two registry keys, their names, value
79 	* types and values.
80 	* return <code>true</code> if key names, value types
81 	* and values are equal, else returns <code>false</code>.
82 	*/
83 	public static boolean compareKeys
84 		(XRegistryKey key1, XRegistryKey key2) {
85 
86 		if (key1 == null || key2 == null ||
87 			!key1.isValid() || !key2.isValid())
88 
89 			return false ;
90 
91 		String keyName1 = getShortKeyName(key1.getKeyName()) ;
92 		String keyName2 = getShortKeyName(key2.getKeyName()) ;
93 
94 		if (!keyName1.equals(keyName2)) return false ;
95 
96 		try {
97 			if (key1.getValueType() != key2.getValueType()) return false ;
98 		} catch (InvalidRegistryException e) {
99 			return false ;
100 		}
101 
102 		RegistryValueType type ;
103 		try {
104 			type = key1.getValueType() ;
105 
106 			if (type.equals(RegistryValueType.ASCII)) {
107 				if (!key1.getAsciiValue().equals(key2.getAsciiValue()))
108 					return false ;
109 			} else
110 			if (type.equals(RegistryValueType.STRING)) {
111 				if (!key1.getStringValue().equals(key2.getStringValue()))
112 					return false ;
113 			} else
114 			if (type.equals(RegistryValueType.LONG)) {
115 				if (key1.getLongValue() != key2.getLongValue())
116 					return false ;
117 			} else
118 			if (type.equals(RegistryValueType.BINARY)) {
119 				byte[] bin1 = key1.getBinaryValue() ;
120 				byte[] bin2 = key2.getBinaryValue() ;
121 				if (bin1.length != bin2.length)
122 					return false ;
123 				for (int i = 0; i < bin1.length; i++)
124 					if (bin1[i] != bin2[i]) return false ;
125 			} else
126 			if (type.equals(RegistryValueType.ASCIILIST)) {
127 				String[] list1 = key1.getAsciiListValue() ;
128 				String[] list2 = key2.getAsciiListValue() ;
129 				if (list1.length != list2.length)
130 					return false ;
131 				for (int i = 0; i < list1.length; i++)
132 					if (!list1[i].equals(list2[i])) return false ;
133 			} else
134 			if (type.equals(RegistryValueType.STRINGLIST)) {
135 				String[] list1 = key1.getStringListValue() ;
136 				String[] list2 = key2.getStringListValue() ;
137 				if (list1.length != list2.length)
138 					return false ;
139 				for (int i = 0; i < list1.length; i++)
140 					if (!list1[i].equals(list2[i])) return false ;
141 			} else
142 			if (type.equals(RegistryValueType.LONGLIST)) {
143 				int[] list1 = key1.getLongListValue() ;
144 				int[] list2 = key2.getLongListValue() ;
145 				if (list1.length != list2.length)
146 					return false ;
147 				for (int i = 0; i < list1.length; i++)
148 					if (list1[i] != list2[i]) return false ;
149 			}
150 		} catch (Exception e) {
151 			return false ;
152 		}
153 
154 		return true ;
155 	}
156 
157 	/**
158 	* Gets name of the key relative to its parent.
159 	* For example if full name of key is '/key1/subkey'
160 	* short key name is 'subkey'
161 	* @param keyName Full key name.
162 	* @return Short key name.
163 	*/
164 	public static String getShortKeyName(String keyName) {
165 		if (keyName == null) return null ;
166 		int idx = keyName.lastIndexOf("/") ;
167 		if (idx < 0) return keyName ;
168 		else return keyName.substring(idx + 1) ;
169 	}
170 
171 	/**
172 	* Compare all child keys.
173 	* @param compareRoot If <code>true</code> method also
174 	* compare root keys, if <code>false</code> it begins recursive
175 	* comparing from children of root keys.
176 	* @return <code>true</code> if keys and their sub keys are equal.
177 	*/
178 	protected static boolean compareKeyTrees
179 		(XRegistryKey tree1, XRegistryKey tree2, boolean compareRoot) {
180 
181 		if (compareRoot && !compareKeys(tree1, tree2)) return false ;
182 
183 		try {
184 			String[] keyNames1 = tree1.getKeyNames() ;
185 			String[] keyNames2 = tree2.getKeyNames() ;
186 
187 			if (keyNames1 == null && keyNames2 == null) return true ;
188 
189 			if (keyNames1 == null || keyNames2 == null ||
190 				keyNames2.length != keyNames1.length)
191 				return false ;
192 
193 			for (int i = 0; i < keyNames1.length; i++) {
194 
195 				String keyName = getShortKeyName(keyNames1[i]) ;
196 				XRegistryKey key2 = tree2.openKey(keyName) ;
197 
198 				if (key2 == null)
199 				// key with the same name doesn't exist in the second tree
200 					return false ;
201 
202 				if (!tree1.getKeyType(keyName).equals(
203 					 tree2.getKeyType(keyName)))
204 					return false ;
205 
206 				if (tree1.getKeyType(keyName).equals(
207 					RegistryKeyType.LINK)) {
208 
209 					if (!getShortKeyName(tree1.getLinkTarget(keyName)).equals(
210 						getShortKeyName(tree2.getLinkTarget(keyName))))
211 
212 						return false ;
213 				} else {
214 
215 					if (compareKeyTrees(tree1.openKey(keyName),
216 						  tree2.openKey(keyName), true) == false) return false ;
217 				}
218 			}
219 		} catch (InvalidRegistryException e) {
220 			return false ;
221 		}
222 
223 		return true ;
224 	}
225 
226 	/**
227 	* Compare keys specified and all their child keys.
228 	* @return <code>true</code> if keys and their sub keys are equal.
229 	*/
230 	public static boolean compareKeyTrees
231 		(XRegistryKey tree1, XRegistryKey tree2) {
232 
233 		return compareKeyTrees(tree1, tree2, false) ;
234 	}
235 
236 	/**
237 	* Prints to a specified output about all keys and subkeys information
238 	* (key name, type, value, link target, attributes) recursively.
239 	* @param reg Registry for which information is needed.
240 	* @param out Output stream.
241 	*/
242 	public static void printRegistryInfo(XSimpleRegistry reg, PrintWriter out) {
243 		try {
244 			printRegistryInfo(reg.getRootKey(), out) ;
245 		} catch (com.sun.star.registry.InvalidRegistryException e) {
246 			out.println("!!! Can't open root registry key for info printing") ;
247 		}
248 	}
249 
250 	/**
251 	* Prints to a specified output about all keys and subkeys information
252 	* (key name, type, value, link target, attributes) recursively.
253 	* @param root Key for which subkeys (and further) information is required.
254 	* @param out Output stream.
255 	*/
256 	public static void printRegistryInfo(XRegistryKey root, PrintWriter out) {
257 		if (root == null) {
258 			out.println("/(null)") ;
259 			return ;
260 		}
261 
262 		out.println("/") ;
263 		try {
264 			printTreeInfo(root, out, "  ") ;
265 		} catch (com.sun.star.registry.InvalidRegistryException e) {
266 			out.println("Exception accessing registry :") ;
267 			e.printStackTrace(out) ;
268 		}
269 	}
270 
271 	private static void printTreeInfo(XRegistryKey key,
272 		PrintWriter out, String margin)
273 		throws com.sun.star.registry.InvalidRegistryException {
274 
275 		String[] subKeys = key.getKeyNames() ;
276 
277 		if (subKeys == null || subKeys.length == 0) return ;
278 
279 		for (int i = 0; i < subKeys.length; i++) {
280 			printKeyInfo(key, subKeys[i], out, margin) ;
281 			XRegistryKey subKey = key.openKey
282 				(getShortKeyName(subKeys[i])) ;
283 			printTreeInfo(subKey, out, margin + "  ") ;
284 			subKey.closeKey() ;
285 		}
286 	}
287 
288 	private static void printKeyInfo(XRegistryKey parentKey,
289 		String keyName, PrintWriter out, String margin)
290 		throws com.sun.star.registry.InvalidRegistryException {
291 
292 		out.print(margin) ;
293 		keyName = getShortKeyName(keyName) ;
294 		XRegistryKey key = parentKey.openKey(keyName) ;
295 		if (key != null)
296 			out.print("/" + getShortKeyName(key.getKeyName()) + " ") ;
297 		else {
298 			out.println("(null)") ;
299 			return ;
300 		}
301 
302 		if (!key.isValid()) {
303 			out.println("(not valid)") ;
304 			return ;
305 		}
306 
307 		if (key.isReadOnly()) {
308 			out.print("(read only) ") ;
309 		}
310 
311 		if (parentKey.getKeyType(keyName) == RegistryKeyType.LINK) {
312 			out.println("(link to " + parentKey.getLinkTarget(keyName) + ")") ;
313 			return ;
314 		}
315 
316 		RegistryValueType type ;
317 		try {
318 			type = key.getValueType() ;
319 
320 			if (type.equals(RegistryValueType.ASCII)) {
321 				out.println("[ASCII] = '" + key.getAsciiValue() + "'") ;
322 			} else
323 			if (type.equals(RegistryValueType.STRING)) {
324 				out.println("[STRING] = '" + key.getStringValue() + "'") ;
325 			} else
326 			if (type.equals(RegistryValueType.LONG)) {
327 				out.println("[LONG] = " + key.getLongValue()) ;
328 			} else
329 			if (type.equals(RegistryValueType.BINARY)) {
330 				out.print("[BINARY] = {") ;
331 				byte[] bin = key.getBinaryValue() ;
332 				for (int i = 0; i < bin.length; i++)
333 					out.print("" + bin[i] + ",") ;
334 				out.println("}") ;
335 			} else
336 			if (type.equals(RegistryValueType.ASCIILIST)) {
337 				out.print("[ASCIILIST] = {") ;
338 				String[] list = key.getAsciiListValue() ;
339 				for (int i = 0; i < list.length; i++)
340 					out.print("'" + list[i] + "',") ;
341 				out.println("}") ;
342 			} else
343 			if (type.equals(RegistryValueType.STRINGLIST)) {
344 				out.print("[STRINGLIST] = {") ;
345 				String[] list = key.getStringListValue() ;
346 				for (int i = 0; i < list.length; i++)
347 					out.print("'" + list[i] + "',") ;
348 				out.println("}") ;
349 			} else
350 			if (type.equals(RegistryValueType.LONGLIST)) {
351 				out.print("[LONGLIST] = {") ;
352 				int[] list = key.getLongListValue() ;
353 				for (int i = 0; i < list.length; i++)
354 					out.print("" + list[i] + ",") ;
355 				out.println("}") ;
356 			} else {
357 				out.println("") ;
358 			}
359 		} catch (com.sun.star.uno.Exception e) {
360 			out.println("Exception occured : ") ;
361 			e.printStackTrace(out) ;
362 		} finally {
363 			key.closeKey() ;
364 		}
365 	}
366 
367 
368 //	public static void compareKeyTrees
369 
370 }
371