View Javadoc

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