mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-09-27 10:19:33 +02:00
234 lines
7.8 KiB
Java
234 lines
7.8 KiB
Java
/**
|
|
*
|
|
* Copyright 2003-2007 Jive Software.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package org.jivesoftware.smackx.jiveproperties.packet;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.ObjectOutputStream;
|
|
import java.io.Serializable;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Map;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
|
|
import org.jivesoftware.smack.packet.ExtensionElement;
|
|
import org.jivesoftware.smack.packet.Message;
|
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
|
import org.jivesoftware.smack.util.stringencoder.Base64;
|
|
|
|
/**
|
|
* Properties provide an easy mechanism for clients to share data. Each property has a
|
|
* String name, and a value that is a Java primitive (int, long, float, double, boolean)
|
|
* or any Serializable object (a Java object is Serializable when it implements the
|
|
* Serializable interface).
|
|
*
|
|
*/
|
|
public class JivePropertiesExtension implements ExtensionElement {
|
|
/**
|
|
* Namespace used to store stanza properties.
|
|
*/
|
|
public static final String NAMESPACE = "http://www.jivesoftware.com/xmlns/xmpp/properties";
|
|
|
|
public static final String ELEMENT = "properties";
|
|
|
|
private static final Logger LOGGER = Logger.getLogger(JivePropertiesExtension.class.getName());
|
|
|
|
private final Map<String, Object> properties;
|
|
|
|
public JivePropertiesExtension() {
|
|
properties = new HashMap<>();
|
|
}
|
|
|
|
public JivePropertiesExtension(Map<String, Object> properties) {
|
|
this.properties = properties;
|
|
}
|
|
|
|
/**
|
|
* Returns the stanza property with the specified name or <tt>null</tt> if the
|
|
* property doesn't exist. Property values that were originally primitives will
|
|
* be returned as their object equivalent. For example, an int property will be
|
|
* returned as an Integer, a double as a Double, etc.
|
|
*
|
|
* @param name the name of the property.
|
|
* @return the property, or <tt>null</tt> if the property doesn't exist.
|
|
*/
|
|
public synchronized Object getProperty(String name) {
|
|
if (properties == null) {
|
|
return null;
|
|
}
|
|
return properties.get(name);
|
|
}
|
|
|
|
/**
|
|
* Sets a property with an Object as the value. The value must be Serializable
|
|
* or an IllegalArgumentException will be thrown.
|
|
*
|
|
* @param name the name of the property.
|
|
* @param value the value of the property.
|
|
*/
|
|
public synchronized void setProperty(String name, Object value) {
|
|
if (!(value instanceof Serializable)) {
|
|
throw new IllegalArgumentException("Value must be serializable");
|
|
}
|
|
properties.put(name, value);
|
|
}
|
|
|
|
/**
|
|
* Deletes a property.
|
|
*
|
|
* @param name the name of the property to delete.
|
|
*/
|
|
public synchronized void deleteProperty(String name) {
|
|
if (properties == null) {
|
|
return;
|
|
}
|
|
properties.remove(name);
|
|
}
|
|
|
|
/**
|
|
* Returns an unmodifiable collection of all the property names that are set.
|
|
*
|
|
* @return all property names.
|
|
*/
|
|
public synchronized Collection<String> getPropertyNames() {
|
|
if (properties == null) {
|
|
return Collections.emptySet();
|
|
}
|
|
return Collections.unmodifiableSet(new HashSet<>(properties.keySet()));
|
|
}
|
|
|
|
/**
|
|
* Returns an unmodifiable map of all properties.
|
|
*
|
|
* @return all properties.
|
|
*/
|
|
public synchronized Map<String, Object> getProperties() {
|
|
if (properties == null) {
|
|
return Collections.emptyMap();
|
|
}
|
|
return Collections.unmodifiableMap(new HashMap<>(properties));
|
|
}
|
|
|
|
@Override
|
|
public String getElementName() {
|
|
return ELEMENT;
|
|
}
|
|
|
|
@Override
|
|
public String getNamespace() {
|
|
return NAMESPACE;
|
|
}
|
|
|
|
@Override
|
|
public CharSequence toXML(String enclosingNamespace) {
|
|
XmlStringBuilder xml = new XmlStringBuilder(this);
|
|
xml.rightAngleBracket();
|
|
// Loop through all properties and write them out.
|
|
for (String name : getPropertyNames()) {
|
|
Object value = getProperty(name);
|
|
xml.openElement("property");
|
|
xml.element("name", name);
|
|
xml.halfOpenElement("value");
|
|
|
|
String type;
|
|
String valueStr;
|
|
if (value instanceof Integer) {
|
|
type = "integer";
|
|
valueStr = Integer.toString((Integer) value);
|
|
}
|
|
else if (value instanceof Long) {
|
|
type = "long";
|
|
valueStr = Long.toString((Long) value);
|
|
}
|
|
else if (value instanceof Float) {
|
|
type = "float";
|
|
valueStr = Float.toString((Float) value);
|
|
}
|
|
else if (value instanceof Double) {
|
|
type = "double";
|
|
valueStr = Double.toString((Double) value);
|
|
}
|
|
else if (value instanceof Boolean) {
|
|
type = "boolean";
|
|
valueStr = Boolean.toString((Boolean) value);
|
|
}
|
|
else if (value instanceof String) {
|
|
type = "string";
|
|
valueStr = (String) value;
|
|
}
|
|
// Otherwise, it's a generic Serializable object. Serialized objects are in
|
|
// a binary format, which won't work well inside of XML. Therefore, we base-64
|
|
// encode the binary data before adding it.
|
|
else {
|
|
ByteArrayOutputStream byteStream = null;
|
|
ObjectOutputStream out = null;
|
|
try {
|
|
byteStream = new ByteArrayOutputStream();
|
|
out = new ObjectOutputStream(byteStream);
|
|
out.writeObject(value);
|
|
type = "java-object";
|
|
valueStr = Base64.encodeToString(byteStream.toByteArray());
|
|
}
|
|
catch (Exception e) {
|
|
LOGGER.log(Level.SEVERE, "Error encoding java object", e);
|
|
type = "java-object";
|
|
valueStr = "Serializing error: " + e.getMessage();
|
|
}
|
|
finally {
|
|
if (out != null) {
|
|
try {
|
|
out.close();
|
|
}
|
|
catch (Exception e) {
|
|
// Ignore.
|
|
}
|
|
}
|
|
if (byteStream != null) {
|
|
try {
|
|
byteStream.close();
|
|
}
|
|
catch (Exception e) {
|
|
// Ignore.
|
|
}
|
|
}
|
|
}
|
|
}
|
|
xml.attribute("type", type);
|
|
xml.rightAngleBracket();
|
|
xml.escape(valueStr);
|
|
xml.closeElement("value");
|
|
xml.closeElement("property");
|
|
}
|
|
xml.closeElement(this);
|
|
|
|
return xml;
|
|
}
|
|
|
|
/**
|
|
* Return a Jive properties extensions of the given message.
|
|
*
|
|
* @param message the message to return the extension from.
|
|
* @return a Jive properties extension or null.
|
|
* @since 4.2
|
|
*/
|
|
public static JivePropertiesExtension from(Message message) {
|
|
return message.getExtension(ELEMENT, NAMESPACE);
|
|
}
|
|
}
|