001/** 002 * 003 * Copyright 2020 Paul Schaub. 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.List; 021import java.util.Map; 022import java.util.WeakHashMap; 023 024import org.jivesoftware.smack.Manager; 025import org.jivesoftware.smack.SmackException; 026import org.jivesoftware.smack.XMPPConnection; 027import org.jivesoftware.smack.XMPPConnectionRegistry; 028import org.jivesoftware.smack.XMPPException; 029import org.jivesoftware.smack.filter.StanzaExtensionFilter; 030import org.jivesoftware.smack.packet.Message; 031import org.jivesoftware.smack.packet.MessageBuilder; 032import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; 033import org.jivesoftware.smackx.muc.packet.GroupChatInvitation; 034 035import org.jxmpp.jid.EntityBareJid; 036 037/** 038 * Smacks API for XEP-0249: Direct MUC Invitations. 039 * Use this instead of {@link org.jivesoftware.smackx.muc.packet.MUCUser.Invite}. 040 * 041 * To invite a user to a group chat, use {@link #inviteToMuc(MultiUserChat, EntityBareJid)}. 042 * 043 * In order to listen for incoming invitations, register a {@link DirectMucInvitationListener} using 044 * {@link #addInvitationListener(DirectMucInvitationListener)}. 045 * 046 * @see <a href="https://xmpp.org/extensions/xep-0249.html">Direct MUC Invitations</a> 047 */ 048public final class DirectMucInvitationManager extends Manager { 049 050 private static final Map<XMPPConnection, DirectMucInvitationManager> INSTANCES = new WeakHashMap<>(); 051 private final List<DirectMucInvitationListener> directMucInvitationListeners = new ArrayList<>(); 052 private final ServiceDiscoveryManager serviceDiscoveryManager; 053 054 static { 055 XMPPConnectionRegistry.addConnectionCreationListener(DirectMucInvitationManager::getInstanceFor); 056 } 057 058 public static synchronized DirectMucInvitationManager getInstanceFor(XMPPConnection connection) { 059 DirectMucInvitationManager manager = INSTANCES.get(connection); 060 if (manager == null) { 061 manager = new DirectMucInvitationManager(connection); 062 INSTANCES.put(connection, manager); 063 } 064 return manager; 065 } 066 067 private DirectMucInvitationManager(XMPPConnection connection) { 068 super(connection); 069 serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection); 070 071 connection().addAsyncStanzaListener(stanza -> { 072 GroupChatInvitation invitation = stanza.getExtension(GroupChatInvitation.class); 073 for (DirectMucInvitationListener listener : directMucInvitationListeners) { 074 listener.invitationReceived(invitation, stanza); 075 } 076 }, new StanzaExtensionFilter(GroupChatInvitation.ELEMENT, GroupChatInvitation.NAMESPACE)); 077 serviceDiscoveryManager.addFeature(GroupChatInvitation.NAMESPACE); 078 } 079 080 public void inviteToMuc(MultiUserChat muc, EntityBareJid user) 081 throws SmackException.NotConnectedException, InterruptedException { 082 inviteToMuc(muc, user, null, null, false, null); 083 } 084 085 public void inviteToMuc(MultiUserChat muc, EntityBareJid user, String password, String reason, boolean continueAsOneToOneChat, String thread) 086 throws SmackException.NotConnectedException, InterruptedException { 087 inviteToMuc(user, new GroupChatInvitation(muc.getRoom(), reason, password, continueAsOneToOneChat, thread)); 088 } 089 090 public void inviteToMuc(EntityBareJid jid, GroupChatInvitation invitation) throws SmackException.NotConnectedException, InterruptedException { 091 Message invitationMessage = MessageBuilder.buildMessage() 092 .to(jid) 093 .addExtension(invitation) 094 .build(); 095 connection().sendStanza(invitationMessage); 096 } 097 098 public boolean userSupportsInvitations(EntityBareJid jid) 099 throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, 100 SmackException.NoResponseException { 101 return serviceDiscoveryManager.supportsFeature(jid, GroupChatInvitation.NAMESPACE); 102 } 103 104 public synchronized void addInvitationListener(DirectMucInvitationListener listener) { 105 directMucInvitationListeners.add(listener); 106 } 107 108 public synchronized void removeInvitationListener(DirectMucInvitationListener listener) { 109 directMucInvitationListeners.remove(listener); 110 } 111}