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