001/**
002 *
003 * Copyright 2017 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.jingle;
018
019import java.util.HashMap;
020import java.util.Iterator;
021import java.util.Set;
022import java.util.WeakHashMap;
023
024import org.jivesoftware.smack.Manager;
025import org.jivesoftware.smack.XMPPConnection;
026import org.jivesoftware.smackx.jingle.element.Jingle;
027import org.jivesoftware.smackx.jingle.element.JingleContent;
028import org.jivesoftware.smackx.jingle.element.JingleContentTransport;
029import org.jivesoftware.smackx.jingle.transports.JingleTransportManager;
030import org.jivesoftware.smackx.jingle.transports.jingle_ibb.element.JingleIBBTransport;
031import org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransport;
032
033/**
034 * Manager where TransportMethods are registered.
035 */
036public final class JingleTransportMethodManager extends Manager {
037
038    private static final WeakHashMap<XMPPConnection, JingleTransportMethodManager> INSTANCES = new WeakHashMap<>();
039
040    private final HashMap<String, JingleTransportManager<?>> transportManagers = new HashMap<>();
041
042    private static final String[] transportPreference = new String[] {
043            JingleS5BTransport.NAMESPACE_V1,
044            JingleIBBTransport.NAMESPACE_V1
045    };
046
047    private JingleTransportMethodManager(XMPPConnection connection) {
048        super(connection);
049    }
050
051    public static JingleTransportMethodManager getInstanceFor(XMPPConnection connection) {
052        JingleTransportMethodManager manager = INSTANCES.get(connection);
053        if (manager == null) {
054            manager = new JingleTransportMethodManager(connection);
055            INSTANCES.put(connection, manager);
056        }
057        return manager;
058    }
059
060    public void registerTransportManager(JingleTransportManager<?> manager) {
061        transportManagers.put(manager.getNamespace(), manager);
062    }
063
064    public static JingleTransportManager<?> getTransportManager(XMPPConnection connection, String namespace) {
065        return getInstanceFor(connection).getTransportManager(namespace);
066    }
067
068    public JingleTransportManager<?> getTransportManager(String namespace) {
069        return transportManagers.get(namespace);
070    }
071
072    public static JingleTransportManager<?> getTransportManager(XMPPConnection connection, Jingle request) {
073        return getInstanceFor(connection).getTransportManager(request);
074    }
075    public JingleTransportManager<?> getTransportManager(Jingle request) {
076
077        JingleContent content = request.getContents().get(0);
078        if (content == null) {
079            return null;
080        }
081
082        JingleContentTransport transport = content.getTransport();
083        if (transport == null) {
084            return null;
085        }
086
087        return getTransportManager(transport.getNamespace());
088    }
089
090    public static JingleTransportManager<?> getBestAvailableTransportManager(XMPPConnection connection) {
091        return getInstanceFor(connection).getBestAvailableTransportManager();
092    }
093
094    public JingleTransportManager<?> getBestAvailableTransportManager() {
095        JingleTransportManager<?> tm;
096        for (String ns : transportPreference) {
097            tm = getTransportManager(ns);
098            if (tm != null) {
099                return tm;
100            }
101        }
102
103        Iterator<String> it = transportManagers.keySet().iterator();
104        if (it.hasNext()) {
105            return getTransportManager(it.next());
106        }
107
108        return null;
109    }
110
111    public JingleTransportManager<?> getBestAvailableTransportManager(Set<String> except) {
112        JingleTransportManager<?> tm;
113        for (String ns : transportPreference) {
114            tm = getTransportManager(ns);
115            if (tm != null) {
116                if (except.contains(tm.getNamespace())) {
117                    continue;
118                }
119                return tm;
120            }
121        }
122
123        for (String ns : transportManagers.keySet()) {
124            if (except.contains(ns)) {
125                continue;
126            }
127            return getTransportManager(ns);
128        }
129
130        return null;
131    }
132}