1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $RCSfile$
3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Revision$
4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Date$
5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2003-2007 Jive Software.
7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License.
10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at
11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *     http://www.apache.org/licenses/LICENSE-2.0
13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software
15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS,
16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and
18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License.
19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smack.packet;
22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.ByteArrayOutputStream;
24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.ObjectOutputStream;
25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.Serializable;
26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.text.DateFormat;
27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.text.SimpleDateFormat;
28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.ArrayList;
29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Collection;
30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Collections;
31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.HashMap;
32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.HashSet;
33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.List;
34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Map;
35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.TimeZone;
36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.CopyOnWriteArrayList;
37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.util.StringUtils;
39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Base class for XMPP packets. Every packet has a unique ID (which is automatically
42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * generated, but can be overriden). Optionally, the "to" and "from" fields can be set,
43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * as well as an arbitrary number of properties.
44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Properties provide an easy mechanism for clients to share data. Each property has a
46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * String name, and a value that is a Java primitive (int, long, float, double, boolean)
47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * or any Serializable object (a Java object is Serializable when it implements the
48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Serializable interface).
49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Matt Tucker
51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic abstract class Packet {
53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected static final String DEFAULT_LANGUAGE =
55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            java.util.Locale.getDefault().getLanguage().toLowerCase();
56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private static String DEFAULT_XML_NS = null;
58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Constant used as packetID to indicate that a packet has no id. To indicate that a packet
61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * has no id set this constant as the packet's id. When the packet is asked for its id the
62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * answer will be <tt>null</tt>.
63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static final String ID_NOT_AVAILABLE = "ID_NOT_AVAILABLE";
65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Date format as defined in XEP-0082 - XMPP Date and Time Profiles.
68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The time zone is set to UTC.
69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * <p>
70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Date formats are not synchronized. Since multiple threads access the format concurrently,
71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * it must be synchronized externally.
72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static final DateFormat XEP_0082_UTC_FORMAT = new SimpleDateFormat(
74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    static {
76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        XEP_0082_UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * A prefix helps to make sure that ID's are unique across mutliple instances.
82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private static String prefix = StringUtils.randomString(5) + "-";
84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Keeps track of the current increment, which is appended to the prefix to
87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * forum a unique ID.
88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private static long id = 0;
90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private String xmlns = DEFAULT_XML_NS;
92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the next unique id. Each id made up of a short alphanumeric
95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * prefix along with a unique numeric value.
96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the next id.
98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static synchronized String nextID() {
100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return prefix + Long.toString(id++);
101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static void setDefaultXmlns(String defaultXmlns) {
104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        DEFAULT_XML_NS = defaultXmlns;
105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private String packetID = null;
108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private String to = null;
109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private String from = null;
110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private final List<PacketExtension> packetExtensions
111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            = new CopyOnWriteArrayList<PacketExtension>();
112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private final Map<String,Object> properties = new HashMap<String, Object>();
114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private XMPPError error = null;
115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public Packet() {
117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public Packet(Packet p) {
120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        packetID = p.getPacketID();
121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        to = p.getTo();
122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        from = p.getFrom();
123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        xmlns = p.xmlns;
124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        error = p.error;
125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Copy extensions
127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        for (PacketExtension pe : p.getExtensions()) {
128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            addExtension(pe);
129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the unique ID of the packet. The returned value could be <tt>null</tt> when
134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * ID_NOT_AVAILABLE was set as the packet's id.
135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the packet's unique ID or <tt>null</tt> if the packet's id is not available.
137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String getPacketID() {
139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (ID_NOT_AVAILABLE.equals(packetID)) {
140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return null;
141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (packetID == null) {
144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            packetID = nextID();
145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return packetID;
147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Sets the unique ID of the packet. To indicate that a packet has no id
151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * pass the constant ID_NOT_AVAILABLE as the packet's id value.
152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packetID the unique ID for the packet.
154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void setPacketID(String packetID) {
156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.packetID = packetID;
157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns who the packet is being sent "to", or <tt>null</tt> if
161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * the value is not set. The XMPP protocol often makes the "to"
162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * attribute optional, so it does not always need to be set.<p>
163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The StringUtils class provides several useful methods for dealing with
165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * XMPP addresses such as parsing the
166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link StringUtils#parseBareAddress(String) bare address},
167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link StringUtils#parseName(String) user name},
168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link StringUtils#parseServer(String) server}, and
169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link StringUtils#parseResource(String) resource}.
170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return who the packet is being sent to, or <tt>null</tt> if the
172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *      value has not been set.
173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String getTo() {
175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return to;
176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Sets who the packet is being sent "to". The XMPP protocol often makes
180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * the "to" attribute optional, so it does not always need to be set.
181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param to who the packet is being sent to.
183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void setTo(String to) {
185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.to = to;
186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns who the packet is being sent "from" or <tt>null</tt> if
190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * the value is not set. The XMPP protocol often makes the "from"
191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * attribute optional, so it does not always need to be set.<p>
192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The StringUtils class provides several useful methods for dealing with
194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * XMPP addresses such as parsing the
195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link StringUtils#parseBareAddress(String) bare address},
196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link StringUtils#parseName(String) user name},
197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link StringUtils#parseServer(String) server}, and
198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link StringUtils#parseResource(String) resource}.
199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return who the packet is being sent from, or <tt>null</tt> if the
201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *      value has not been set.
202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String getFrom() {
204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return from;
205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Sets who the packet is being sent "from". The XMPP protocol often
209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * makes the "from" attribute optional, so it does not always need to
210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * be set.
211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param from who the packet is being sent to.
213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void setFrom(String from) {
215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.from = from;
216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the error associated with this packet, or <tt>null</tt> if there are
220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * no errors.
221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the error sub-packet or <tt>null</tt> if there isn't an error.
223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public XMPPError getError() {
225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return error;
226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Sets the error for this packet.
230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param error the error to associate with this packet.
232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void setError(XMPPError error) {
234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.error = error;
235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns an unmodifiable collection of the packet extensions attached to the packet.
239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the packet extensions.
241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public synchronized Collection<PacketExtension> getExtensions() {
243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (packetExtensions == null) {
244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return Collections.emptyList();
245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return Collections.unmodifiableList(new ArrayList<PacketExtension>(packetExtensions));
247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the first extension of this packet that has the given namespace.
251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param namespace the namespace of the extension that is desired.
253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the packet extension with the given namespace.
254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public PacketExtension getExtension(String namespace) {
256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return getExtension(null, namespace);
257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the first packet extension that matches the specified element name and
261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * namespace, or <tt>null</tt> if it doesn't exist. If the provided elementName is null
262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * than only the provided namespace is attempted to be matched. Packet extensions are
263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * are arbitrary XML sub-documents in standard XMPP packets. By default, a
264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * DefaultPacketExtension instance will be returned for each extension. However,
265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * PacketExtensionProvider instances can be registered with the
266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link org.jivesoftware.smack.provider.ProviderManager ProviderManager}
267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * class to handle custom parsing. In that case, the type of the Object
268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * will be determined by the provider.
269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param elementName the XML element name of the packet extension. (May be null)
271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param namespace the XML element namespace of the packet extension.
272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the extension, or <tt>null</tt> if it doesn't exist.
273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public PacketExtension getExtension(String elementName, String namespace) {
275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (namespace == null) {
276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return null;
277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        for (PacketExtension ext : packetExtensions) {
279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if ((elementName == null || elementName.equals(ext.getElementName()))
280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    && namespace.equals(ext.getNamespace()))
281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            {
282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                return ext;
283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return null;
286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Adds a packet extension to the packet. Does nothing if extension is null.
290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param extension a packet extension.
292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void addExtension(PacketExtension extension) {
294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (extension == null) return;
295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        packetExtensions.add(extension);
296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Adds a collection of packet extensions to the packet. Does nothing if extensions is null.
300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param extensions a collection of packet extensions
302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void addExtensions(Collection<PacketExtension> extensions) {
304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (extensions == null) return;
305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        packetExtensions.addAll(extensions);
306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Removes a packet extension from the packet.
310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param extension the packet extension to remove.
312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void removeExtension(PacketExtension extension)  {
314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        packetExtensions.remove(extension);
315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the packet property with the specified name or <tt>null</tt> if the
319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * property doesn't exist. Property values that were originally primitives will
320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * be returned as their object equivalent. For example, an int property will be
321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * returned as an Integer, a double as a Double, etc.
322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param name the name of the property.
324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the property, or <tt>null</tt> if the property doesn't exist.
325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public synchronized Object getProperty(String name) {
327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (properties == null) {
328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return null;
329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return properties.get(name);
331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Sets a property with an Object as the value. The value must be Serializable
335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * or an IllegalArgumentException will be thrown.
336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param name the name of the property.
338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param value the value of the property.
339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public synchronized void setProperty(String name, Object value) {
341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (!(value instanceof Serializable)) {
342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new IllegalArgumentException("Value must be serialiazble");
343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        properties.put(name, value);
345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Deletes a property.
349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param name the name of the property to delete.
351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public synchronized void deleteProperty(String name) {
353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (properties == null) {
354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return;
355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        properties.remove(name);
357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns an unmodifiable collection of all the property names that are set.
361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return all property names.
363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public synchronized Collection<String> getPropertyNames() {
365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (properties == null) {
366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return Collections.emptySet();
367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return Collections.unmodifiableSet(new HashSet<String>(properties.keySet()));
369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the packet as XML. Every concrete extension of Packet must implement
373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * this method. In addition to writing out packet-specific data, every sub-class
374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * should also write out the error and the extensions data if they are defined.
375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the XML format of the packet as a String.
377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract String toXML();
379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the extension sub-packets (including properties data) as an XML
382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * String, or the Empty String if there are no packet extensions.
383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the extension sub-packets as XML or the Empty String if there
385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * are no packet extensions.
386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected synchronized String getExtensionsXML() {
388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        StringBuilder buf = new StringBuilder();
389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Add in all standard extension sub-packets.
390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        for (PacketExtension extension : getExtensions()) {
391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            buf.append(extension.toXML());
392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Add in packet properties.
394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (properties != null && !properties.isEmpty()) {
395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            buf.append("<properties xmlns=\"http://www.jivesoftware.com/xmlns/xmpp/properties\">");
396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            // Loop through all properties and write them out.
397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            for (String name : getPropertyNames()) {
398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                Object value = getProperty(name);
399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                buf.append("<property>");
400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                buf.append("<name>").append(StringUtils.escapeForXML(name)).append("</name>");
401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                buf.append("<value type=\"");
402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                if (value instanceof Integer) {
403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    buf.append("integer\">").append(value).append("</value>");
404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                else if (value instanceof Long) {
406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    buf.append("long\">").append(value).append("</value>");
407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                else if (value instanceof Float) {
409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    buf.append("float\">").append(value).append("</value>");
410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                else if (value instanceof Double) {
412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    buf.append("double\">").append(value).append("</value>");
413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                else if (value instanceof Boolean) {
415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    buf.append("boolean\">").append(value).append("</value>");
416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                else if (value instanceof String) {
418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    buf.append("string\">");
419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    buf.append(StringUtils.escapeForXML((String)value));
420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    buf.append("</value>");
421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                // Otherwise, it's a generic Serializable object. Serialized objects are in
423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                // a binary format, which won't work well inside of XML. Therefore, we base-64
424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                // encode the binary data before adding it.
425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                else {
426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    ByteArrayOutputStream byteStream = null;
427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    ObjectOutputStream out = null;
428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    try {
429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        byteStream = new ByteArrayOutputStream();
430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        out = new ObjectOutputStream(byteStream);
431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        out.writeObject(value);
432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        buf.append("java-object\">");
433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        String encodedVal = StringUtils.encodeBase64(byteStream.toByteArray());
434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        buf.append(encodedVal).append("</value>");
435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    }
436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    catch (Exception e) {
437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        e.printStackTrace();
438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    }
439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    finally {
440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        if (out != null) {
441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            try {
442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                                out.close();
443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            }
444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            catch (Exception e) {
445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                                // Ignore.
446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            }
447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        }
448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        if (byteStream != null) {
449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            try {
450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                                byteStream.close();
451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            }
452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            catch (Exception e) {
453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                                // Ignore.
454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            }
455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        }
456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    }
457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                buf.append("</property>");
459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            buf.append("</properties>");
461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return buf.toString();
463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String getXmlns() {
466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return this.xmlns;
467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the default language used for all messages containing localized content.
471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the default language
473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static String getDefaultLanguage() {
475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return DEFAULT_LANGUAGE;
476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public boolean equals(Object o) {
479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (this == o) return true;
480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (o == null || getClass() != o.getClass()) return false;
481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        Packet packet = (Packet) o;
483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (error != null ? !error.equals(packet.error) : packet.error != null) { return false; }
485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (from != null ? !from.equals(packet.from) : packet.from != null) { return false; }
486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (!packetExtensions.equals(packet.packetExtensions)) { return false; }
487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (packetID != null ? !packetID.equals(packet.packetID) : packet.packetID != null) {
488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return false;
489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (properties != null ? !properties.equals(packet.properties)
491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                : packet.properties != null) {
492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return false;
493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (to != null ? !to.equals(packet.to) : packet.to != null)  { return false; }
495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return !(xmlns != null ? !xmlns.equals(packet.xmlns) : packet.xmlns != null);
496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public int hashCode() {
499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        int result;
500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        result = (xmlns != null ? xmlns.hashCode() : 0);
501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        result = 31 * result + (packetID != null ? packetID.hashCode() : 0);
502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        result = 31 * result + (to != null ? to.hashCode() : 0);
503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        result = 31 * result + (from != null ? from.hashCode() : 0);
504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        result = 31 * result + packetExtensions.hashCode();
505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        result = 31 * result + properties.hashCode();
506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        result = 31 * result + (error != null ? error.hashCode() : 0);
507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return result;
508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
510