package com.limegroup.gnutella.settings;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.limewire.service.ErrorService;
import org.limewire.setting.RemoteSettingController;
import org.limewire.setting.RemoteSettingManager;
/**
* A RemoteSettingManager that uses SIMPP to remotely control the settings.
* <p>
* Before this can be used, you MUST call setRemoteSettingController,
* otherwise activating any simpp settings will fail.
* (Note: this is typically done by calling SettingsFactory.setRemoteSettingManager
* with this instance.)
*/
public class SimppSettingsManager implements RemoteSettingManager {
private static final Log LOG = LogFactory.getLog(SimppSettingsManager.class);
/**
* The properties we create from the string we get via simpp message
* <p>
* LOCKING: _remoteController
*/
private final Properties _simppProps = new Properties();
/**
* A mapping of simppKeys to simppValues which have not been initialized
* yet. Newly created settings must check with this map to see if they
* should load default value or the simpp value.
* <p>
* LOCKING: _remoteController
*/
private final Map<String, String> _remainderSimppSettings = new HashMap<String, String>();
/** The controller used to set remote settings. */
private volatile RemoteSettingController _remoteController;
/**
* Call this method with the verified simppSettings which are used to
* replace other settings if they exist in the system.
*/
public void updateSimppSettings(String simppSettings) {
if(_remoteController == null)
throw new IllegalStateException("No RemoteSettingController set!");
synchronized(_remoteController) {
byte[] settings = null;
try {
settings = simppSettings.getBytes("UTF-8");
} catch (UnsupportedEncodingException uex) {
ErrorService.error(uex);
return;
}
ByteArrayInputStream bais = new ByteArrayInputStream(settings);
_simppProps.clear();
try {
_simppProps.load(bais);
} catch(IOException iox) {
LOG.error("IOX reading simpp properties", iox);
return;
}
activateSimppSettings();
}
}
/**
* Call this method if you want to activate the settings to the ones in
* this.simppProps.
*/
@SuppressWarnings({ "unchecked" })
public void activateSimppSettings() {
LOG.debug("activating new settings");
if(_remoteController == null)
throw new IllegalStateException("No RemoteSettingController set!");
synchronized(_remoteController) {
for(Map.Entry<Object, Object> entry : _simppProps.entrySet()) {
String key = (String)entry.getKey();
String value = (String)entry.getValue();
if(!_remoteController.updateSetting(key, value))
_remainderSimppSettings.put(key, value);
}
Set keys = _simppProps.keySet();
_remoteController.revertRemoteSettingsUnlessIn(keys);
}
}
/**
* @return the simpp value for a simppkey from the map that remembers simpp
* settings which have not been loaded yet. Removes the entry from the
* mapping since it is no longer needed, now that the setting has been
* created.
*/
public String getUnloadedValueFor(String simppKey) {
synchronized(_remoteController) {
return _remainderSimppSettings.remove(simppKey);
}
}
public void setRemoteSettingController(RemoteSettingController controller) {
_remoteController = controller;
}
}