001/** 002 * 003 * Copyright 2015-2020 Florian Schmaus 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smackx.muc; 018 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.List; 022 023import org.jivesoftware.smack.SmackException.NoResponseException; 024import org.jivesoftware.smack.SmackException.NotConnectedException; 025import org.jivesoftware.smack.XMPPException.XMPPErrorException; 026 027import org.jivesoftware.smackx.muc.MultiUserChatException.MucConfigurationNotSupportedException; 028import org.jivesoftware.smackx.xdata.FormField; 029import org.jivesoftware.smackx.xdata.form.FillableForm; 030import org.jivesoftware.smackx.xdata.form.FilledForm; 031import org.jivesoftware.smackx.xdata.form.Form; 032 033import org.jxmpp.jid.Jid; 034import org.jxmpp.jid.util.JidUtil; 035 036/** 037 * Multi-User Chat configuration form manager is used to fill out and submit a {@link FilledForm} used to 038 * configure rooms. 039 * <p> 040 * Room configuration needs either be done right after the room is created and still locked. Or at 041 * any later point (see <a href="http://xmpp.org/extensions/xep-0045.html#roomconfig">XEP-45 § 10.2 042 * Subsequent Room Configuration</a>). When done with the configuration, call 043 * {@link #submitConfigurationForm()}. 044 * </p> 045 * <p> 046 * The manager may not provide all possible configuration options. If you want direct access to the 047 * configuration form, use {@link MultiUserChat#getConfigurationForm()} and 048 * {@link MultiUserChat#sendConfigurationForm(FillableForm)}. 049 * </p> 050 */ 051public class MucConfigFormManager { 052 053 private static final String HASH_ROOMCONFIG = "#roomconfig"; 054 055 public static final String FORM_TYPE = MultiUserChatConstants.NAMESPACE + HASH_ROOMCONFIG; 056 057 /** 058 * The constant String {@value}. 059 * 060 * @see <a href="http://xmpp.org/extensions/xep-0045.html#owner">XEP-0045 § 10. Owner Use Cases</a> 061 */ 062 public static final String MUC_ROOMCONFIG_ROOMOWNERS = "muc#roomconfig_roomowners"; 063 064 /** 065 * The constant String {@value}. 066 */ 067 public static final String MUC_ROOMCONFIG_MEMBERSONLY = "muc#roomconfig_membersonly"; 068 069 /** 070 * The constant String {@value}. 071 * 072 * @see <a href="http://xmpp.org/extensions/xep-0045.html#enter-pw">XEP-0045 § 7.2.6 Password-Protected Rooms</a> 073 */ 074 public static final String MUC_ROOMCONFIG_PASSWORDPROTECTEDROOM = "muc#roomconfig_passwordprotectedroom"; 075 076 /** 077 * The constant String {@value}. 078 */ 079 public static final String MUC_ROOMCONFIG_ROOMSECRET = "muc#roomconfig_roomsecret"; 080 081 private final MultiUserChat multiUserChat; 082 private final FillableForm answerForm; 083 private final List<Jid> owners; 084 085 /** 086 * Create a new MUC config form manager. 087 * <p> 088 * Note that the answerForm needs to be filled out with the defaults. 089 * </p> 090 * 091 * @param multiUserChat the MUC for this configuration form. 092 * @throws InterruptedException if the calling thread was interrupted. 093 * @throws NotConnectedException if the XMPP connection is not connected. 094 * @throws XMPPErrorException if there was an XMPP error returned. 095 * @throws NoResponseException if there was no response from the remote entity. 096 */ 097 MucConfigFormManager(MultiUserChat multiUserChat) throws NoResponseException, 098 XMPPErrorException, NotConnectedException, InterruptedException { 099 this.multiUserChat = multiUserChat; 100 101 // Set the answer form 102 Form configForm = multiUserChat.getConfigurationForm(); 103 this.answerForm = configForm.getFillableForm(); 104 105 // Set the local variables according to the fields found in the answer form 106 FormField roomOwnersFormField = answerForm.getDataForm().getField(MUC_ROOMCONFIG_ROOMOWNERS); 107 if (roomOwnersFormField != null) { 108 // Set 'owners' to the currently configured owners 109 List<? extends CharSequence> ownerStrings = roomOwnersFormField.getValues(); 110 owners = new ArrayList<>(ownerStrings.size()); 111 JidUtil.jidsFrom(ownerStrings, owners, null); 112 } 113 else { 114 // roomowners not supported, this should barely be the case 115 owners = null; 116 } 117 } 118 119 /** 120 * Check if the room supports room owners. 121 * @return <code>true</code> if supported, <code>false</code> if not. 122 * @see #MUC_ROOMCONFIG_ROOMOWNERS 123 */ 124 public boolean supportsRoomOwners() { 125 return owners != null; 126 } 127 128 /** 129 * Set the owners of the room. 130 * 131 * @param newOwners a collection of JIDs to become the new owners of the room. 132 * @return a reference to this object. 133 * @throws MucConfigurationNotSupportedException if the MUC service does not support this option. 134 * @see #MUC_ROOMCONFIG_ROOMOWNERS 135 */ 136 public MucConfigFormManager setRoomOwners(Collection<? extends Jid> newOwners) throws MucConfigurationNotSupportedException { 137 if (!supportsRoomOwners()) { 138 throw new MucConfigurationNotSupportedException(MUC_ROOMCONFIG_ROOMOWNERS); 139 } 140 owners.clear(); 141 owners.addAll(newOwners); 142 return this; 143 } 144 145 /** 146 * Check if the room supports a members only configuration. 147 * 148 * @return <code>true</code> if supported, <code>false</code> if not. 149 */ 150 public boolean supportsMembersOnly() { 151 return answerForm.hasField(MUC_ROOMCONFIG_MEMBERSONLY); 152 } 153 154 /** 155 * Make the room for members only. 156 * 157 * @return a reference to this object. 158 * @throws MucConfigurationNotSupportedException if the requested MUC configuration is not supported by the MUC service. 159 */ 160 public MucConfigFormManager makeMembersOnly() throws MucConfigurationNotSupportedException { 161 return setMembersOnly(true); 162 } 163 164 /** 165 * Set if the room is members only. Rooms are not members only per default. 166 * 167 * @param isMembersOnly if the room should be members only. 168 * @return a reference to this object. 169 * @throws MucConfigurationNotSupportedException if the requested MUC configuration is not supported by the MUC service. 170 */ 171 public MucConfigFormManager setMembersOnly(boolean isMembersOnly) throws MucConfigurationNotSupportedException { 172 if (!supportsMembersOnly()) { 173 throw new MucConfigurationNotSupportedException(MUC_ROOMCONFIG_MEMBERSONLY); 174 } 175 answerForm.setAnswer(MUC_ROOMCONFIG_MEMBERSONLY, isMembersOnly); 176 return this; 177 } 178 179 /** 180 * Check if the room supports password protection. 181 * 182 * @return <code>true</code> if supported, <code>false</code> if not. 183 */ 184 public boolean supportsPasswordProtected() { 185 return answerForm.hasField(MUC_ROOMCONFIG_PASSWORDPROTECTEDROOM); 186 } 187 188 /** 189 * Set a password and make the room password protected. Users will need to supply the password 190 * to join the room. 191 * 192 * @param password the password to set. 193 * @return a reference to this object. 194 * @throws MucConfigurationNotSupportedException if the requested MUC configuration is not supported by the MUC service. 195 */ 196 public MucConfigFormManager setAndEnablePassword(String password) 197 throws MucConfigurationNotSupportedException { 198 return setIsPasswordProtected(true).setRoomSecret(password); 199 } 200 201 /** 202 * Make the room password protected. 203 * 204 * @return a reference to this object. 205 * @throws MucConfigurationNotSupportedException if the requested MUC configuration is not supported by the MUC service. 206 */ 207 public MucConfigFormManager makePasswordProtected() throws MucConfigurationNotSupportedException { 208 return setIsPasswordProtected(true); 209 } 210 211 /** 212 * Set if this room is password protected. Rooms are by default not password protected. 213 * 214 * @param isPasswordProtected TODO javadoc me please 215 * @return a reference to this object. 216 * @throws MucConfigurationNotSupportedException if the requested MUC configuration is not supported by the MUC service. 217 */ 218 public MucConfigFormManager setIsPasswordProtected(boolean isPasswordProtected) 219 throws MucConfigurationNotSupportedException { 220 if (!supportsMembersOnly()) { 221 throw new MucConfigurationNotSupportedException(MUC_ROOMCONFIG_PASSWORDPROTECTEDROOM); 222 } 223 answerForm.setAnswer(MUC_ROOMCONFIG_PASSWORDPROTECTEDROOM, isPasswordProtected); 224 return this; 225 } 226 227 /** 228 * Set the room secret, aka the room password. If set and enabled, the password is required to 229 * join the room. Note that this does only set it by does not enable password protection. Use 230 * {@link #setAndEnablePassword(String)} to set a password and make the room protected. 231 * 232 * @param secret the secret/password. 233 * @return a reference to this object. 234 * @throws MucConfigurationNotSupportedException if the requested MUC configuration is not supported by the MUC service. 235 */ 236 public MucConfigFormManager setRoomSecret(String secret) 237 throws MucConfigurationNotSupportedException { 238 if (!answerForm.hasField(MUC_ROOMCONFIG_ROOMSECRET)) { 239 throw new MucConfigurationNotSupportedException(MUC_ROOMCONFIG_ROOMSECRET); 240 } 241 answerForm.setAnswer(MUC_ROOMCONFIG_ROOMSECRET, secret); 242 return this; 243 } 244 245 /** 246 * Submit the configuration as {@link FilledForm} to the room. 247 * 248 * @throws NoResponseException if there was no response from the room. 249 * @throws XMPPErrorException if there was an XMPP error returned. 250 * @throws NotConnectedException if the XMPP connection is not connected. 251 * @throws InterruptedException if the calling thread was interrupted. 252 */ 253 public void submitConfigurationForm() throws NoResponseException, XMPPErrorException, NotConnectedException, 254 InterruptedException { 255 if (owners != null) { 256 answerForm.setAnswer(MUC_ROOMCONFIG_ROOMOWNERS, JidUtil.toStringList(owners)); 257 } 258 multiUserChat.sendConfigurationForm(answerForm); 259 } 260}