/* * File : PlayerSettings.java * Created : 19-jun-2002 10:22 * By : fbusquets * * JClic - Authoring and playing system for educational activities * * Copyright (C) 2000 - 2005 Francesc Busquets & Departament * d'Educacio de la Generalitat de Catalunya * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details (see the LICENSE file). */ package edu.xtec.jclic; import edu.xtec.jclic.fileSystem.FileSystem; import edu.xtec.jclic.project.LibraryManager; import edu.xtec.util.BrowserLauncher; import edu.xtec.util.Domable; import edu.xtec.util.JDomUtility; import edu.xtec.util.LFUtil; import edu.xtec.util.Messages; import edu.xtec.util.Options; import edu.xtec.util.ResourceBridge; import java.awt.Component; import java.io.File; import java.io.FileOutputStream; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * * @author Francesc Busquets (fbusquets@xtec.cat) * @version 13.09.10 */ public class PlayerSettings extends Object implements Cloneable, edu.xtec.jclic.Constants, Domable { public ResourceBridge rb; //public Options options; public LibraryManager libraryManager; public String language, country, variant; public String reporterClass, reporterParams; public boolean reporterEnabled; public boolean soundEnabled, systemSounds; public String lookAndFeel; public String skin; public Map<String, String> misc; public String rootPath; public String mediaSystem; public FileSystem fileSystem; public static int MAX_RECENT = 8; public String[] recentFiles; public String preferredBrowser; protected String password; protected boolean passwordConfirmed; public String cfgFile; public boolean readOnly; protected static String defaultCfgFile = null; public static final String PROJECTS_PATH = "projects", CFG_FILE = "jclic.cfg", DEFAULT_SKIN = "@default.xml", DEFAULT_REPORTER = "TCPReporter", DEFAULT_REPORTER_PARAMS = "path=localhost:9000"; public boolean fressaEnabled; /** Creates new PlayerSettings */ public PlayerSettings(ResourceBridge rb, String fromPath /*, Options options*/) { this.rb = rb; password = null; misc = new HashMap<String, String>(); reporterEnabled = false; reporterClass = DEFAULT_REPORTER; reporterParams = DEFAULT_REPORTER_PARAMS; soundEnabled = true; systemSounds = true; lookAndFeel = edu.xtec.util.LFUtil.DEFAULT; preferredBrowser = ""; skin = DEFAULT_SKIN; recentFiles = new String[MAX_RECENT]; mediaSystem = DEFAULT; readOnly = false; rootPath = System.getProperty("user.home"); cfgFile = (fromPath == null ? getDefaultCfgFile(rb.getOptions()) : fromPath); fileSystem = new FileSystem(rb); if (FileSystem.isStrUrl(cfgFile)) { readOnly = true; } else { File f = new File(cfgFile); readOnly = !f.canWrite(); } libraryManager = new LibraryManager(this); passwordConfirmed = false; } public static final String ELEMENT_NAME = "JClicSettings", REPORTER = "reporter", CLASS = "class", PARAMS = "params", SOUND = "sound", SYSTEM = "system", MISC = "misc", PATHS = "paths", PATH = "path", ROOT = "root", RECENT_FILES = "recentFiles", FILE = "file", PASSWORD = "password"; public static String getDefaultCfgFile(Options options) { if (defaultCfgFile == null) { defaultCfgFile = edu.xtec.util.PersistentSettings.getFilePath(PROGRAM, CFG_FILE, options, true); } return defaultCfgFile; } public static PlayerSettings loadPlayerSettings(ResourceBridge rb) { PlayerSettings result = null; String cfgFile = rb.getOptions().getString(ELEMENT_NAME); if (cfgFile != null) { try { result = new PlayerSettings(rb, cfgFile); result.loadSettings(result.fileSystem.getXMLDocument(cfgFile).getRootElement()); } catch (Exception ex) { result = null; System.err.println("Unable to read settings from " + cfgFile + "\n" + ex); } } if (result == null) { cfgFile = getDefaultCfgFile(rb.getOptions()); result = new PlayerSettings(rb, cfgFile); try { result.loadSettings(result.fileSystem.getXMLDocument(cfgFile).getRootElement()); } catch (Exception ex) { result.initNewSettings(); } } rb.getOptions().syncProperties(result.getProperties(), true); if (!rb.getOptions().getBoolean(Options.LANGUAGE_BY_PARAM) && result.language != null) { rb.getOptions().put(Messages.LANGUAGE, result.language); if (result.country != null) { rb.getOptions().put(Messages.COUNTRY, result.country); } if (result.variant != null) { rb.getOptions().put(Messages.VARIANT, result.variant); } } return result; } private void initNewSettings() { try { Messages msg = rb.getOptions().getMessages(); if (language == null) { language = msg.getLocale().getLanguage(); country = msg.getLocale().getCountry(); variant = msg.getLocale().getVariant(); } readOnly = false; File f = new File(new File(cfgFile).getParentFile(), PROJECTS_PATH); f.mkdirs(); rootPath = f.getAbsolutePath(); fileSystem = new FileSystem(rootPath, rb); } catch (Exception ex) { System.err.println("Unable to create new settings!\n" + ex); } } public void checkLibrary() { if (!readOnly && libraryManager.isEmpty() && rootPath != null && !FileSystem.isStrUrl(rootPath)) { File f = new File(new File(rootPath), "library.jclic"); try { libraryManager.addNewLibrary(f.getAbsolutePath(), null); save(); } catch (Exception ex) { System.err.println("Unable to create new project library!\n" + ex); } } } public void save() { if (!readOnly) { try { FileOutputStream fos = fileSystem.createSecureFileOutputStream(cfgFile); JDomUtility.saveDocument(fos, getJDomElement()); fos.close(); } catch (Exception ex) { System.err.println("unable to save settings in " + cfgFile + ": " + ex.getMessage()); } } } public org.jdom.Element getJDomElement() { org.jdom.Element e = new org.jdom.Element(ELEMENT_NAME); org.jdom.Element child, child2; e.addContent(libraryManager.getJDomElement()); if (password != null) { e.setAttribute(PASSWORD, edu.xtec.util.Encryption.Encrypt(password)); } if (language != null) { child = new org.jdom.Element(Messages.LANGUAGE); child.setAttribute(ID, language); if (country != null) { child.setAttribute(Messages.COUNTRY, country); } if (variant != null) { child.setAttribute(Messages.VARIANT, variant); } e.addContent(child); } child = new org.jdom.Element(PATHS); child2 = new org.jdom.Element(PATH); child2.setAttribute(ID, ROOT); child2.setAttribute(PATH, rootPath); child.addContent(child2); e.addContent(child); child = new org.jdom.Element(REPORTER); child.setAttribute(ENABLED, JDomUtility.boolString(reporterEnabled)); child.setAttribute(CLASS, reporterClass); child.setAttribute(PARAMS, reporterParams); e.addContent(child); child = new org.jdom.Element(SOUND); child.setAttribute(ENABLED, JDomUtility.boolString(soundEnabled)); child.setAttribute(SYSTEM, JDomUtility.boolString(systemSounds)); child.setAttribute(MEDIA_SYSTEM, mediaSystem); e.addContent(child); child = new org.jdom.Element(LFUtil.LOOK_AND_FEEL); child.setAttribute(ID, lookAndFeel); e.addContent(child); child = new org.jdom.Element(BrowserLauncher.BROWSER); child.setAttribute(ID, preferredBrowser); e.addContent(child); child = new org.jdom.Element(SKIN); child.setAttribute(ID, skin); e.addContent(child); if (!misc.isEmpty()) { child = new org.jdom.Element(MISC); for (java.util.Map.Entry me : misc.entrySet()) { String k = (String) me.getKey(); Object v = me.getValue(); if (k != null && v != null && v instanceof String) { child.setAttribute(k, (String) v); } } e.addContent(child); } child = new org.jdom.Element(RECENT_FILES); for (int i = 0; i < MAX_RECENT; i++) { if (recentFiles[i] != null) { child2 = new org.jdom.Element(FILE); child2.setAttribute(PATH, recentFiles[i]); child.addContent(child2); } } e.addContent(child); return e; } public void loadSettings(org.jdom.Element e) throws Exception { setProperties(e, null); } public void setProperties(org.jdom.Element e, Object aux) throws Exception { JDomUtility.checkName(e, ELEMENT_NAME); org.jdom.Element child, child2; password = JDomUtility.getStringAttr(e, PASSWORD, password, false); if (password != null) { password = edu.xtec.util.Encryption.Decrypt(password); } if ((child = e.getChild(LibraryManager.ELEMENT_NAME)) != null) { libraryManager = LibraryManager.getLibraryManager(this, child); } if ((child = e.getChild(PATHS)) != null) { String rp = null; Iterator it = child.getChildren(PATH).iterator(); while (it.hasNext()) { child2 = (org.jdom.Element) it.next(); if (ROOT.equals(child2.getAttributeValue(ID))) { rp = JDomUtility.getStringAttr(child2, PATH, rootPath, false); } } if (rp != null) { rootPath = rp; if (!FileSystem.isStrUrl(rootPath)) { fileSystem = new FileSystem(rootPath, rb); } } } if ((child = e.getChild(Messages.LANGUAGE)) != null) { language = JDomUtility.getStringAttr(child, ID, language, false); country = JDomUtility.getStringAttr(child, Messages.COUNTRY, country, false); variant = JDomUtility.getStringAttr(child, Messages.VARIANT, variant, false); } if ((child = e.getChild(REPORTER)) != null) { reporterEnabled = JDomUtility.getBoolAttr(child, ENABLED, reporterEnabled); reporterClass = JDomUtility.getStringAttr(child, CLASS, reporterClass, false); reporterParams = JDomUtility.getStringAttr(child, PARAMS, reporterParams, false); } if ((child = e.getChild(SOUND)) != null) { soundEnabled = JDomUtility.getBoolAttr(child, ENABLED, soundEnabled); systemSounds = JDomUtility.getBoolAttr(child, SYSTEM, systemSounds); mediaSystem = JDomUtility.getStringAttr(child, MEDIA_SYSTEM, mediaSystem, false); } if ((child = e.getChild(LFUtil.LOOK_AND_FEEL)) != null) { lookAndFeel = JDomUtility.getStringAttr(child, ID, lookAndFeel, false); } if ((child = e.getChild(BrowserLauncher.BROWSER)) != null) { preferredBrowser = JDomUtility.getStringAttr(child, ID, preferredBrowser, false); BrowserLauncher.setPreferredBrowser(preferredBrowser); } if ((child = e.getChild(SKIN)) != null) { skin = JDomUtility.getStringAttr(child, ID, skin, false); } if ((child = e.getChild(MISC)) != null) { java.util.Iterator it = child.getAttributes().iterator(); while (it.hasNext()) { org.jdom.Attribute a = (org.jdom.Attribute) it.next(); misc.put(a.getName(), a.getValue()); //System.out.println(a.getName()+" - "+a.getValue()); } } if ((child = e.getChild(RECENT_FILES)) != null) { java.util.Iterator it = child.getChildren(FILE).iterator(); for (int i = 0; i < MAX_RECENT; i++) { if (it.hasNext()) { recentFiles[i] = JDomUtility.getStringAttr(((org.jdom.Element) it.next()), PATH, null, false); } else { recentFiles[i] = null; } } } } public Messages getMessages() { return rb.getOptions().getMessages(); } public Map getProperties() { HashMap<String, Object> prop = new HashMap<String, Object>(); String t = TRUE; String f = FALSE; if (language != null) { prop.put(Messages.LANGUAGE, language); prop.put(Messages.COUNTRY, country); prop.put(Messages.VARIANT, variant); } if (reporterEnabled) { prop.put(REPORTER_CLASS, reporterClass); prop.put(REPORTER_PARAMS, reporterParams); } prop.put(SYSTEM_SOUNDS, systemSounds ? t : f); prop.put(AUDIO_ENABLED, soundEnabled ? t : f); prop.put(LFUtil.LOOK_AND_FEEL, lookAndFeel); prop.put(BrowserLauncher.BROWSER, preferredBrowser); prop.put(MEDIA_SYSTEM, mediaSystem); prop.put(SKIN, skin); prop.putAll(misc); return prop; } public boolean edit(Component parent) { boolean result = false; if (promptPassword(parent, null)) { PlayerSettingsDlg dlg = new PlayerSettingsDlg(this, parent); dlg.setVisible(true); result = dlg.result; if (result) { BrowserLauncher.setPreferredBrowser(preferredBrowser); } } return result; } public boolean promptPassword(Component parent, String[] msgKeys) { boolean result = (passwordConfirmed || password == null || password.length() == 0); while (!result) { if (msgKeys == null) { msgKeys = new String[]{"settings_passwordRequired"}; } String r = getMessages().showInputDlg(parent, msgKeys, null, null, null, true); if (r == null) { break; } result = password.equals(r); if (!result) { getMessages().showAlert(parent, "PASSWORD_INCORRECT"); } else { passwordConfirmed = true; } } return result; } public void addRecentFile(String fName) { if (fName != null) { String[] recentBak = recentFiles; recentFiles = new String[MAX_RECENT]; recentFiles[0] = fName.trim(); for (int i = 0, j = 1; i < MAX_RECENT && j < MAX_RECENT; i++) { if (recentBak[i] != null && !recentBak[i].equals(fName)) { recentFiles[j++] = recentBak[i]; } } } } }