RoomInfo.java

  1. /**
  2.  *
  3.  * Copyright 2003-2007 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.smackx.muc;

  18. import java.net.MalformedURLException;
  19. import java.net.URL;
  20. import java.util.List;
  21. import java.util.logging.Level;
  22. import java.util.logging.Logger;

  23. import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
  24. import org.jivesoftware.smackx.xdata.Form;
  25. import org.jivesoftware.smackx.xdata.FormField;
  26. import org.jxmpp.jid.BareJid;
  27. import org.jxmpp.jid.Jid;

  28. /**
  29.  * Represents the room information that was discovered using Service Discovery. It's possible to
  30.  * obtain information about a room before joining the room but only for rooms that are public (i.e.
  31.  * rooms that may be discovered).
  32.  *
  33.  * @author Gaston Dombiak
  34.  */
  35. public class RoomInfo {

  36.     private static final Logger LOGGER = Logger.getLogger(RoomInfo.class.getName());

  37.     /**
  38.      * JID of the room. The localpart of the JID is commonly used as the ID of the room or name.
  39.      */
  40.     private final BareJid room;
  41.     /**
  42.      * Description of the room.
  43.      */
  44.     private final String description;

  45.     /**
  46.      * Name of the room.
  47.      */
  48.     private final String name;

  49.     /**
  50.      * Last known subject of the room.
  51.      */
  52.     private final String subject;
  53.     /**
  54.      * Current number of occupants in the room.
  55.      */
  56.     private final int occupantsCount;
  57.     /**
  58.      * A room is considered members-only if an invitation is required in order to enter the room.
  59.      * Any user that is not a member of the room won't be able to join the room unless the user
  60.      * decides to register with the room (thus becoming a member).
  61.      */
  62.     private final boolean membersOnly;
  63.     /**
  64.      * Moderated rooms enable only participants to speak. Users that join the room and aren't
  65.      * participants can't speak (they are just visitors).
  66.      */
  67.     private final boolean moderated;
  68.     /**
  69.      * Every presence packet can include the JID of every occupant unless the owner deactives this
  70.      * configuration.
  71.      */
  72.     private final boolean nonanonymous;
  73.     /**
  74.      * Indicates if users must supply a password to join the room.
  75.      */
  76.     private final boolean passwordProtected;
  77.     /**
  78.      * Persistent rooms are saved to the database to make sure that rooms configurations can be
  79.      * restored in case the server goes down.
  80.      */
  81.     private final boolean persistent;

  82.     /**
  83.      * Maximum number of history messages returned by the room.
  84.      */
  85.     private final int maxhistoryfetch;

  86.     /**
  87.      * Contact Address
  88.      */
  89.     private final List<String> contactJid;

  90.     /**
  91.      * Natural Language for Room Discussions
  92.      */
  93.     private final String lang;

  94.     /**
  95.      * An associated LDAP group that defined room membership. Should be an LDAP
  96.      * Distinguished Name
  97.      */
  98.     private final String ldapgroup;

  99.     /**
  100.      * True if the room subject can be modified by participants
  101.      */
  102.     private final Boolean subjectmod;

  103.     /**
  104.      * URL for archived discussion logs
  105.      */
  106.     private final URL logs;

  107.     /**
  108.      * An associated pubsub node
  109.      */
  110.     private final String pubsub;

  111.     /**
  112.      * The rooms extended configuration form;
  113.      */
  114.     private final Form form;

  115.     RoomInfo(DiscoverInfo info) {
  116.         final Jid from = info.getFrom();
  117.         if (from != null) {
  118.             this.room = info.getFrom().asBareJidIfPossible();
  119.         } else {
  120.             this.room = null;
  121.         }
  122.         // Get the information based on the discovered features
  123.         this.membersOnly = info.containsFeature("muc_membersonly");
  124.         this.moderated = info.containsFeature("muc_moderated");
  125.         this.nonanonymous = info.containsFeature("muc_nonanonymous");
  126.         this.passwordProtected = info.containsFeature("muc_passwordprotected");
  127.         this.persistent = info.containsFeature("muc_persistent");

  128.         List<DiscoverInfo.Identity> identities = info.getIdentities();
  129.         // XEP-45 6.4 is not really clear on the topic if an identity needs to
  130.         // be send together with the disco result and how to call this description.
  131.         if (!identities.isEmpty()) {
  132.             this.name = identities.get(0).getName();
  133.         } else {
  134.             LOGGER.warning("DiscoverInfo does not contain any Identity: " + info.toXML());
  135.             this.name = "";
  136.         }
  137.         String subject = "";
  138.         int occupantsCount = -1;
  139.         String description = "";
  140.         int maxhistoryfetch = -1;
  141.         List<String> contactJid = null;
  142.         String lang = null;
  143.         String ldapgroup = null;
  144.         Boolean subjectmod = null;
  145.         URL logs = null;
  146.         String pubsub = null;
  147.         // Get the information based on the discovered extended information
  148.         form = Form.getFormFrom(info);
  149.         if (form != null) {
  150.             FormField descField = form.getField("muc#roominfo_description");
  151.             if (descField != null && !descField.getValues().isEmpty()) {
  152.                 // Prefer the extended result description
  153.                 description = descField.getValues().get(0);
  154.             }

  155.             FormField subjField = form.getField("muc#roominfo_subject");
  156.             if (subjField != null && !subjField.getValues().isEmpty()) {
  157.                 subject = subjField.getValues().get(0);
  158.             }

  159.             FormField occCountField = form.getField("muc#roominfo_occupants");
  160.             if (occCountField != null && !occCountField.getValues().isEmpty()) {
  161.                 occupantsCount = Integer.parseInt(occCountField.getValues().get(
  162.                                 0));
  163.             }

  164.             FormField maxhistoryfetchField = form.getField("muc#maxhistoryfetch");
  165.             if (maxhistoryfetchField != null && !maxhistoryfetchField.getValues().isEmpty()) {
  166.                 maxhistoryfetch = Integer.parseInt(maxhistoryfetchField.getValues().get(
  167.                                 0));
  168.             }

  169.             FormField contactJidField = form.getField("muc#roominfo_contactjid");
  170.             if (contactJidField != null && !contactJidField.getValues().isEmpty()) {
  171.                 contactJid = contactJidField.getValues();
  172.             }

  173.             FormField langField = form.getField("muc#roominfo_lang");
  174.             if (langField != null && !langField.getValues().isEmpty()) {
  175.                 lang = langField.getValues().get(0);
  176.             }

  177.             FormField ldapgroupField = form.getField("muc#roominfo_ldapgroup");
  178.             if (ldapgroupField != null && !ldapgroupField.getValues().isEmpty()) {
  179.                 ldapgroup = ldapgroupField.getValues().get(0);
  180.             }

  181.             FormField subjectmodField = form.getField("muc#roominfo_subjectmod");
  182.             if (subjectmodField != null && !subjectmodField.getValues().isEmpty()) {
  183.                 subjectmod = Boolean.valueOf(subjectmodField.getValues().get(0));
  184.             }

  185.             FormField urlField = form.getField("muc#roominfo_logs");
  186.             if (urlField != null && !urlField.getValues().isEmpty()) {
  187.                 String urlString = urlField.getValues().get(0);
  188.                 try {
  189.                     logs = new URL(urlString);
  190.                 } catch (MalformedURLException e) {
  191.                     LOGGER.log(Level.SEVERE, "Could not parse URL", e);
  192.                 }
  193.             }

  194.             FormField pubsubField = form.getField("muc#roominfo_pubsub");
  195.             if (pubsubField != null && !pubsubField.getValues().isEmpty()) {
  196.                 pubsub = pubsubField.getValues().get(0);
  197.             }
  198.         }
  199.         this.description = description;
  200.         this.subject = subject;
  201.         this.occupantsCount = occupantsCount;
  202.         this.maxhistoryfetch = maxhistoryfetch;
  203.         this.contactJid = contactJid;
  204.         this.lang = lang;
  205.         this.ldapgroup = ldapgroup;
  206.         this.subjectmod = subjectmod;
  207.         this.logs = logs;
  208.         this.pubsub = pubsub;
  209.     }

  210.     /**
  211.      * Returns the JID of the room whose information was discovered.
  212.      *
  213.      * @return the JID of the room whose information was discovered.
  214.      */
  215.     public BareJid getRoom() {
  216.         return room;
  217.     }

  218.     /**
  219.      * Returns the room name.
  220.      * <p>
  221.      * The name returnd here was provided as value of the name attribute
  222.      * of the returned identity within the disco#info result.
  223.      * </p>
  224.      *
  225.      * @return the name of the room.
  226.      */
  227.     public String getName() {
  228.         return name;
  229.     }

  230.     /**
  231.      * Returns the discovered description of the room.
  232.      * <p>
  233.      * The description returned by this method was provided as value of the form
  234.      * field of the extended disco info result. It may be <code>null</code>.
  235.      * </p>
  236.      *
  237.      * @return the discovered description of the room or null
  238.      */
  239.     public String getDescription() {
  240.         return description;
  241.     }

  242.     /**
  243.      * Returns the discovered subject of the room. The subject may be null if the room does not
  244.      * have a subject.
  245.      *
  246.      * @return the discovered subject of the room or null
  247.      */
  248.     public String getSubject() {
  249.         return subject;
  250.     }

  251.     /**
  252.      * Returns the discovered number of occupants that are currently in the room. If this
  253.      * information was not discovered (i.e. the server didn't send it) then a value of -1 will be
  254.      * returned.
  255.      *
  256.      * @return the number of occupants that are currently in the room or -1 if that information was
  257.      * not provided by the server.
  258.      */
  259.     public int getOccupantsCount() {
  260.         return occupantsCount;
  261.     }

  262.     /**
  263.      * Returns true if the room has restricted the access so that only members may enter the room.
  264.      *
  265.      * @return true if the room has restricted the access so that only members may enter the room.
  266.      */
  267.     public boolean isMembersOnly() {
  268.         return membersOnly;
  269.     }

  270.     /**
  271.      * Returns true if the room enabled only participants to speak. Occupants with a role of
  272.      * visitor won't be able to speak in the room.
  273.      *
  274.      * @return true if the room enabled only participants to speak.
  275.      */
  276.     public boolean isModerated() {
  277.         return moderated;
  278.     }

  279.     /**
  280.      * Returns true if presence packets will include the JID of every occupant.
  281.      *
  282.      * @return true if presence packets will include the JID of every occupant.
  283.      */
  284.     public boolean isNonanonymous() {
  285.         return nonanonymous;
  286.     }

  287.     /**
  288.      * Returns true if users musy provide a valid password in order to join the room.
  289.      *
  290.      * @return true if users musy provide a valid password in order to join the room.
  291.      */
  292.     public boolean isPasswordProtected() {
  293.         return passwordProtected;
  294.     }

  295.     /**
  296.      * Returns true if the room will persist after the last occupant have left the room.
  297.      *
  298.      * @return true if the room will persist after the last occupant have left the room.
  299.      */
  300.     public boolean isPersistent() {
  301.         return persistent;
  302.     }

  303.     /**
  304.      * Returns the maximum number of history messages which are returned by the
  305.      * room or '-1' if this property is not reported by the room.
  306.      *
  307.      * @return the maximum number of history messages or '-1'
  308.      */
  309.     public int getMaxHistoryFetch() {
  310.         return maxhistoryfetch;
  311.     }

  312.     /**
  313.      * Returns Contact Addresses as JIDs, if such are reported.
  314.      *
  315.      * @return a list of contact addresses for this room.
  316.      */
  317.     public List<String> getContactJids() {
  318.         return contactJid;
  319.     }

  320.     /**
  321.      * Returns the natural language of the room discussion, or <code>null</code>.
  322.      *
  323.      * @return the language of the room discussion or <code>null</code>.
  324.      */
  325.     public String getLang() {
  326.         return lang;
  327.     }

  328.     /**
  329.      * Returns an associated LDAP group that defines room membership. The
  330.      * value should be an LDAP Distinguished Name according to an
  331.      * implementation-specific or deployment-specific definition of a group.
  332.      *
  333.      * @return an associated LDAP group or <code>null</code>
  334.      */
  335.     public String getLdapGroup() {
  336.         return ldapgroup;
  337.     }

  338.     /**
  339.      * Returns an Boolean instance with the value 'true' if the subject can be
  340.      * modified by the room participants, 'false' if not, or <code>null</code>
  341.      * if this information is reported by the room.
  342.      *
  343.      * @return an boolean that is true if the subject can be modified by
  344.      *         participants or <code>null</code>
  345.      */
  346.     public Boolean isSubjectModifiable() {
  347.         return subjectmod;
  348.     }

  349.     /**
  350.      * An associated pubsub node for this room or <code>null</code>.
  351.      *
  352.      * @return the associated pubsub node or <code>null</code>
  353.      */
  354.     public String getPubSub() {
  355.         return pubsub;
  356.     }

  357.     /**
  358.      * Returns the URL where archived discussion logs can be found or
  359.      * <code>null</code> if there is no such URL.
  360.      *
  361.      * @return the URL where archived logs can be found or <code>null</code>
  362.      */
  363.     public URL getLogsUrl() {
  364.         return logs;
  365.     }

  366.     /**
  367.      * Returns the form included in the extended disco info result or
  368.      * <code>null</code> if no such form was sent.
  369.      *
  370.      * @return The room info form or <code>null</code>
  371.      * @see <a
  372.      *      href="http://xmpp.org/extensions/xep-0045.html#disco-roominfo">XEP-45:
  373.      *      Multi User Chat - 6.5 Querying for Room Information</a>
  374.      */
  375.     public Form getForm() {
  376.         return form;
  377.     }

  378. }