AMPExtension.java

  1. /**
  2.  *
  3.  * Copyright 2014 Vyacheslav Blinov
  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.smackx.amp.packet;

  18. import java.util.Collections;
  19. import java.util.List;
  20. import java.util.concurrent.CopyOnWriteArrayList;

  21. import org.jivesoftware.smack.packet.ExtensionElement;
  22. import org.jivesoftware.smackx.amp.AMPDeliverCondition;
  23. import org.jivesoftware.smackx.amp.AMPExpireAtCondition;
  24. import org.jivesoftware.smackx.amp.AMPMatchResourceCondition;

  25. public class AMPExtension implements ExtensionElement {

  26.     public static final String NAMESPACE = "http://jabber.org/protocol/amp";
  27.     public static final String ELEMENT = "amp";

  28.     private CopyOnWriteArrayList<Rule> rules = new CopyOnWriteArrayList<Rule>();
  29.     private boolean perHop = false;

  30.     private final String from;
  31.     private final String to;
  32.     private final Status status;

  33.     /**
  34.      * Create a new AMPExtension instance with defined from, to and status attributes. Used to create incoming packets.
  35.      * @param from jid that triggered this amp callback.
  36.      * @param to receiver of this amp receipt.
  37.      * @param status status of this amp receipt.
  38.      */
  39.     public AMPExtension(String from, String to, Status status) {
  40.         this.from = from;
  41.         this.to = to;
  42.         this.status = status;
  43.     }

  44.     /**
  45.      * Create a new amp request extension to be used with outgoing message.
  46.      */
  47.     public AMPExtension() {
  48.         this.from = null;
  49.         this.to = null;
  50.         this.status = null;
  51.     }

  52.     /**
  53.      * @return jid that triggered this amp callback.
  54.      */
  55.     public String getFrom() {
  56.         return from;
  57.     }

  58.     /**
  59.      * @return receiver of this amp receipt.
  60.      */
  61.     public String getTo() {
  62.         return to;
  63.     }

  64.     /**
  65.      * Status of this amp notification
  66.      * @return Status for this amp
  67.      */
  68.     public Status getStatus() {
  69.         return status;
  70.     }

  71.     /**
  72.      * Returns a unmodifiable List of the rules in the packet.
  73.      *
  74.      * @return a unmodifiable List of the rules in the packet.
  75.      */
  76.     public List<Rule> getRules() {
  77.         return Collections.unmodifiableList(rules);
  78.     }

  79.     /**
  80.      * Adds a rule to the amp element. Amp can have any number of rules.
  81.      *
  82.      * @param rule the rule to add.
  83.      */
  84.     public void addRule(Rule rule) {
  85.         rules.add(rule);
  86.     }

  87.     /**
  88.      * Returns a count of the rules in the AMP packet.
  89.      *
  90.      * @return the number of rules in the AMP packet.
  91.      */
  92.     public int getRulesCount() {
  93.         return rules.size();
  94.     }

  95.     /**
  96.      * Sets this amp ruleset to be "per-hop".
  97.      *
  98.      * @param enabled true if "per-hop" should be enabled
  99.      */
  100.     public synchronized void setPerHop(boolean enabled) {
  101.         perHop = enabled;
  102.     }

  103.     /**
  104.      * Returns true is this ruleset is "per-hop".
  105.      *
  106.      * @return true is this ruleset is "per-hop".
  107.      */
  108.     public synchronized boolean isPerHop() {
  109.         return perHop;
  110.     }

  111.     /**
  112.      * Returns the XML element name of the extension sub-packet root element.
  113.      * Always returns "amp"
  114.      *
  115.      * @return the XML element name of the packet extension.
  116.      */
  117.     @Override
  118.     public String getElementName() {
  119.         return ELEMENT;
  120.     }

  121.     /**
  122.      * Returns the XML namespace of the extension sub-packet root element.
  123.      * According the specification the namespace is always "http://jabber.org/protocol/xhtml-im"
  124.      *
  125.      * @return the XML namespace of the packet extension.
  126.      */
  127.     @Override
  128.     public String getNamespace() {
  129.         return NAMESPACE;
  130.     }

  131.     /**
  132.      * Returns the XML representation of a XHTML extension according the specification.
  133.      **/
  134.     @Override
  135.     public String toXML() {
  136.         StringBuilder buf = new StringBuilder();
  137.         buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append("\"");
  138.         if (status != null) {
  139.             buf.append(" status=\"").append(status.toString()).append("\"");
  140.         }
  141.         if (to != null) {
  142.             buf.append(" to=\"").append(to).append("\"");
  143.         }
  144.         if (from != null) {
  145.             buf.append(" from=\"").append(from).append("\"");
  146.         }
  147.         if (perHop) {
  148.             buf.append(" per-hop=\"true\"");
  149.         }
  150.         buf.append(">");

  151.         // Loop through all the rules and append them to the string buffer
  152.         for (Rule rule : getRules()) {
  153.             buf.append(rule.toXML());
  154.         }

  155.         buf.append("</").append(getElementName()).append(">");
  156.         return buf.toString();
  157.     }

  158.     /**
  159.      * XEP-0079 Rule element. Defines AMP Rule parameters. Can be added to AMPExtension.
  160.      */
  161.     public static class Rule {
  162.         public static final String ELEMENT = "rule";

  163.         private final Action action;
  164.         private final Condition condition;

  165.         public Action getAction() {
  166.             return action;
  167.         }

  168.         public Condition getCondition() {
  169.             return condition;
  170.         }

  171.         /**
  172.          * Create a new amp rule with specified action and condition. Value will be taken from condition argument
  173.          * @param action action for this rule
  174.          * @param condition condition for this rule
  175.          */
  176.         public Rule(Action action, Condition condition) {
  177.             if (action == null)
  178.                 throw new NullPointerException("Can't create Rule with null action");
  179.             if (condition == null)
  180.                 throw new NullPointerException("Can't create Rule with null condition");

  181.             this.action = action;
  182.             this.condition = condition;
  183.         }

  184.         private String toXML() {
  185.             return "<" + ELEMENT + " " + Action.ATTRIBUTE_NAME + "=\"" + action.toString() + "\" " +
  186.                     Condition.ATTRIBUTE_NAME + "=\"" + condition.getName() + "\" " +
  187.                     "value=\"" + condition.getValue() + "\"/>";
  188.         }
  189.     }

  190.     /**
  191.      * Interface for defining XEP-0079 Conditions and their values
  192.      * @see AMPDeliverCondition
  193.      * @see AMPExpireAtCondition
  194.      * @see AMPMatchResourceCondition
  195.      **/
  196.     public static interface Condition {
  197.         String getName();
  198.         String getValue();

  199.         static final String ATTRIBUTE_NAME="condition";
  200.     }

  201.     /**
  202.      * amp action attribute
  203.      * See http://xmpp.org/extensions/xep-0079.html#actions-def
  204.      **/
  205.     public static enum Action {
  206.         /**
  207.          * The "alert" action triggers a reply <message/> stanza to the sending entity.
  208.          * This <message/> stanza MUST contain the element <amp status='alert'/>,
  209.          * which itself contains the <rule/> that triggered this action. In all other respects,
  210.          * this action behaves as "drop".
  211.          */
  212.         alert,
  213.         /**
  214.          * The "drop" action silently discards the message from any further delivery attempts
  215.          * and ensures that it is not placed into offline storage.
  216.          * The drop MUST NOT result in other responses.
  217.          */
  218.         drop,
  219.         /**
  220.          * The "error" action triggers a reply <message/> stanza of type "error" to the sending entity.
  221.          * The <message/> stanza's <error/> child MUST contain a
  222.          * <failed-rules xmlns='http://jabber.org/protocol/amp#errors'/> error condition,
  223.          * which itself contains the rules that triggered this action.
  224.          */
  225.         error,
  226.         /**
  227.          * The "notify" action triggers a reply <message/> stanza to the sending entity.
  228.          * This <message/> stanza MUST contain the element <amp status='notify'/>, which itself
  229.          * contains the <rule/> that triggered this action. Unlike the other actions,
  230.          * this action does not override the default behavior for a server.
  231.          * Instead, the server then executes its default behavior after sending the notify.
  232.          */
  233.         notify;

  234.         public static final String ATTRIBUTE_NAME="action";
  235.     }

  236.     /**
  237.      * amp notification status as defined by XEP-0079
  238.      */
  239.     public static enum Status {
  240.         alert,
  241.         error,
  242.         notify
  243.     }
  244. }