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