aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorIngo Bauersachs <ingo@jitsi.org>2014-01-12 15:34:36 +0100
committerIngo Bauersachs <ingo@jitsi.org>2014-01-12 15:34:36 +0100
commit09c0ef620b050e601cdc75c13bc7d54a2d7cc335 (patch)
tree5b4899e1480822e588a27325137516adbde47190 /src
parente7cd23f4345012d397e9bfe3a0bfd660ba1c100d (diff)
downloadjitsi-09c0ef620b050e601cdc75c13bc7d54a2d7cc335.zip
jitsi-09c0ef620b050e601cdc75c13bc7d54a2d7cc335.tar.gz
jitsi-09c0ef620b050e601cdc75c13bc7d54a2d7cc335.tar.bz2
ConfigService based on HSQLDB (through JDBC)
Diffstat (limited to 'src')
-rw-r--r--src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java56
-rw-r--r--src/net/java/sip/communicator/impl/configuration/JdbcConfigService.java910
-rw-r--r--src/net/java/sip/communicator/impl/configuration/configuration.manifest.mf7
3 files changed, 945 insertions, 28 deletions
diff --git a/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java b/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java
index 17066eb..3510da6 100644
--- a/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java
+++ b/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java
@@ -7,7 +7,11 @@
package net.java.sip.communicator.impl.configuration;
import com.sun.jna.*;
+
+import net.java.sip.communicator.util.ServiceUtils;
+
import org.jitsi.service.configuration.*;
+import org.jitsi.service.fileaccess.*;
import org.jitsi.service.libjitsi.*;
import org.jitsi.util.*;
import org.osgi.framework.*;
@@ -29,10 +33,9 @@ public class ConfigurationActivator
= Logger.getLogger(ConfigurationActivator.class);
/**
- * The <tt>BundleContext</tt> in which the configuration bundle has been
- * started and has not been stopped yet.
+ * The currently registered {@link ConfigurationService} instance.
*/
- private static BundleContext bundleContext;
+ private ConfigurationService cs;
/**
* Starts the configuration service
@@ -44,20 +47,29 @@ public class ConfigurationActivator
public void start(BundleContext bundleContext)
throws Exception
{
- ConfigurationActivator.bundleContext = bundleContext;
-
- ConfigurationService configurationService
- = LibJitsi.getConfigurationService();
-
- if (configurationService != null)
+ FileAccessService fas
+ = ServiceUtils.getService(bundleContext, FileAccessService.class);
+ File useDatabaseConfig = fas.getPrivatePersistentFile(
+ ".usedatabaseconfig",
+ FileCategory.PROFILE);
+
+ // BETA: if the marker file exists, use the database configuration
+ if (useDatabaseConfig.exists())
{
- bundleContext.registerService(
- ConfigurationService.class.getName(),
- configurationService,
- null);
-
- fixPermissions(configurationService);
+ logger.info("Using database configuration store.");
+ this.cs = new JdbcConfigService(fas);
+ }
+ else
+ {
+ this.cs = LibJitsi.getConfigurationService();
}
+
+ bundleContext.registerService(
+ ConfigurationService.class.getName(),
+ this.cs,
+ null);
+
+ fixPermissions(this.cs);
}
/**
@@ -72,18 +84,8 @@ public class ConfigurationActivator
public void stop(BundleContext bundleContext)
throws Exception
{
- }
-
- /**
- * Gets the <tt>BundleContext</tt> in which the configuration bundle has
- * been started and has not been stopped yet.
- *
- * @return the <tt>BundleContext</tt> in which the configuration bundle has
- * been started and has not been stopped yet
- */
- public static BundleContext getBundleContext()
- {
- return bundleContext;
+ this.cs.storeConfiguration();
+ this.cs = null;
}
/**
diff --git a/src/net/java/sip/communicator/impl/configuration/JdbcConfigService.java b/src/net/java/sip/communicator/impl/configuration/JdbcConfigService.java
new file mode 100644
index 0000000..e75068b
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/configuration/JdbcConfigService.java
@@ -0,0 +1,910 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.configuration;
+
+import java.beans.*;
+import java.io.*;
+import java.sql.*;
+import java.sql.Statement;
+import java.util.*;
+
+import org.jitsi.service.configuration.*;
+import org.jitsi.service.fileaccess.*;
+import org.jitsi.util.*;
+
+import com.google.common.collect.*;
+
+/**
+ * Implementation of the {@link ConfigurationService} based on JDBC.
+ *
+ * @author Ingo Bauersachs
+ */
+public final class JdbcConfigService
+ implements ConfigurationService
+{
+ /**
+ * The <tt>Logger</tt> used by this class.
+ */
+ private final Logger logger
+ = Logger.getLogger(JdbcConfigService.class);
+
+ /**
+ * Name of the file containing default properties.
+ */
+ private static final String DEFAULT_PROPS_FILE_NAME
+ = "jitsi-defaults.properties";
+
+ /**
+ * Name of the file containing overrides (possibly set by the distributor)
+ * for any of the default properties.
+ */
+ private static final String DEFAULT_OVERRIDES_PROPS_FILE_NAME
+ = "jitsi-default-overrides.properties";
+
+ /**
+ * A set of immutable properties deployed with the application during
+ * install time. The properties in this file will be impossible to override
+ * and attempts to do so will simply be ignored.
+ * @see #defaultProperties
+ */
+ private Map<String, String> immutableDefaultProperties
+ = new HashMap<String, String>();
+
+ /**
+ * A set of properties deployed with the application during install time.
+ * Contrary to the properties in {@link #immutableDefaultProperties} the
+ * ones in this map can be overridden with call to the
+ * <tt>setProperty()</tt> methods. Still, re-setting one of these properties
+ * to <tt>null</tt> would cause for its initial value to be restored.
+ */
+ private Map<String, String> defaultProperties
+ = new HashMap<String, String>();
+
+ /**
+ * Registered property change listeners that may veto a change.
+ */
+ private SetMultimap<String, ConfigVetoableChangeListener> vetoListeners
+ = HashMultimap.create();
+
+ /**
+ * Registered property change listeners.
+ */
+ private SetMultimap<String, PropertyChangeListener> listeners
+ = HashMultimap.create();
+
+ /**
+ * Connection to the JDBC database.
+ */
+ private Connection connection;
+
+ // SQL statements for queries against the database
+ private PreparedStatement selectExact;
+ private PreparedStatement selectLike;
+ private PreparedStatement selectAll;
+ private PreparedStatement insertOrUpdate;
+ private PreparedStatement delete;
+
+ /**
+ * Reference to the {@link FileAccessService}.
+ */
+ private FileAccessService fas;
+
+ /**
+ * Creates a new instance of this class.
+ * @param fas Reference to the {@link FileAccessService}.
+ * @throws Exception
+ */
+ public JdbcConfigService(FileAccessService fas) throws Exception
+ {
+ this.fas = fas;
+ File dataFile = fas.getPrivatePersistentFile(
+ "props.hsql.script",
+ FileCategory.PROFILE);
+ File oldProps = fas.getPrivatePersistentFile(
+ "sip-communicator.properties",
+ FileCategory.PROFILE);
+
+ // if the file for the current database does not exist yet but
+ // the previous properties-based file is there, migrate it
+ boolean migrate = false;
+ if (!dataFile.exists() && oldProps.exists())
+ {
+ migrate = true;
+ }
+
+ // open the connection
+ Class.forName("org.hsqldb.jdbc.JDBCDriver");
+ checkConnection();
+
+ // then do the actual migration
+ if (migrate)
+ {
+ Properties p = new Properties();
+ p.load(new FileInputStream(oldProps));
+
+ this.connection.setAutoCommit(false);
+ for (Map.Entry<Object, Object> e : p.entrySet())
+ {
+ this.setProperty(e.getKey().toString(), e.getValue(), false);
+ }
+
+ this.connection.commit();
+ this.connection.setAutoCommit(true);
+ }
+
+ // and finally load the (mandatory) system properties
+ loadDefaultProperties(DEFAULT_PROPS_FILE_NAME);
+ loadDefaultProperties(DEFAULT_OVERRIDES_PROPS_FILE_NAME);
+ }
+
+ /**
+ * Verifies that the connection to the database and all prepared statement
+ * are valid.
+ *
+ * @throws SQLException
+ */
+ private void checkConnection() throws SQLException
+ {
+ if (this.connection != null && this.connection.isValid(1))
+ {
+ return;
+ }
+
+ String filename;
+ try
+ {
+ File f = fas.getPrivatePersistentFile(
+ "props.hsql",
+ FileCategory.PROFILE);
+ filename = f.getAbsolutePath();
+ }
+ catch (Exception e)
+ {
+ throw new SQLException(e);
+ }
+
+ this.connection = DriverManager.getConnection(
+ "jdbc:hsqldb:file:"
+ + filename
+ + ";shutdown=true;hsqldb.write_delay=false;"
+ + "hsqldb.write_delay_millis=0");
+ Statement st = this.connection.createStatement();
+ st.executeUpdate(
+ "CREATE TABLE IF NOT EXISTS Props ("
+ + "k LONGVARCHAR UNIQUE, v LONGVARCHAR"
+ + ")");
+
+ this.selectExact = this.connection.prepareStatement(
+ "SELECT v FROM Props WHERE k=?");
+ this.selectLike = this.connection.prepareStatement(
+ "SELECT k, v FROM Props WHERE k LIKE ?");
+ this.selectAll = this.connection.prepareStatement(
+ "SELECT k, v FROM Props");
+ this.insertOrUpdate = this.connection.prepareStatement(
+ "MERGE INTO Props"
+ + " USING (VALUES(?,?)) AS i(k,v) ON Props.k = i.k"
+ + " WHEN MATCHED THEN UPDATE SET Props.v = i.v"
+ + " WHEN NOT MATCHED THEN INSERT (k, v) VALUES (i.k, i.v)");
+ this.delete = this.connection.prepareStatement(
+ "DELETE FROM Props WHERE k=?");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#setProperty(java
+ * .lang.String, java.lang.Object)
+ */
+ @Override
+ public synchronized void setProperty(String propertyName, Object property)
+ {
+ this.setProperty(propertyName, property, false);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#setProperty(java
+ * .lang.String, java.lang.Object, boolean)
+ */
+ @Override
+ public synchronized void setProperty(String propertyName, Object property,
+ boolean isSystem)
+ {
+ // a property with the same name as an existing system property cannot
+ // be set, so mark it as a system property
+ if (!isSystem && System.getProperty(propertyName) != null)
+ {
+ isSystem = true;
+ }
+
+ if (isSystem)
+ {
+ if (property == null)
+ {
+ System.clearProperty(propertyName);
+ return;
+ }
+
+ System.setProperty(propertyName, property.toString());
+ }
+ else
+ {
+ if (immutableDefaultProperties.containsKey(propertyName))
+ {
+ return;
+ }
+
+ try
+ {
+ this.checkConnection();
+ Object oldValue = this.getProperty(propertyName);
+ this.fireVetoableChange(propertyName, oldValue, property);
+ if (property == null)
+ {
+ this.delete.setString(1, propertyName);
+ this.delete.execute();
+ }
+ else
+ {
+ this.insertOrUpdate.setString(1, propertyName);
+ this.insertOrUpdate.setString(2, property.toString());
+ this.insertOrUpdate.execute();
+ }
+
+ this.fireChange(propertyName, oldValue, property);
+ }
+ catch (SQLException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#setProperties(java
+ * .util.Map)
+ */
+ @Override
+ public synchronized void setProperties(Map<String, Object> properties)
+ {
+ try
+ {
+ checkConnection();
+ this.connection.setAutoCommit(false);
+ for (Map.Entry<String, Object> e : properties.entrySet())
+ {
+ this.setProperty(e.getKey(), e.getValue(), false);
+ }
+
+ this.connection.commit();
+ this.connection.setAutoCommit(true);
+ }
+ catch (SQLException e1)
+ {
+ throw new RuntimeException(e1);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#getProperty(java
+ * .lang.String)
+ */
+ @Override
+ public synchronized Object getProperty(String propertyName)
+ {
+ Object value = immutableDefaultProperties.get(propertyName);
+ if (value != null)
+ {
+ return value;
+ }
+
+ try
+ {
+ this.checkConnection();
+ this.selectExact.setString(1, propertyName);
+ ResultSet q = this.selectExact.executeQuery();
+ if (q.next())
+ {
+ value = q.getString(1);
+ }
+ }
+ catch (SQLException e)
+ {
+ logger.error(e);
+ throw new RuntimeException(e);
+ }
+
+ if (value != null)
+ {
+ return value;
+ }
+
+ value = defaultProperties.get(propertyName);
+ if (value != null)
+ {
+ return value;
+ }
+
+ return System.getProperty(propertyName);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#removeProperty(java
+ * .lang.String)
+ */
+ @Override
+ public synchronized void removeProperty(String propertyName)
+ {
+ //remove all properties
+ for (String child : this.getPropertyNamesByPrefix(propertyName, false))
+ {
+ removeProperty(child);
+ }
+
+ this.setProperty(propertyName, null, false);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#getAllPropertyNames
+ * ()
+ */
+ @Override
+ public List<String> getAllPropertyNames()
+ {
+ List<String> data = new ArrayList<String>(
+ immutableDefaultProperties.keySet());
+ data.addAll(defaultProperties.keySet());
+ try
+ {
+ this.checkConnection();
+ ResultSet q = this.selectAll.executeQuery();
+ while (q.next())
+ {
+ data.add(q.getString(1));
+ }
+ }
+ catch (SQLException e)
+ {
+ logger.error(e);
+ throw new RuntimeException(e);
+ }
+
+ return data;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService
+ * #getPropertyNamesByPrefix(java.lang.String, boolean)
+ */
+ @Override
+ public List<String> getPropertyNamesByPrefix(String prefix,
+ boolean exactPrefixMatch)
+ {
+ try
+ {
+ List<String> resultSet = new ArrayList<String>(50);
+ this.checkConnection();
+ this.selectLike.setString(1, prefix + "%");
+ ResultSet q = this.selectLike.executeQuery();
+ while (q.next())
+ {
+ String key = q.getString(1);
+ int ix = key.lastIndexOf('.');
+ if(ix == -1)
+ {
+ continue;
+ }
+
+ String keyPrefix = key.substring(0, ix);
+ if(exactPrefixMatch)
+ {
+ if(prefix.equals(keyPrefix))
+ {
+ resultSet.add(key);
+ }
+ }
+ else
+ {
+ if(keyPrefix.startsWith(prefix))
+ {
+ resultSet.add(key);
+ }
+ }
+ }
+
+ return resultSet;
+ }
+ catch (SQLException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService
+ * #getPropertyNamesBySuffix(java.lang.String)
+ */
+ @Override
+ public List<String> getPropertyNamesBySuffix(String suffix)
+ {
+ try
+ {
+ List<String> resultKeySet = new ArrayList<String>(20);
+ this.checkConnection();
+ this.selectLike.setString(1, "%" + suffix);
+ ResultSet q = this.selectLike.executeQuery();
+ while (q.next())
+ {
+ String key = q.getString(1);
+ int ix = key.lastIndexOf('.');
+ if (ix != -1 && suffix.equals(key.substring(ix + 1)))
+ resultKeySet.add(key);
+ }
+
+ return resultKeySet;
+ }
+ catch (SQLException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#getString(java.lang
+ * .String)
+ */
+ @Override
+ public String getString(String propertyName)
+ {
+ String value = (String)this.getProperty(propertyName);
+ if (value != null)
+ {
+ value = value.trim();
+ if (value.length() == 0)
+ {
+ return null;
+ }
+ }
+
+ return value;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#getString(java.lang
+ * .String, java.lang.String)
+ */
+ @Override
+ public String getString(String propertyName, String defaultValue)
+ {
+ String value = this.getString(propertyName);
+ if (value == null)
+ {
+ return defaultValue;
+ }
+
+ return value;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#getBoolean(java.
+ * lang.String, boolean)
+ */
+ @Override
+ public boolean getBoolean(String propertyName, boolean defaultValue)
+ {
+ Object value = this.getProperty(propertyName);
+ if (value == null)
+ {
+ return defaultValue;
+ }
+
+ return Boolean.parseBoolean(value.toString());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#getInt(java.lang
+ * .String, int)
+ */
+ @Override
+ public int getInt(String propertyName, int defaultValue)
+ {
+ Object value = this.getProperty(propertyName);
+ if (value == null)
+ {
+ return defaultValue;
+ }
+
+ return Integer.parseInt(value.toString());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#getLong(java.lang
+ * .String, long)
+ */
+ @Override
+ public long getLong(String propertyName, long defaultValue)
+ {
+ Object value = this.getProperty(propertyName);
+ if (value == null)
+ {
+ return defaultValue;
+ }
+
+ return Long.parseLong(value.toString());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jitsi.service.configuration.ConfigurationService#
+ * addPropertyChangeListener(java.beans.PropertyChangeListener)
+ */
+ @Override
+ public void addPropertyChangeListener(PropertyChangeListener listener)
+ {
+ this.listeners.put(null, listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jitsi.service.configuration.ConfigurationService#
+ * removePropertyChangeListener(java.beans.PropertyChangeListener)
+ */
+ @Override
+ public void removePropertyChangeListener(PropertyChangeListener listener)
+ {
+ this.listeners.remove(null, listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jitsi.service.configuration.ConfigurationService#
+ * addPropertyChangeListener(java.lang.String,
+ * java.beans.PropertyChangeListener)
+ */
+ @Override
+ public void addPropertyChangeListener(String propertyName,
+ PropertyChangeListener listener)
+ {
+ this.listeners.put(propertyName, listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jitsi.service.configuration.ConfigurationService#
+ * removePropertyChangeListener(java.lang.String,
+ * java.beans.PropertyChangeListener)
+ */
+ @Override
+ public void removePropertyChangeListener(String propertyName,
+ PropertyChangeListener listener)
+ {
+ this.listeners.remove(propertyName, listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jitsi.service.configuration.ConfigurationService#
+ * addVetoableChangeListener
+ * (org.jitsi.service.configuration.ConfigVetoableChangeListener)
+ */
+ @Override
+ public void addVetoableChangeListener(ConfigVetoableChangeListener listener)
+ {
+ this.vetoListeners.put(null, listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jitsi.service.configuration.ConfigurationService#
+ * removeVetoableChangeListener
+ * (org.jitsi.service.configuration.ConfigVetoableChangeListener)
+ */
+ @Override
+ public void removeVetoableChangeListener(
+ ConfigVetoableChangeListener listener)
+ {
+ this.vetoListeners.remove(null, listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jitsi.service.configuration.ConfigurationService#
+ * addVetoableChangeListener(java.lang.String,
+ * org.jitsi.service.configuration.ConfigVetoableChangeListener)
+ */
+ @Override
+ public void addVetoableChangeListener(String propertyName,
+ ConfigVetoableChangeListener listener)
+ {
+ this.vetoListeners.put(propertyName, listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jitsi.service.configuration.ConfigurationService#
+ * removeVetoableChangeListener(java.lang.String,
+ * org.jitsi.service.configuration.ConfigVetoableChangeListener)
+ */
+ @Override
+ public void removeVetoableChangeListener(String propertyName,
+ ConfigVetoableChangeListener listener)
+ {
+ this.vetoListeners.remove(propertyName, listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#storeConfiguration()
+ */
+ @Override
+ public void storeConfiguration() throws IOException
+ {
+ try
+ {
+ this.connection.close();
+ }
+ catch (SQLException e)
+ {
+ logger.error(e);
+ }
+ finally
+ {
+ this.connection = null;
+ }
+ }
+
+ /**
+ * Does nothing. The database cannot be edited from the outside.
+ */
+ @Override
+ public void reloadConfiguration() throws IOException
+ {
+ // nothing to do, the file cannot be edited outside
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#purgeStoredConfiguration
+ * ()
+ */
+ @Override
+ public void purgeStoredConfiguration()
+ {
+ try
+ {
+ this.checkConnection();
+ Statement st = this.connection.createStatement();
+ st.executeUpdate("TRUNCATE TABLE Props");
+ }
+ catch (SQLException e)
+ {
+ logger.error(e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#getScHomeDirName()
+ */
+ @Override
+ public String getScHomeDirName()
+ {
+ return System.getProperty(PNAME_SC_HOME_DIR_NAME);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#getScHomeDirLocation
+ * ()
+ */
+ @Override
+ public String getScHomeDirLocation()
+ {
+ return System.getProperty(PNAME_SC_HOME_DIR_LOCATION);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jitsi.service.configuration.ConfigurationService#getConfigurationFilename
+ * ()
+ */
+ @Override
+ public String getConfigurationFilename()
+ {
+ return "props.hsql.script";
+ }
+
+
+ /**
+ * Loads the specified default properties maps from the Jitsi installation
+ * directory. Typically this file is to be called for the default properties
+ * and the admin overrides.
+ *
+ * @param fileName the name of the file we need to load.
+ */
+ private void loadDefaultProperties(String fileName)
+ {
+ try
+ {
+ Properties fileProps = new Properties();
+
+ InputStream fileStream;
+ if(OSUtils.IS_ANDROID)
+ {
+ fileStream
+ = getClass().getClassLoader()
+ .getResourceAsStream(fileName);
+ }
+ else
+ {
+ fileStream = ClassLoader.getSystemResourceAsStream(fileName);
+ }
+
+ fileProps.load(fileStream);
+ fileStream.close();
+
+ // now get those properties and place them into the mutable and
+ // immutable properties maps.
+ for (Map.Entry<Object, Object> entry : fileProps.entrySet())
+ {
+ String name = (String) entry.getKey();
+ String value = (String) entry.getValue();
+
+ if ( name == null
+ || value == null
+ || name.trim().length() == 0)
+ {
+ continue;
+ }
+
+ if (name.startsWith("*"))
+ {
+ name = name.substring(1);
+
+ if(name.trim().length() == 0)
+ {
+ continue;
+ }
+
+ //it seems that we have a valid default immutable property
+ immutableDefaultProperties.put(name, value);
+
+ //in case this is an override, make sure we remove previous
+ //definitions of this property
+ defaultProperties.remove(name);
+ }
+ else
+ {
+ //this property is a regular, mutable default property.
+ defaultProperties.put(name, value);
+
+ //in case this is an override, make sure we remove previous
+ //definitions of this property
+ immutableDefaultProperties.remove(name);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ //we can function without defaults so we are just logging those.
+ logger.info("No defaults property file loaded: " + fileName
+ + ". Not a problem.");
+
+ if(logger.isDebugEnabled())
+ logger.debug("load exception", ex);
+ }
+ }
+
+ /**
+ * Notify all listening objects about a prospective change.
+ *
+ * @param propertyName The property that is going to change.
+ * @param oldValue The previous value of the property (can be <tt>null</tt>)
+ * @param newValue The new value of the property (can be <tt>null</tt>)
+ */
+ private void fireVetoableChange(String propertyName,
+ Object oldValue, Object newValue)
+ {
+ PropertyChangeEvent evt = new PropertyChangeEvent(
+ this,
+ propertyName,
+ oldValue,
+ newValue);
+
+ for (ConfigVetoableChangeListener l : vetoListeners.get(propertyName))
+ {
+ l.vetoableChange(evt);
+ }
+
+ for (ConfigVetoableChangeListener l : vetoListeners.get(null))
+ {
+ l.vetoableChange(evt);
+ }
+ }
+
+ /**
+ * Notify all listeners that a property has changed.
+ *
+ * @param propertyName The property that has just changed.
+ * @param oldValue The previous value of the property (can be <tt>null</tt>)
+ * @param newValue The new value of the property (can be <tt>null</tt>)
+ */
+ private void fireChange(String propertyName,
+ Object oldValue, Object newValue)
+ {
+ PropertyChangeEvent evt = new PropertyChangeEvent(
+ this,
+ propertyName,
+ oldValue,
+ newValue);
+
+ for (PropertyChangeListener l : listeners.get(propertyName))
+ {
+ l.propertyChange(evt);
+ }
+
+ for (PropertyChangeListener l : listeners.get(null))
+ {
+ l.propertyChange(evt);
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/configuration/configuration.manifest.mf b/src/net/java/sip/communicator/impl/configuration/configuration.manifest.mf
index 08273ce..db69160 100644
--- a/src/net/java/sip/communicator/impl/configuration/configuration.manifest.mf
+++ b/src/net/java/sip/communicator/impl/configuration/configuration.manifest.mf
@@ -5,7 +5,12 @@ Bundle-Vendor: jitsi.org
Bundle-Version: 0.0.1
Bundle-SymbolicName: net.java.sip.communicator.configuration
Import-Package: org.jitsi.service.configuration,
+ org.jitsi.service.fileaccess,
org.jitsi.service.libjitsi,
+ net.java.sip.communicator.util,
org.jitsi.util,
com.sun.jna,
- org.osgi.framework
+ org.osgi.framework,
+ org.hsqldb,
+ org.hsqldb.jdbc,
+ com.google.common.collect