View Javadoc

1   /*
2    *  MicroEmulator
3    *  Copyright (C) 2002 Bartek Teodorczyk <barteo@barteo.net>
4    *
5    *  This library is free software; you can redistribute it and/or
6    *  modify it under the terms of the GNU Lesser General Public
7    *  License as published by the Free Software Foundation; either
8    *  version 2.1 of the License, or (at your option) any later version.
9    *
10   *  This library is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   *  Lesser General Public License for more details.
14   *
15   *  You should have received a copy of the GNU Lesser General Public
16   *  License along with this library; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.microemu.app;
21  
22  import java.io.BufferedInputStream;
23  import java.io.File;
24  import java.io.FileInputStream;
25  import java.io.FileWriter;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.util.Enumeration;
29  import java.util.HashMap;
30  import java.util.Iterator;
31  import java.util.Map;
32  import java.util.Properties;
33  import java.util.Vector;
34  
35  import nanoxml.XMLElement;
36  import nanoxml.XMLParseException;
37  
38  import org.microemu.EmulatorContext;
39  import org.microemu.app.util.DeviceEntry;
40  import org.microemu.app.util.IOUtils;
41  import org.microemu.app.util.MIDletSystemProperties;
42  import org.microemu.app.util.MRUList;
43  import org.microemu.app.util.MidletURLReference;
44  import org.microemu.device.impl.DeviceImpl;
45  import org.microemu.device.impl.Rectangle;
46  import org.microemu.log.Logger;
47  import org.microemu.microedition.ImplementationInitialization;
48  
49  public class Config {
50  
51  	private static File meHome;
52  
53  	/**
54  	 * emulatorID used for multiple instance of MicroEmulator, now redefine home
55  	 */
56  	private static String emulatorID;
57  
58  	private static XMLElement configXml;
59  
60  	private static DeviceEntry defaultDevice;
61  
62  	private static EmulatorContext emulatorContext;
63  
64  	private static MRUList urlsMRU = new MRUList(MidletURLReference.class, "midlet");
65  
66  	private static File initMEHomePath() {
67  		try {
68  			File meHome = new File(System.getProperty("user.home") + "/.microemulator/");
69  			if (emulatorID != null) {
70  				return new File(meHome, emulatorID);
71  			} else {
72  				return meHome;
73  			}
74  		} catch (SecurityException e) {
75  			Logger.error("Cannot access user.home", e);
76  			return null;
77  		}
78  	}
79  
80  	public static void loadConfig(DeviceEntry defaultDevice, EmulatorContext emulatorContext) {
81  		Config.defaultDevice = defaultDevice;
82  		Config.emulatorContext = emulatorContext;
83  
84  		File configFile = new File(getConfigPath(), "config2.xml");
85  		try {
86  			if (configFile.exists()) {
87  				loadConfigFile("config2.xml");
88  			} else {
89  				configFile = new File(getConfigPath(), "config.xml");
90  				if (configFile.exists()) {
91  					// migrate from config.xml
92  					loadConfigFile("config.xml");
93  
94  					for (Enumeration e = getDeviceEntries().elements(); e.hasMoreElements();) {
95  						DeviceEntry entry = (DeviceEntry) e.nextElement();
96  						if (!entry.canRemove()) {
97  							continue;
98  						}
99  
100 						removeDeviceEntry(entry);
101 						File src = new File(getConfigPath(), entry.getFileName());
102 						File dst = File.createTempFile("dev", ".jar", getConfigPath());
103 						IOUtils.copyFile(src, dst);
104 						entry.setFileName(dst.getName());
105 						addDeviceEntry(entry);
106 					}
107 				} else {
108 					createDefaultConfigXml();
109 				}
110 				saveConfig();
111 			}
112 		} catch (IOException ex) {
113 			Logger.error(ex);
114 			createDefaultConfigXml();
115 		} finally {
116 			// Happens in webstart untrusted environment
117 			if (configXml == null) {
118 				createDefaultConfigXml();
119 			}
120 		}
121 		urlsMRU.read(configXml.getChildOrNew("files").getChildOrNew("recent"));
122 		initSystemProperties();
123 	}
124 
125 	private static void loadConfigFile(String configFileName) throws IOException {
126 		File configFile = new File(getConfigPath(), configFileName);
127 		InputStream is = null;
128 		String xml = "";
129 		try {
130 			InputStream dis = new BufferedInputStream(is = new FileInputStream(configFile));
131 			while (dis.available() > 0) {
132 				byte[] b = new byte[dis.available()];
133 				dis.read(b);
134 				xml += new String(b);
135 			}
136 			configXml = new XMLElement();
137 			configXml.parseString(xml);
138 		} catch (XMLParseException e) {
139 			Logger.error(e);
140 			createDefaultConfigXml();
141 		} finally {
142 			IOUtils.closeQuietly(is);
143 		}
144 	}
145 
146 	private static void createDefaultConfigXml() {
147 		configXml = new XMLElement();
148 		configXml.setName("config");
149 	}
150 
151 	public static void saveConfig() {
152 
153 		urlsMRU.save(configXml.getChildOrNew("files").getChildOrNew("recent"));
154 
155 		File configFile = new File(getConfigPath(), "config2.xml");
156 
157 		getConfigPath().mkdirs();
158 		FileWriter fw = null;
159 		try {
160 			fw = new FileWriter(configFile);
161 			configXml.write(fw);
162 			fw.close();
163 		} catch (IOException ex) {
164 			Logger.error(ex);
165 		} finally {
166 			IOUtils.closeQuietly(fw);
167 		}
168 	}
169 
170 	static Map getExtensions() {
171 		Map extensions = new HashMap();
172 		XMLElement extensionsXml = configXml.getChild("extensions");
173 		if (extensionsXml == null) {
174 			return extensions;
175 		}
176 		for (Enumeration en = extensionsXml.enumerateChildren(); en.hasMoreElements();) {
177 			XMLElement extension = (XMLElement) en.nextElement();
178 			if (!extension.getName().equals("extension")) {
179 				continue;
180 			}
181 			String className = (String) extension.getChildString("className", null);
182 			if (className == null) {
183 				continue;
184 			}
185 
186 			Map parameters = new HashMap();
187 			parameters.put(ImplementationInitialization.PARAM_EMULATOR_ID, Config.getEmulatorID());
188 
189 			for (Enumeration een = extension.enumerateChildren(); een.hasMoreElements();) {
190 				XMLElement propXml = (XMLElement) een.nextElement();
191 				if (propXml.getName().equals("properties")) {
192 					for (Enumeration e_prop = propXml.enumerateChildren(); e_prop.hasMoreElements();) {
193 						XMLElement tmp_prop = (XMLElement) e_prop.nextElement();
194 						if (tmp_prop.getName().equals("property")) {
195 							parameters.put(tmp_prop.getStringAttribute("name"), tmp_prop.getStringAttribute("value"));
196 						}
197 					}
198 				}
199 			}
200 
201 			extensions.put(className, parameters);
202 		}
203 		return extensions;
204 	}
205 
206 	private static void initSystemProperties() {
207 		Map systemProperties = null;
208 
209 		for (Enumeration e = configXml.enumerateChildren(); e.hasMoreElements();) {
210 			XMLElement tmp = (XMLElement) e.nextElement();
211 			if (tmp.getName().equals("system-properties")) {
212 				// Permits null values.
213 				systemProperties = new HashMap();
214 				for (Enumeration e_prop = tmp.enumerateChildren(); e_prop.hasMoreElements();) {
215 					XMLElement tmp_prop = (XMLElement) e_prop.nextElement();
216 					if (tmp_prop.getName().equals("system-property")) {
217 						systemProperties.put(tmp_prop.getStringAttribute("name"), tmp_prop.getStringAttribute("value"));
218 					}
219 				}
220 			}
221 		}
222 
223 		// No <system-properties> in config2.xml
224 		if (systemProperties == null) {
225 			systemProperties = new Properties();
226 			systemProperties.put("microedition.configuration", "CLDC-1.0");
227 			systemProperties.put("microedition.profiles", "MIDP-2.0");
228 			// Ask avetana to ignore MIDP profiles and load JSR-82
229 			// implementation dll or so
230 			systemProperties.put("avetana.forceNativeLibrary", Boolean.TRUE.toString());
231 
232 			XMLElement propertiesXml = configXml.getChildOrNew("system-properties");
233 
234 			for (Iterator i = systemProperties.entrySet().iterator(); i.hasNext();) {
235 				Map.Entry e = (Map.Entry) i.next();
236 				XMLElement xmlProperty = propertiesXml.addChild("system-property");
237 				xmlProperty.setAttribute("value", (String) e.getValue());
238 				xmlProperty.setAttribute("name", (String) e.getKey());
239 			}
240 
241 			saveConfig();
242 		}
243 
244 		MIDletSystemProperties.setProperties(systemProperties);
245 	}
246 
247 	public static File getConfigPath() {
248 		if (meHome == null) {
249 			meHome = initMEHomePath();
250 		}
251 		return meHome;
252 	}
253 
254 	public static Vector getDeviceEntries() {
255 		Vector result = new Vector();
256 
257 		if (defaultDevice == null) {
258 			defaultDevice = new DeviceEntry("Default device", null, DeviceImpl.DEFAULT_LOCATION, true, false);
259 		}
260 		defaultDevice.setDefaultDevice(true);
261 		result.add(defaultDevice);
262 
263 		XMLElement devicesXml = configXml.getChild("devices");
264 		if (devicesXml == null) {
265 			return result;
266 		}
267 
268 		for (Enumeration e_device = devicesXml.enumerateChildren(); e_device.hasMoreElements();) {
269 			XMLElement tmp_device = (XMLElement) e_device.nextElement();
270 			if (tmp_device.getName().equals("device")) {
271 				boolean devDefault = false;
272 				if (tmp_device.getStringAttribute("default") != null
273 						&& tmp_device.getStringAttribute("default").equals("true")) {
274 					devDefault = true;
275 					defaultDevice.setDefaultDevice(false);
276 				}
277 				String devName = tmp_device.getChildString("name", null);
278 				String devFile = tmp_device.getChildString("filename", null);
279 				String devClass = tmp_device.getChildString("class", null);
280 				String devDescriptor = tmp_device.getChildString("descriptor", null);
281 				;
282 				if (devDescriptor == null) {
283 					result.add(new DeviceEntry(devName, devFile, devDefault, devClass, emulatorContext));
284 				} else {
285 					result.add(new DeviceEntry(devName, devFile, devDescriptor, devDefault));
286 				}
287 			}
288 		}
289 
290 		return result;
291 	}
292 
293 	public static void addDeviceEntry(DeviceEntry entry) {
294 		for (Enumeration en = getDeviceEntries().elements(); en.hasMoreElements();) {
295 			DeviceEntry test = (DeviceEntry) en.nextElement();
296 			if (test.getDescriptorLocation().equals(entry.getDescriptorLocation())) {
297 				return;
298 			}
299 		}
300 
301 		XMLElement devicesXml = configXml.getChildOrNew("devices");
302 
303 		XMLElement deviceXml = devicesXml.addChild("device");
304 		if (entry.isDefaultDevice()) {
305 			deviceXml.setAttribute("default", "true");
306 		}
307 		deviceXml.addChild("name", entry.getName());
308 		deviceXml.addChild("filename", entry.getFileName());
309 		deviceXml.addChild("descriptor", entry.getDescriptorLocation());
310 
311 		saveConfig();
312 	}
313 
314 	public static void removeDeviceEntry(DeviceEntry entry) {
315 		XMLElement devicesXml = configXml.getChild("devices");
316 		if (devicesXml == null) {
317 			return;
318 		}
319 
320 		for (Enumeration e_device = devicesXml.enumerateChildren(); e_device.hasMoreElements();) {
321 			XMLElement tmp_device = (XMLElement) e_device.nextElement();
322 			if (tmp_device.getName().equals("device")) {
323 				String testDescriptor = tmp_device.getChildString("descriptor", null);
324 				// this is needed by migration config.xml -> config2.xml
325 				if (testDescriptor == null) {
326 					devicesXml.removeChild(tmp_device);
327 
328 					saveConfig();
329 					continue;
330 				}
331 				if (testDescriptor.equals(entry.getDescriptorLocation())) {
332 					devicesXml.removeChild(tmp_device);
333 
334 					saveConfig();
335 					break;
336 				}
337 			}
338 		}
339 	}
340 
341 	public static void changeDeviceEntry(DeviceEntry entry) {
342 		XMLElement devicesXml = configXml.getChild("devices");
343 		if (devicesXml == null) {
344 			return;
345 		}
346 
347 		for (Enumeration e_device = devicesXml.enumerateChildren(); e_device.hasMoreElements();) {
348 			XMLElement tmp_device = (XMLElement) e_device.nextElement();
349 			if (tmp_device.getName().equals("device")) {
350 				String testDescriptor = tmp_device.getChildString("descriptor", null);
351 				if (testDescriptor.equals(entry.getDescriptorLocation())) {
352 					if (entry.isDefaultDevice()) {
353 						tmp_device.setAttribute("default", "true");
354 					} else {
355 						tmp_device.removeAttribute("default");
356 					}
357 
358 					saveConfig();
359 					break;
360 				}
361 			}
362 		}
363 	}
364 
365 	public static Rectangle getDeviceEntryDisplaySize(DeviceEntry entry) {
366 		XMLElement devicesXml = configXml.getChild("devices");
367 
368 		for (Enumeration e_device = devicesXml.enumerateChildren(); e_device.hasMoreElements();) {
369 			XMLElement tmp_device = (XMLElement) e_device.nextElement();
370 			if (tmp_device.getName().equals("device")) {
371 				String testDescriptor = tmp_device.getChildString("descriptor", null);
372 				if (testDescriptor.equals(entry.getDescriptorLocation())) {
373 					XMLElement rectangleXml = tmp_device.getChild("rectangle");
374 					if (rectangleXml != null) {
375 						Rectangle result = new Rectangle();
376 						result.x = rectangleXml.getChildInteger("x", -1);
377 						result.y = rectangleXml.getChildInteger("y", -1);
378 						result.width = rectangleXml.getChildInteger("width", -1);
379 						result.height = rectangleXml.getChildInteger("height", -1);
380 
381 						return result;
382 					}
383 				}
384 			}
385 		}
386 
387 		return null;
388 	}
389 
390 	public static void setDeviceEntryDisplaySize(DeviceEntry entry, Rectangle rect) {
391 		if (entry == null) {
392 			return;
393 		}
394 		XMLElement devicesXml = configXml.getChild("devices");
395 		if (devicesXml == null) {
396 			return;
397 		}
398 
399 		for (Enumeration e_device = devicesXml.enumerateChildren(); e_device.hasMoreElements();) {
400 			XMLElement tmp_device = (XMLElement) e_device.nextElement();
401 			if (tmp_device.getName().equals("device")) {
402 				String testDescriptor = tmp_device.getChildString("descriptor", null);
403 				if (testDescriptor.equals(entry.getDescriptorLocation())) {
404 					XMLElement mainXml = tmp_device.getChildOrNew("rectangle");
405 					XMLElement xml = mainXml.getChildOrNew("x");
406 					xml.setContent(String.valueOf(rect.x));
407 					xml = mainXml.getChildOrNew("y");
408 					xml.setContent(String.valueOf(rect.y));
409 					xml = mainXml.getChildOrNew("width");
410 					xml.setContent(String.valueOf(rect.width));
411 					xml = mainXml.getChildOrNew("height");
412 					xml.setContent(String.valueOf(rect.height));
413 
414 					saveConfig();
415 					break;
416 				}
417 			}
418 		}
419 	}
420 
421 	public static String getRecordStoreManagerClassName() {
422 		XMLElement recordStoreManagerXml = configXml.getChild("recordStoreManager");
423 		if (recordStoreManagerXml == null) {
424 			return null;
425 		}
426 
427 		return recordStoreManagerXml.getStringAttribute("class");
428 	}
429 
430 	public static void setRecordStoreManagerClassName(String className) {
431 		XMLElement recordStoreManagerXml = configXml.getChildOrNew("recordStoreManager");
432 		recordStoreManagerXml.setAttribute("class", className);
433 
434 		saveConfig();
435 	}
436 
437 	public static boolean isLogConsoleLocationEnabled() {
438 		XMLElement logConsoleXml = configXml.getChild("logConsole");
439 		if (logConsoleXml == null) {
440 			return true;
441 		}
442 
443 		return logConsoleXml.getBooleanAttribute("locationEnabled", true);
444 	}
445 
446 	public static void setLogConsoleLocationEnabled(boolean state) {
447 		XMLElement logConsoleXml = configXml.getChildOrNew("logConsole");
448 		if (state) {
449 			logConsoleXml.setAttribute("locationEnabled", "true");
450 		} else {
451 			logConsoleXml.setAttribute("locationEnabled", "false");
452 		}
453 
454 		saveConfig();
455 	}
456 
457 	public static boolean isWindowOnStart(String name) {
458 		XMLElement windowsXml = configXml.getChild("windows");
459 		if (windowsXml == null) {
460 			return false;
461 		}
462 
463 		XMLElement mainXml = windowsXml.getChild(name);
464 		if (mainXml == null) {
465 			return false;
466 		}
467 
468 		String attr = mainXml.getStringAttribute("onstart", "false");
469 		if (attr.trim().toLowerCase().equals("true")) {
470 			return true;
471 		} else {
472 			return false;
473 		}
474 	}
475 
476 	public static Rectangle getWindow(String name, Rectangle defaultWindow) {
477 		XMLElement windowsXml = configXml.getChild("windows");
478 		if (windowsXml == null) {
479 			return defaultWindow;
480 		}
481 
482 		XMLElement mainXml = windowsXml.getChild(name);
483 		if (mainXml == null) {
484 			return defaultWindow;
485 		}
486 
487 		Rectangle window = new Rectangle();
488 		window.x = mainXml.getChildInteger("x", defaultWindow.x);
489 		window.y = mainXml.getChildInteger("y", defaultWindow.y);
490 		window.width = mainXml.getChildInteger("width", defaultWindow.width);
491 		window.height = mainXml.getChildInteger("height", defaultWindow.height);
492 
493 		return window;
494 	}
495 
496 	public static void setWindow(String name, Rectangle window, boolean onStart) {
497 		XMLElement windowsXml = configXml.getChildOrNew("windows");
498 		XMLElement mainXml = windowsXml.getChildOrNew(name);
499 		if (onStart) {
500 			mainXml.setAttribute("onstart", "true");
501 		} else {
502 			mainXml.removeAttribute("onstart");
503 		}
504 		XMLElement xml = mainXml.getChildOrNew("x");
505 		xml.setContent(String.valueOf(window.x));
506 		xml = mainXml.getChildOrNew("y");
507 		xml.setContent(String.valueOf(window.y));
508 		xml = mainXml.getChildOrNew("width");
509 		xml.setContent(String.valueOf(window.width));
510 		xml = mainXml.getChildOrNew("height");
511 		xml.setContent(String.valueOf(window.height));
512 
513 		saveConfig();
514 	}
515 
516 	public static String getRecentDirectory(String key) {
517 		String defaultResult = ".";
518 
519 		XMLElement filesXml = configXml.getChild("files");
520 		if (filesXml == null) {
521 			return defaultResult;
522 		}
523 
524 		return filesXml.getChildString(key, defaultResult);
525 	}
526 
527 	public static void setRecentDirectory(String key, String recentJadDirectory) {
528 		XMLElement filesXml = configXml.getChildOrNew("files");
529 		XMLElement recentJadDirectoryXml = filesXml.getChildOrNew(key);
530 		recentJadDirectoryXml.setContent(recentJadDirectory);
531 
532 		saveConfig();
533 	}
534 
535 	public static MRUList getUrlsMRU() {
536 		return urlsMRU;
537 	}
538 
539 	public static String getEmulatorID() {
540 		return emulatorID;
541 	}
542 
543 	public static void setEmulatorID(String emulatorID) {
544 		Config.emulatorID = emulatorID;
545 	}
546 
547 }