Fixes a warning introduced in r5094 about the use of deprecated API.

cusax-fix
Lyubomir Marinov 17 years ago
parent b2f1b06ce6
commit 10064c4066

@ -9,9 +9,6 @@
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import net.java.sip.communicator.impl.configuration.xml.*;
import net.java.sip.communicator.service.configuration.*;
import net.java.sip.communicator.service.configuration.event.*;
import net.java.sip.communicator.service.fileaccess.*;
@ -19,8 +16,6 @@
import net.java.sip.communicator.util.xml.*;
import org.osgi.framework.*;
import org.w3c.dom.*;
import org.xml.sax.*;
/**
* A straight forward implementation of the ConfigurationService using an xml
@ -37,23 +32,6 @@ public class ConfigurationServiceImpl
{
private final Logger logger = Logger.getLogger(ConfigurationServiceImpl.class);
/**
* The XML Document containing the configuration file this service loaded.
*/
private Document propertiesDocument = null;
/** Name of the xml attribute containing property values */
private static final String ATTRIBUTE_VALUE = "value";
/**
* Name of the xml attribute indicating that a property is to be resolved
* in the system properties
*/
private static final String SYSTEM_ATTRIBUTE_NAME = "system";
/** The value of the Name of the xml attribute containing property values */
private static final String SYSTEM_ATTRIBUTE_TRUE = "true";
/**
* The name of the system property that stores the name of the configuration
* file.
@ -75,21 +53,6 @@ public class ConfigurationServiceImpl
private final ChangeEventDispatcher changeEventDispatcher =
new ChangeEventDispatcher(this);
/**
* The list of properties currently registered in the configuration service.
*/
private Map<String, Object> properties = new Hashtable<String, Object>();
/**
* Contains the properties that were initially loaded from the configuration
* file or (if the properties have been modified and saved since initially
* loaded) those that were last written to the file.We use the property so
* that we could determine which properties are new and do not have a
* corresponding node in the XMLDocument object.
*/
private Map<String, Object> fileExtractedProperties =
new Hashtable<String, Object>();
/**
* Indicates whether the service is started or stopped.
*/
@ -100,6 +63,8 @@ public class ConfigurationServiceImpl
*/
private FileAccessService faService = null;
private final ConfigurationStore store = new PropertyConfigurationStore();
/**
* Sets the property with the specified name to the specified value. Calling
* this method would first trigger a PropertyChangeEvent that will
@ -153,7 +118,7 @@ public void setProperty(String propertyName, Object property,
logger.trace(propertyName + "( oldValue=" + oldValue
+ ", newValue=" + property + ".");
//once set system, a property remains system event if the user
//once set system, a property remains system even if the user
//specified sth else
if (isSystem(propertyName))
@ -161,9 +126,7 @@ public void setProperty(String propertyName, Object property,
if (property == null)
{
properties.remove(propertyName);
fileExtractedProperties.remove(propertyName);
store.removeProperty(propertyName);
if (isSystem)
{
@ -178,12 +141,11 @@ public void setProperty(String propertyName, Object property,
//in case this is a system property, we must only store it
//in the System property set and keep only a ref locally.
System.setProperty(propertyName, property.toString());
properties.put(propertyName,
new PropertyReference(propertyName));
store.setSystemProperty(propertyName);
}
else
{
properties.put(propertyName, property);
store.setNonSystemProperty(propertyName, property);
}
}
if (changeEventDispatcher.hasPropertyChangeListeners(propertyName))
@ -210,7 +172,6 @@ public void setProperty(String propertyName, Object property,
* All properties with prefix propertyName will also be removed.
* <p>
* @param propertyName the name of the property to change.
* @param property the new value of the specified property.
* @throws PropertyVetoException in case the changed has been refused by
* at least one propertychange listener.
*/
@ -237,9 +198,7 @@ public void removeProperty(String propertyName)
logger.trace("Will remove prop: " + propertyName + ".");
properties.remove(propertyName);
fileExtractedProperties.remove(propertyName);
store.removeProperty(propertyName);
if (changeEventDispatcher.hasPropertyChangeListeners(propertyName))
changeEventDispatcher.firePropertyChange(
@ -259,19 +218,13 @@ public void removeProperty(String propertyName)
/**
* Returns the value of the property with the specified name or null if no
* such property exists.
*
* @param propertyName the name of the property that is being queried.
* @return the value of the property with the specified name.
*/
public Object getProperty(String propertyName)
{
Object value = properties.get(propertyName);
//if this is a property reference make sure we return the referenced
//value and not the reference itself
if(value instanceof PropertyReference)
return ((PropertyReference)value).getValue();
else
return value;
return store.getProperty(propertyName);
}
/**
@ -308,7 +261,7 @@ public List<String> getPropertyNamesByPrefix(String prefix, boolean exactPrefixM
{
List<String> resultKeySet = new LinkedList<String>();
for (String key : properties.keySet())
for (String key : store.getPropertyNames())
{
int ix = key.lastIndexOf('.');
@ -468,27 +421,10 @@ void start()
public void reloadConfiguration()
throws IOException, XMLException
{
properties = new Hashtable<String, Object>();
this.configurationFile = null;
fileExtractedProperties =
loadConfiguration(getConfigurationFile());
this.properties.putAll(fileExtractedProperties);
}
File file = getConfigurationFile();
/**
* Loads the contents of the specified configuration file into the local
* properties object.
* @param file a reference to the configuration file to load.
* @return a hashtable containing all properties extracted from the
* specified file.
*
* @throws IOException if the specified file does not exist
* @throws XMLException if there is a problem with the file syntax.
*/
Map<String, Object> loadConfiguration(File file)
throws IOException, XMLException
{
// restore the file if needed
FailSafeTransaction trans = this.faService
.createFailSafeTransaction(file);
@ -498,51 +434,8 @@ Map<String, Object> loadConfiguration(File file)
logger.error("can't restore the configuration file before loading" +
" it", e);
}
try
{
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Map<String, Object> properties = new Hashtable<String, Object>();
//if the file is empyt (or contains only sth insignificant)
//ifnore it and create a new document.
if(file.length() < "<sip-communicator>".length()*2)
propertiesDocument = createPropertiesDocument();
else
propertiesDocument = builder.parse(file);
Node root = propertiesDocument.getFirstChild();
Node currentNode = null;
NodeList children = root.getChildNodes();
for(int i = 0; i < children.getLength(); i++)
{
currentNode = children.item(i);
if(currentNode.getNodeType() == Node.ELEMENT_NODE)
{
StringBuffer propertyNameBuff = new StringBuffer();
propertyNameBuff.append(currentNode.getNodeName());
loadNode(currentNode, propertyNameBuff, properties);
}
}
return properties;
}
catch(SAXException ex)
{
logger.error("Error parsing configuration file", ex);
throw new XMLException(ex.getMessage(), ex);
}
catch(ParserConfigurationException ex)
{
//it is not highly probable that this might happen - so lets just
//log it.
logger.error("Error finding configuration for default parsers", ex);
return new Hashtable<String, Object>();
}
store.reloadConfiguration(file);
}
public synchronized void storeConfiguration()
@ -551,214 +444,37 @@ public synchronized void storeConfiguration()
storeConfiguration(getConfigurationFile());
}
private Document createPropertiesDocument()
{
if(propertiesDocument == null)
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try
{
builder = factory.newDocumentBuilder();
}
catch (ParserConfigurationException ex)
{
logger.error("Failed to create a DocumentBuilder", ex);
return null;
}
propertiesDocument = builder.newDocument();
propertiesDocument.appendChild(
propertiesDocument.createElement("sip-communicator"));
}
return propertiesDocument;
}
/**
* Stores local properties in the specified configuration file.
*
* @param file a reference to the configuration file where properties should
* be stored.
* be stored.
* @throws IOException if there was a problem writing to the specified file.
*/
private void storeConfiguration(File file)
throws IOException
private void storeConfiguration(File file) throws IOException
{
if(!started)
throw new IllegalStateException("Service is stopped or has not been started");
//resolve the properties that were initially in the file - back to
//the document.
if (propertiesDocument == null)
propertiesDocument = createPropertiesDocument();
Node root = propertiesDocument.getFirstChild();
Node currentNode = null;
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
{
currentNode = children.item(i);
if (currentNode.getNodeType() == Node.ELEMENT_NODE)
{
StringBuffer propertyNameBuff = new StringBuffer();
propertyNameBuff.append(currentNode.getNodeName());
updateNode(currentNode, propertyNameBuff, properties);
}
}
//create in the document the properties that were added by other
//bundles after the initial property load.
if (!started)
throw new IllegalStateException(
"Service is stopped or has not been started");
Map<String, Object> newlyAddedProperties = cloneProperties();
//remove those that were originally there;
for (String propName : fileExtractedProperties.keySet())
newlyAddedProperties.remove(propName);
this.processNewProperties(propertiesDocument,
newlyAddedProperties);
//write the file.
// write the file.
File config = getConfigurationFile();
FailSafeTransaction trans = this.faService
.createFailSafeTransaction(config);
try {
FailSafeTransaction trans =
this.faService.createFailSafeTransaction(config);
try
{
trans.beginTransaction();
OutputStream stream = new FileOutputStream(config);
XMLUtils.indentedWriteXML(
propertiesDocument, stream);
stream.close();
trans.commit();
} catch (Exception e) {
logger.error("can't write data in the configuration file", e);
trans.rollback();
}
}
/**
* Loads the contents of the specified node and its children into the local
* properties. Any nodes marked as "system" will also be resolved in the
* system properties.
* @param node the root node that we shold load together with its children
* @param propertyNameBuff a StringBuffer containing the prefix describing
* the route to the specified node including its one name
* @param properties the dictionary object where all properties extracted
* from this node and its children should be recorded.
*/
private void loadNode(Node node,
StringBuffer propertyNameBuff,
Map<String, Object> properties)
{
Node currentNode = null;
NodeList children = node.getChildNodes();
for(int i = 0; i < children.getLength(); i++)
{
currentNode = children.item(i);
store.storeConfiguration(stream);
if(currentNode.getNodeType() == Node.ELEMENT_NODE)
{
StringBuffer newPropBuff =
new StringBuffer(propertyNameBuff
+ "." +currentNode.getNodeName());
String value = XMLConfUtils.getAttribute(
currentNode, ATTRIBUTE_VALUE);
String propertyType =
XMLConfUtils.getAttribute(currentNode, SYSTEM_ATTRIBUTE_NAME);
// the value attr is present we must handle the desired property
if(value != null)
{
//if the property is marked as "system", we should resolve
//it against the system properties and only store a
//reference locally. this is normally done for properties
//that are supposed to configure underlying libraries.
if(propertyType != null
&& propertyType.equals(SYSTEM_ATTRIBUTE_TRUE))
{
properties.put(
newPropBuff.toString(),
new PropertyReference(newPropBuff.toString()));
System.setProperty(newPropBuff.toString(), value);
}
else
{
properties.put(newPropBuff.toString(), value);
}
}
//load child nodes
loadNode(currentNode, newPropBuff, properties);
}
stream.close();
trans.commit();
}
}
/**
* Updates the value of the specified node and its children to reflect those
* in the properties file. Nodes marked as "system" will be updated from
* the specified properties object and not from the system properties since
* if any intentional change (through a configuration form) has occurred
* it will have been made there.
*
* @param node the root node that we shold update together with its children
* @param propertyNameBuff a StringBuffer containing the prefix describing
* the dot separated route to the specified node including its one name
* @param properties the dictionary object where the up to date values of
* the node should be queried.
*/
private void updateNode(Node node,
StringBuffer propertyNameBuff,
Map<String, Object> properties)
{
Node currentNode = null;
NodeList children = node.getChildNodes();
for(int i = 0; i < children.getLength(); i++)
catch (Exception e)
{
currentNode = children.item(i);
if(currentNode.getNodeType() == Node.ELEMENT_NODE)
{
StringBuffer newPropBuff =
new StringBuffer(propertyNameBuff.toString()).append(".")
.append(currentNode.getNodeName());
Attr attr =
((Element)currentNode).getAttributeNode(ATTRIBUTE_VALUE);
if(attr != null)
{
//update the corresponding node
Object value = properties.get(newPropBuff.toString());
if(value == null)
{
node.removeChild(currentNode);
continue;
}
boolean isSystem = value instanceof PropertyReference;
String prop = isSystem
?((PropertyReference)value).getValue().toString()
:value.toString();
attr.setNodeValue(prop);
//in case the property has changed to system since the last
//load - update the conf file accordingly.
if(isSystem)
((Element)currentNode).setAttribute(
SYSTEM_ATTRIBUTE_NAME, SYSTEM_ATTRIBUTE_TRUE);
else
((Element)currentNode).removeAttribute(
SYSTEM_ATTRIBUTE_NAME);
}
//update child nodes
updateNode(currentNode, newPropBuff, properties);
}
logger.error("can't write data in the configuration file", e);
trans.rollback();
}
}
@ -805,8 +521,9 @@ public String getScHomeDirLocation()
//now save all this as a configuration property so that we don't
//have to look for it in the sys props next time and so that it is
//available for other bundles to consult.
properties.put(PNAME_SC_HOME_DIR_LOCATION, scHomeDirLocation);
// available for other bundles to consult.
store.setNonSystemProperty(PNAME_SC_HOME_DIR_LOCATION,
scHomeDirLocation);
}
return scHomeDirLocation;
@ -841,8 +558,8 @@ public String getScHomeDirName()
//now save all this as a configuration property so that we don't
//have to look for it in the sys props next time and so that it is
//available for other bundles to consult.
properties.put(PNAME_SC_HOME_DIR_NAME, scHomeDirName);
// available for other bundles to consult.
store.setNonSystemProperty(PNAME_SC_HOME_DIR_NAME, scHomeDirName);
}
return scHomeDirName;
@ -931,7 +648,7 @@ File createConfigurationFile()
PrintWriter writer = new PrintWriter(new FileWriter(
configFileInUserHomeDir));
String line = null;
String line;
logger.debug("Copying properties file:");
while ( (line = reader.readLine()) != null)
{
@ -948,73 +665,6 @@ File createConfigurationFile()
}
}
/**
* Creates new entries in the XML <tt>doc</tt> for every element in the
* <tt>newProperties</tt> table.
*
* @param doc the XML <tt>Document</tt> where the new entries should be
* created
* @param newProperties the table containing the properties that are to be
* introduced in the document.
*/
private void processNewProperties(Document doc,
Map<String, Object> newProperties)
{
for (Map.Entry<String, Object> entry : newProperties.entrySet())
{
String key = entry.getKey();
Object value = entry.getValue();
boolean isSystem = value instanceof PropertyReference;
value = isSystem
?((PropertyReference)value).getValue()
:value;
processNewProperty(doc, key, value.toString(), isSystem);
}
}
/**
* Creates an entry in the xml <tt>doc</tt> for the specified key value
* pair.
* @param doc the XML <tt>document</tt> to update.
* @param key the value of the <tt>name</tt> attribute for the new entry
* @param value the value of the <tt>value</tt> attribue for the new
* @param isSystem specifies whether this is a system property (system
* attribute will be set to true).
* entry.
*/
private void processNewProperty(Document doc,
String key,
String value,
boolean isSystem)
{
StringTokenizer tokenizer = new StringTokenizer(key, ".");
String[] toks = new String[tokenizer.countTokens()];
int i = 0;
while(tokenizer.hasMoreTokens())
toks[i++] = tokenizer.nextToken();
String[] chain = new String[toks.length - 1];
for (int j = 0; j < chain.length; j++)
{
chain[j] = toks[j];
}
String nodeName = toks[toks.length - 1];
Element parent = XMLConfUtils.createLastPathComponent(doc, chain);
Element newNode = XMLConfUtils.findChild(parent, nodeName);
if (newNode == null)
{
newNode = doc.createElement(nodeName);
parent.appendChild(newNode);
}
newNode.setAttribute("value", value);
if(isSystem)
newNode.setAttribute(SYSTEM_ATTRIBUTE_NAME, SYSTEM_ATTRIBUTE_TRUE);
}
/**
* Returns the value of the specified java system property. In case the
* value was a zero length String or one that only contained whitespaces,
@ -1092,59 +742,6 @@ public int getInt(String propertyName, int defaultValue)
return intValue;
}
/**
* We use property references when we'd like to store system properties.
* Simply storing System properties in our properties Map would not be
* enough since it will lead to mismatching values for the same property in
* the System property set and in our local set of properties. Storing them
* only in the System property set OTOH is a bit clumsy since it obliges
* bundles to use to different configuration property sources. For that
* reason, every time we get handed a property labeled as System, in stead
* of storing its actual value in the local property set we store a
* PropertyReference instance that will retrive it from the system
* properties when necessary.
*/
private class PropertyReference
{
private String propertyName = null;
PropertyReference(String propertyName)
{
this.propertyName = propertyName;
}
/**
* Return the actual value of the property as recorded in the System
* properties.
* @return the valued of the property as recorded in the System props.
*/
public Object getValue()
{
return System.getProperty(propertyName);
}
}
/**
* Returns a copy of the Map containing all configuration properties
* @return a Map clone of the current configuration property set.
*/
private Map<String, Object> cloneProperties()
{
// at the time I'm writing this method we're implementing the
// configuration service through the use of a hashtable. this may very
// well change one day so let's not be presumptuous
if (properties instanceof Hashtable)
return (Map<String, Object>) ((Hashtable) properties).clone();
if (properties instanceof HashMap)
return (Map<String, Object>) ((HashMap) properties).clone();
if (properties instanceof TreeMap)
return (Map<String, Object>) ((TreeMap) properties).clone();
// well you can't say that I didn't try!!!
return new Hashtable<String, Object>(properties);
}
/**
* Determines whether the property with the specified
* <tt>propertyName</tt> has been previously declared as System
@ -1157,8 +754,7 @@ private Map<String, Object> cloneProperties()
*/
private boolean isSystem(String propertyName)
{
return properties.containsKey(propertyName)
&& properties.get(propertyName) instanceof PropertyReference;
return store.isSystem(propertyName);
}
/**

@ -0,0 +1,33 @@
/*
* SIP Communicator, 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.io.*;
import net.java.sip.communicator.util.xml.*;
/**
* @author Lubomir Marinov
*/
public interface ConfigurationStore
{
public Object getProperty(String name);
public String[] getPropertyNames();
public boolean isSystem(String name);
public void reloadConfiguration(File file) throws IOException, XMLException;
public void removeProperty(String name);
public void setNonSystemProperty(String name, Object value);
public void setSystemProperty(String name);
public void storeConfiguration(OutputStream out) throws IOException;
}

@ -0,0 +1,73 @@
/*
* SIP Communicator, 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.io.*;
import java.util.*;
/**
* @author Lubomir Marinov
*/
public class PropertyConfigurationStore
implements ConfigurationStore
{
private final Properties properties = new Properties();
public Object getProperty(String name)
{
return properties.get(name);
}
public String[] getPropertyNames()
{
synchronized (properties)
{
Set<Object> propertyNames = properties.keySet();
return propertyNames.toArray(new String[propertyNames.size()]);
}
}
public boolean isSystem(String name)
{
return (System.getProperty(name) != null);
}
public void reloadConfiguration(File file) throws IOException
{
properties.clear();
InputStream in = new BufferedInputStream(new FileInputStream(file));
try
{
properties.load(in);
}
finally
{
in.close();
}
}
public void removeProperty(String name)
{
properties.remove(name);
}
public void setNonSystemProperty(String name, Object value)
{
properties.setProperty(name, value.toString());
}
public void setSystemProperty(String name)
{
removeProperty(name);
}
public void storeConfiguration(OutputStream out) throws IOException
{
properties.store(out, null);
}
}

@ -0,0 +1,473 @@
/*
* SIP Communicator, 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.xml;
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import net.java.sip.communicator.impl.configuration.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.xml.*;
public class XMLConfigurationStore
implements ConfigurationStore
{
private static final Logger logger =
Logger.getLogger(XMLConfigurationStore.class);
/** Name of the xml attribute containing property values */
private static final String ATTRIBUTE_VALUE = "value";
/**
* Name of the xml attribute indicating that a property is to be resolved in
* the system properties
*/
private static final String SYSTEM_ATTRIBUTE_NAME = "system";
/** The value of the Name of the xml attribute containing property values */
private static final String SYSTEM_ATTRIBUTE_TRUE = "true";
/**
* The list of properties currently registered in the configuration service.
*/
private Map<String, Object> properties = new Hashtable<String, Object>();
/**
* Contains the properties that were initially loaded from the configuration
* file or (if the properties have been modified and saved since initially
* loaded) those that were last written to the file.We use the property so
* that we could determine which properties are new and do not have a
* corresponding node in the XMLDocument object.
*/
private Map<String, Object> fileExtractedProperties =
new Hashtable<String, Object>();
/**
* The XML Document containing the configuration file this service loaded.
*/
private Document propertiesDocument;
/**
* Returns a copy of the Map containing all configuration properties
* @return a Map clone of the current configuration property set.
*/
private Map<String, Object> cloneProperties()
{
// at the time I'm writing this method we're implementing the
// configuration service through the use of a hashtable. this may very
// well change one day so let's not be presumptuous
if (properties instanceof Hashtable)
return (Map<String, Object>) ((Hashtable) properties).clone();
if (properties instanceof HashMap)
return (Map<String, Object>) ((HashMap) properties).clone();
if (properties instanceof TreeMap)
return (Map<String, Object>) ((TreeMap) properties).clone();
// well you can't say that I didn't try!!!
return new Hashtable<String, Object>(properties);
}
private Document createPropertiesDocument()
{
if (propertiesDocument == null)
{
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try
{
builder = factory.newDocumentBuilder();
}
catch (ParserConfigurationException ex)
{
logger.error("Failed to create a DocumentBuilder", ex);
return null;
}
propertiesDocument = builder.newDocument();
propertiesDocument.appendChild(propertiesDocument
.createElement("sip-communicator"));
}
return propertiesDocument;
}
public Object getProperty(String propertyName)
{
Object value = properties.get(propertyName);
// if this is a property reference make sure we return the referenced
// value and not the reference itself
if (value instanceof PropertyReference)
return ((PropertyReference) value).getValue();
else
return value;
}
public String[] getPropertyNames()
{
Set<String> propertyNames = properties.keySet();
return propertyNames.toArray(new String[propertyNames.size()]);
}
public boolean isSystem(String propertyName)
{
return properties.get(propertyName) instanceof PropertyReference;
}
/**
* Loads the contents of the specified configuration file into the local
* properties object.
* @param file a reference to the configuration file to load.
* @return a hashtable containing all properties extracted from the
* specified file.
*
* @throws IOException if the specified file does not exist
* @throws XMLException if there is a problem with the file syntax.
*/
private Map<String, Object> loadConfiguration(File file)
throws IOException,
XMLException
{
try
{
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Map<String, Object> properties = new Hashtable<String, Object>();
//if the file is empty (or contains only sth insignificant)
//ifnore it and create a new document.
if(file.length() < "<sip-communicator>".length()*2)
propertiesDocument = createPropertiesDocument();
else
propertiesDocument = builder.parse(file);
Node root = propertiesDocument.getFirstChild();
Node currentNode = null;
NodeList children = root.getChildNodes();
for(int i = 0; i < children.getLength(); i++)
{
currentNode = children.item(i);
if(currentNode.getNodeType() == Node.ELEMENT_NODE)
{
StringBuffer propertyNameBuff = new StringBuffer();
propertyNameBuff.append(currentNode.getNodeName());
loadNode(currentNode, propertyNameBuff, properties);
}
}
return properties;
}
catch(SAXException ex)
{
logger.error("Error parsing configuration file", ex);
throw new XMLException(ex.getMessage(), ex);
}
catch(ParserConfigurationException ex)
{
//it is not highly probable that this might happen - so lets just
//log it.
logger.error("Error finding configuration for default parsers", ex);
return new Hashtable<String, Object>();
}
}
/**
* Loads the contents of the specified node and its children into the local
* properties. Any nodes marked as "system" will also be resolved in the
* system properties.
* @param node the root node that we should load together with its children
* @param propertyNameBuff a StringBuffer containing the prefix describing
* the route to the specified node including its one name
* @param properties the dictionary object where all properties extracted
* from this node and its children should be recorded.
*/
private void loadNode(Node node,
StringBuffer propertyNameBuff,
Map<String, Object> properties)
{
Node currentNode = null;
NodeList children = node.getChildNodes();
for(int i = 0; i < children.getLength(); i++)
{
currentNode = children.item(i);
if(currentNode.getNodeType() == Node.ELEMENT_NODE)
{
StringBuffer newPropBuff =
new StringBuffer(propertyNameBuff
+ "." +currentNode.getNodeName());
String value = XMLConfUtils.getAttribute(
currentNode, ATTRIBUTE_VALUE);
String propertyType =
XMLConfUtils.getAttribute(currentNode, SYSTEM_ATTRIBUTE_NAME);
// the value attr is present we must handle the desired property
if(value != null)
{
//if the property is marked as "system", we should resolve
//it against the system properties and only store a
//reference locally. this is normally done for properties
//that are supposed to configure underlying libraries.
if(propertyType != null
&& propertyType.equals(SYSTEM_ATTRIBUTE_TRUE))
{
properties.put(
newPropBuff.toString(),
new PropertyReference(newPropBuff.toString()));
System.setProperty(newPropBuff.toString(), value);
}
else
{
properties.put(newPropBuff.toString(), value);
}
}
//load child nodes
loadNode(currentNode, newPropBuff, properties);
}
}
}
/**
* Creates new entries in the XML <tt>doc</tt> for every element in the
* <tt>newProperties</tt> table.
*
* @param doc the XML <tt>Document</tt> where the new entries should be
* created
* @param newProperties the table containing the properties that are to be
* introduced in the document.
*/
private void processNewProperties(Document doc,
Map<String, Object> newProperties)
{
for (Map.Entry<String, Object> entry : newProperties.entrySet())
{
String key = entry.getKey();
Object value = entry.getValue();
boolean isSystem = value instanceof PropertyReference;
value = isSystem
?((PropertyReference)value).getValue()
:value;
processNewProperty(doc, key, value.toString(), isSystem);
}
}
/**
* Creates an entry in the xml <tt>doc</tt> for the specified key value
* pair.
* @param doc the XML <tt>document</tt> to update.
* @param key the value of the <tt>name</tt> attribute for the new entry
* @param value the value of the <tt>value</tt> attribue for the new
* @param isSystem specifies whether this is a system property (system
* attribute will be set to true).
* entry.
*/
private void processNewProperty(Document doc,
String key,
String value,
boolean isSystem)
{
StringTokenizer tokenizer = new StringTokenizer(key, ".");
String[] toks = new String[tokenizer.countTokens()];
int i = 0;
while(tokenizer.hasMoreTokens())
toks[i++] = tokenizer.nextToken();
String[] chain = new String[toks.length - 1];
for (int j = 0; j < chain.length; j++)
{
chain[j] = toks[j];
}
String nodeName = toks[toks.length - 1];
Element parent = XMLConfUtils.createLastPathComponent(doc, chain);
Element newNode = XMLConfUtils.findChild(parent, nodeName);
if (newNode == null)
{
newNode = doc.createElement(nodeName);
parent.appendChild(newNode);
}
newNode.setAttribute("value", value);
if(isSystem)
newNode.setAttribute(SYSTEM_ATTRIBUTE_NAME, SYSTEM_ATTRIBUTE_TRUE);
}
public void reloadConfiguration(File file) throws IOException, XMLException
{
properties = new Hashtable<String, Object>();
fileExtractedProperties = loadConfiguration(file);
properties.putAll(fileExtractedProperties);
}
public void removeProperty(String propertyName)
{
properties.remove(propertyName);
fileExtractedProperties.remove(propertyName);
}
public void setNonSystemProperty(String propertyName, Object property)
{
properties.put(propertyName, property);
}
public void setSystemProperty(String propertyName)
{
setNonSystemProperty(propertyName, new PropertyReference(propertyName));
}
public void storeConfiguration(OutputStream out)
{
// resolve the properties that were initially in the file - back to
// the document.
if (propertiesDocument == null)
propertiesDocument = createPropertiesDocument();
Node root = propertiesDocument.getFirstChild();
Node currentNode = null;
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
{
currentNode = children.item(i);
if (currentNode.getNodeType() == Node.ELEMENT_NODE)
{
StringBuffer propertyNameBuff = new StringBuffer();
propertyNameBuff.append(currentNode.getNodeName());
updateNode(currentNode, propertyNameBuff, properties);
}
}
// create in the document the properties that were added by other
// bundles after the initial property load.
Map<String, Object> newlyAddedProperties = cloneProperties();
// remove those that were originally there;
for (String propName : fileExtractedProperties.keySet())
newlyAddedProperties.remove(propName);
this.processNewProperties(propertiesDocument, newlyAddedProperties);
XMLUtils.indentedWriteXML(propertiesDocument, out);
}
/**
* Updates the value of the specified node and its children to reflect those
* in the properties file. Nodes marked as "system" will be updated from the
* specified properties object and not from the system properties since if
* any intentional change (through a configuration form) has occurred it
* will have been made there.
*
* @param node the root node that we shold update together with its children
* @param propertyNameBuff a StringBuffer containing the prefix describing
* the dot separated route to the specified node including its
* one name
* @param properties the dictionary object where the up to date values of
* the node should be queried.
*/
private void updateNode(Node node, StringBuffer propertyNameBuff,
Map<String, Object> properties)
{
Node currentNode = null;
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
{
currentNode = children.item(i);
if (currentNode.getNodeType() == Node.ELEMENT_NODE)
{
StringBuffer newPropBuff =
new StringBuffer(propertyNameBuff.toString()).append(".")
.append(currentNode.getNodeName());
Attr attr =
((Element) currentNode).getAttributeNode(ATTRIBUTE_VALUE);
if (attr != null)
{
// update the corresponding node
Object value = properties.get(newPropBuff.toString());
if (value == null)
{
node.removeChild(currentNode);
continue;
}
boolean isSystem = value instanceof PropertyReference;
String prop =
isSystem ? ((PropertyReference) value).getValue()
.toString() : value.toString();
attr.setNodeValue(prop);
// in case the property has changed to system since the last
// load - update the conf file accordingly.
if (isSystem)
((Element) currentNode).setAttribute(
SYSTEM_ATTRIBUTE_NAME, SYSTEM_ATTRIBUTE_TRUE);
else
((Element) currentNode)
.removeAttribute(SYSTEM_ATTRIBUTE_NAME);
}
// update child nodes
updateNode(currentNode, newPropBuff, properties);
}
}
}
/**
* We use property references when we'd like to store system properties.
* Simply storing System properties in our properties Map would not be
* enough since it will lead to mismatching values for the same property in
* the System property set and in our local set of properties. Storing them
* only in the System property set OTOH is a bit clumsy since it obliges
* bundles to use to different configuration property sources. For that
* reason, every time we get handed a property labeled as System, in stead
* of storing its actual value in the local property set we store a
* PropertyReference instance that will retrieve it from the system
* properties when necessary.
*/
private static class PropertyReference
{
private final String propertyName;
public PropertyReference(String propertyName)
{
this.propertyName = propertyName;
}
/**
* Return the actual value of the property as recorded in the System
* properties.
*
* @return the valued of the property as recorded in the System props.
*/
public Object getValue()
{
return System.getProperty(propertyName);
}
}
}

@ -9,6 +9,7 @@
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
@ -317,8 +318,7 @@ private void setNextButtonAccordingToUserID()
|| nickField.getText().equals("")
|| serverField.getText() == null
|| serverField.getText().equals("")
|| (!passwordNotRequired.isSelected()
&& passField.getText().equals("")))
|| (!passwordNotRequired.isSelected() && isEmpty(passField)))
{
wizard.getWizardContainer().setNextFinishButtonEnabled(false);
}
@ -328,6 +328,27 @@ private void setNextButtonAccordingToUserID()
}
}
private boolean isEmpty(JPasswordField passField)
{
if (passField.getDocument() != null)
{
char[] pass = passField.getPassword();
if (pass != null)
{
/*
* The Javadoc of JPasswordField.getPassword() recommends
* clearing the returned character array for stronger security
* by setting each character to zero
*/
Arrays.fill(pass, '\0');
return (pass.length <= 0);
}
}
return true;
}
/**
* Handles the <tt>DocumentEvent</tt> triggered when user types in the
* User ID field. Enables or disables the "Next" wizard button according to

Loading…
Cancel
Save