001/**
002 *
003 * Copyright 2019 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.jid_prep;
018
019import java.util.Map;
020import java.util.WeakHashMap;
021
022import org.jivesoftware.smack.Manager;
023import org.jivesoftware.smack.SmackException.NoResponseException;
024import org.jivesoftware.smack.SmackException.NotConnectedException;
025import org.jivesoftware.smack.XMPPConnection;
026import org.jivesoftware.smack.XMPPException.XMPPErrorException;
027import org.jivesoftware.smack.packet.StanzaError;
028
029import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
030import org.jivesoftware.smackx.jid_prep.element.JidPrepIq;
031
032import org.jxmpp.jid.DomainBareJid;
033import org.jxmpp.jid.Jid;
034
035public class JidPrepManager extends Manager {
036
037    public static final String NAMESPACE = JidPrepIq.NAMESPACE;
038
039    private static final Map<XMPPConnection, JidPrepManager> INSTANCES = new WeakHashMap<>();
040
041    private final ServiceDiscoveryManager serviceDiscoveryManager;
042
043    public static synchronized JidPrepManager getInstanceFor(XMPPConnection connection) {
044        JidPrepManager manager = INSTANCES.get(connection);
045        if (manager == null) {
046            manager = new JidPrepManager(connection);
047            INSTANCES.put(connection, manager);
048        }
049        return manager;
050    }
051
052    public JidPrepManager(XMPPConnection connection) {
053        super(connection);
054
055        serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
056    }
057
058    public String requestJidPrep(String jidToBePrepped)
059                    throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
060        DomainBareJid serviceAddress = serviceDiscoveryManager.findService(NAMESPACE, true);
061        return requestJidPrep(serviceAddress, jidToBePrepped);
062    }
063
064    public String requestJidPrep(Jid jidPrepService, String jidToBePrepped)
065                    throws NoResponseException, NotConnectedException, InterruptedException, XMPPErrorException {
066        JidPrepIq jidPrepRequest = new JidPrepIq(jidToBePrepped);
067        jidPrepRequest.setTo(jidPrepService);
068
069        JidPrepIq jidPrepResponse;
070        try {
071            jidPrepResponse = connection().sendIqRequestAndWaitForResponse(jidPrepRequest);
072        } catch (XMPPErrorException e) {
073            StanzaError stanzaError = e.getStanzaError();
074            if (stanzaError.getCondition() == StanzaError.Condition.jid_malformed) {
075                // jid-malformed is, sadly, returned if the jid can not be normalized. This means we can not distinguish
076                // if the error is returned because e.g. the IQ's 'to' address was malformed (c.f. RFC 6120 ยง 8.3.3.8)
077                // or if the JID to prep was malformed. Assume the later is the case and return 'null'.
078                return null;
079            }
080
081            throw e;
082        }
083
084        return jidPrepResponse.getJid();
085    }
086
087    public boolean isSupported(Jid jid)
088                    throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
089        return serviceDiscoveryManager.supportsFeature(jid, NAMESPACE);
090    }
091}