StreamError.java

  1. /**
  2.  *
  3.  * Copyright 2003-2005 Jive Software.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.jivesoftware.smack.packet;

  18. import java.util.List;
  19. import java.util.Map;

  20. import org.jivesoftware.smack.util.StringUtils;
  21. import org.jivesoftware.smack.util.XmlStringBuilder;

  22. /**
  23.  * Represents a stream error packet. Stream errors are unrecoverable errors where the server
  24.  * will close the unrelying TCP connection after the stream error was sent to the client.
  25.  * These is the list of stream errors as defined in the XMPP spec:<p>
  26.  *
  27.  * <table border=1>
  28.  *      <tr><td><b>Code</b></td><td><b>Description</b></td></tr>
  29.  *      <tr><td> bad-format </td><td> the entity has sent XML that cannot be processed </td></tr>
  30.  *      <tr><td> unsupported-encoding </td><td>  the entity has sent a namespace prefix that is
  31.  *          unsupported </td></tr>
  32.  *      <tr><td> bad-namespace-prefix </td><td> Remote Server Timeout </td></tr>
  33.  *      <tr><td> conflict </td><td> the server is closing the active stream for this entity
  34.  *          because a new stream has been initiated that conflicts with the existing
  35.  *          stream. </td></tr>
  36.  *      <tr><td> connection-timeout </td><td> the entity has not generated any traffic over
  37.  *          the stream for some period of time. </td></tr>
  38.  *      <tr><td> host-gone </td><td> the value of the 'to' attribute provided by the initiating
  39.  *          entity in the stream header corresponds to a hostname that is no longer hosted by
  40.  *          the server. </td></tr>
  41.  *      <tr><td> host-unknown </td><td> the value of the 'to' attribute provided by the
  42.  *          initiating entity in the stream header does not correspond to a hostname that is
  43.  *          hosted by the server. </td></tr>
  44.  *      <tr><td> improper-addressing </td><td> a stanza sent between two servers lacks a 'to'
  45.  *          or 'from' attribute </td></tr>
  46.  *      <tr><td> internal-server-error </td><td> the server has experienced a
  47.  *          misconfiguration. </td></tr>
  48.  *      <tr><td> invalid-from </td><td> the JID or hostname provided in a 'from' address does
  49.  *          not match an authorized JID. </td></tr>
  50.  *      <tr><td> invalid-namespace </td><td> the streams namespace name is invalid. </td></tr>
  51.  *      <tr><td> invalid-xml </td><td> the entity has sent invalid XML over the stream. </td></tr>
  52.  *      <tr><td> not-authorized </td><td> the entity has attempted to send data before the
  53.  *          stream has been authenticated </td></tr>
  54.  *      <tr><td> policy-violation </td><td> the entity has violated some local service
  55.  *          policy. </td></tr>
  56.  *      <tr><td> remote-connection-failed </td><td> Rthe server is unable to properly connect
  57.  *          to a remote entity. </td></tr>
  58.  *      <tr><td> resource-constraint </td><td> Rthe server lacks the system resources necessary
  59.  *          to service the stream. </td></tr>
  60.  *      <tr><td> restricted-xml </td><td> the entity has attempted to send restricted XML
  61.  *          features. </td></tr>
  62.  *      <tr><td> see-other-host </td><td>  the server will not provide service to the initiating
  63.  *          entity but is redirecting traffic to another host. </td></tr>
  64.  *      <tr><td> system-shutdown </td><td> the server is being shut down and all active streams
  65.  *          are being closed. </td></tr>
  66.  *      <tr><td> undefined-condition </td><td> the error condition is not one of those defined
  67.  *          by the other conditions in this list. </td></tr>
  68.  *      <tr><td> unsupported-encoding </td><td> the initiating entity has encoded the stream in
  69.  *          an encoding that is not supported. </td></tr>
  70.  *      <tr><td> unsupported-stanza-type </td><td> the initiating entity has sent a first-level
  71.  *          child of the stream that is not supported. </td></tr>
  72.  *      <tr><td> unsupported-version </td><td> the value of the 'version' attribute provided by
  73.  *          the initiating entity in the stream header specifies a version of XMPP that is not
  74.  *          supported. </td></tr>
  75.  *      <tr><td> not-well-formed </td><td> the initiating entity has sent XML that is not
  76.  *          well-formed. </td></tr>
  77.  * </table>
  78.  * <p>
  79.  * Stream error syntax:
  80.  * <pre>
  81.  * {@code
  82.  * <stream:error>
  83.  *   <defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
  84.  *   [<text xmlns='urn:ietf:params:xml:ns:xmpp-streams'
  85.  *      xml:lang='langcode'>
  86.  *   OPTIONAL descriptive text
  87.  *   </text>]
  88.  *   [OPTIONAL application-specific condition element]
  89.  * </stream:error>
  90.  * }
  91.  * </pre>
  92.  *
  93.  * @author Gaston Dombiak
  94.  */
  95. public class StreamError extends AbstractError implements PlainStreamElement {

  96.     public static final String ELEMENT = "stream:error";
  97.     public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-streams";

  98.     private final Condition condition;
  99.     private final String conditionText;

  100.     public StreamError(Condition condition, String conditionText, Map<String, String> descriptiveTexts, List<ExtensionElement> extensions) {
  101.         super(descriptiveTexts, extensions);
  102.         // Some implementations may send the condition as non-empty element containing the empty string, that is
  103.         // <condition xmlns='foo'></condition>, in this case the parser may calls this constructor with the empty string
  104.         // as conditionText, therefore reset it to null if it's the empty string
  105.         if (StringUtils.isNullOrEmpty(conditionText)) {
  106.             conditionText = null;
  107.         }
  108.         if (conditionText != null) {
  109.             switch (condition) {
  110.             case see_other_host:
  111.                 break;
  112.             default:
  113.                 throw new IllegalArgumentException("The given condition '" + condition
  114.                                 + "' can not contain a conditionText");
  115.             }
  116.         }
  117.         this.condition = condition;
  118.         this.conditionText = conditionText;
  119.     }

  120.     public Condition getCondition() {
  121.         return condition;
  122.     }

  123.     public String getConditionText() {
  124.         return conditionText;
  125.     }

  126.     @Override
  127.     public String toString() {
  128.         return toXML().toString();
  129.     }

  130.     @Override
  131.     public XmlStringBuilder toXML() {
  132.         XmlStringBuilder xml = new XmlStringBuilder();
  133.         xml.openElement(ELEMENT);
  134.         xml.halfOpenElement(condition.toString()).xmlnsAttribute(NAMESPACE).closeEmptyElement();
  135.         addDescriptiveTextsAndExtensions(xml);
  136.         xml.closeElement(ELEMENT);
  137.         return xml;
  138.     }

  139.     /**
  140.      * The defined stream error conditions, see RFC 6120 ยง 4.9.3
  141.      *
  142.      */
  143.     public enum Condition {
  144.         bad_format,
  145.         bad_namespace_prefix,
  146.         conflict,
  147.         connection_timeout,
  148.         host_gone,
  149.         host_unknown,
  150.         improper_addressing,
  151.         internal_server_error,
  152.         invalid_from,
  153.         invalid_namespace,
  154.         invalid_xml,
  155.         not_authorized,
  156.         not_well_formed,
  157.         policy_violation,
  158.         remote_connection_failed,
  159.         reset,
  160.         resource_constraint,
  161.         restricted_xml,
  162.         see_other_host,
  163.         system_shutdown,
  164.         undeficed_condition,
  165.         unsupported_encoding,
  166.         unsupported_feature,
  167.         unsupported_stanza_type,
  168.         unsupported_version;

  169.         @Override
  170.         public String toString() {
  171.             return this.name().replace('_', '-');
  172.         }

  173.         public static Condition fromString(String string) {
  174.             string = string.replace('-', '_');
  175.             Condition condition = null;
  176.             try {
  177.                 condition = Condition.valueOf(string);
  178.             } catch (Exception e) {
  179.                 throw new IllegalStateException("Could not transform string '" + string
  180.                                 + "' to XMPPErrorCondition", e);
  181.             }
  182.             return condition;
  183.         }
  184.     }
  185. }