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