/** * Copyright 2012 Voxbone SA/NV * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.voxbone.kelpie; import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.apache.log4j.Logger; import org.jabberstudio.jso.JID; /** * Mapping of jabber ids to telephone numbers, usefull if you want to also want communicaton * from SIP -> XMPP direction * */ public class UriMappings { private static List<Mapping> mappings = new ArrayList<Mapping>(); private static Logger log = Logger.getLogger(UriMappings.class); private static String host; private static String fakeId; private static boolean mapJID = false; private static boolean fwdJID = false; private static String fwdDOMAIN; private static class Mapping { public String sip_id; public JID jid; public String voiceResource; public Mapping(String sip_id, JID jid) { this.sip_id = sip_id; this.jid = jid; this.voiceResource = null; } } public static void configure(Properties properties) { fakeId = properties.getProperty("com.voxbone.kelpie.service_name", "kelpie"); mapJID = Boolean.parseBoolean(properties.getProperty("com.voxbone.kelpie.map.strict", "false")); fwdJID = Boolean.parseBoolean(properties.getProperty("com.voxbone.kelpie.map.forward", "false")); fwdDOMAIN = properties.getProperty("com.voxbone.kelpie.map.forward.domain", "gmail.com"); buildMap(properties); } public static void initialize() { for (Mapping m : mappings) { if (m.voiceResource == null) { Session sess = SessionManager.findCreateSession(host, m.jid); sess.sendSubscribeRequest(new JID(fakeId + "@" + host), m.jid, "subscribe"); } } } public static void buildMap(Properties p) { host = p.getProperty("com.voxbone.kelpie.hostname"); for (Object okey : p.keySet()) { String key = (String) okey; if (key.startsWith("com.voxbone.kelpie.mapping") && fwdJID == false) { String sip_id = key.substring("com.voxbone.kelpie.mapping.".length()); JID jid = new JID((String) p.get(key)); log.debug("Adding " + sip_id + " => " + jid); mappings.add(new Mapping(sip_id, jid)); } } } public static JID toJID(String sip_id) { for (Mapping m : mappings) { if (m.sip_id.equals(sip_id)) { return m.jid; } } if (sip_id != null && !sip_id.startsWith("+") && (fwdJID && fwdDOMAIN != null) ) { // full domain forwarder mode String [] fields = sip_id.split("\\+", 2); JID jid = new JID(fields[0] + "@" + fwdDOMAIN ); log.debug("Adding forwarder " + sip_id + " => " + jid ); mappings.add(new Mapping(sip_id, jid)); for (Mapping m : mappings) { if (m.jid == jid) { Session sess = SessionManager.findCreateSession(host, m.jid); try { sess.sendSubscribeRequest(new JID(fakeId + "@" + host), m.jid, "subscribe"); } catch (Exception e) { log.debug("Error " + e + " subscribing to " + sip_id + " => " + jid); } int count = 0; while (count < 5 && m.voiceResource == null) try { log.debug("NULL resource for " + jid + " - sending probe..."); sess.sendSubscribeRequest(new JID(fakeId + "@" + host), m.jid, "probe"); count++; Thread.sleep(500); } catch (Exception ex) { continue; } if (m.voiceResource == null && mapJID) { log.debug("Removing forwarder " + sip_id + " => " + jid ); mappings.remove(m); SessionManager.removeSession(SessionManager.getSession(jid)); return null; } } } return jid; } else if (sip_id.contains("+") && !sip_id.startsWith("+") ) { String [] fields = sip_id.split("\\+", 2); JID jid = new JID(fields[0] + "@" + fields[1]); log.debug("Resolving resources for " + jid ); if (UriMappings.isDup(sip_id)) { log.debug("Existing Mapping found for " + sip_id ); } else { log.debug("Adding live " + sip_id + " => " + jid ); mappings.add(new Mapping(sip_id, jid)); } for (Mapping m : mappings) { if (m.jid == jid) { Session sess = SessionManager.findCreateSession(host, m.jid); try { sess.sendSubscribeRequest(new JID(fakeId + "@" + host), m.jid, "subscribe"); } catch (Exception e) { log.debug("Error " + e + " subscribing to " + sip_id + " => " + jid); } int count = 0; while (count < 5 && m.voiceResource == null) try { log.debug("NULL resource for " + jid); count++; Thread.sleep(500); } catch (Exception ex) { continue; } if (m.voiceResource == null && mapJID) { log.debug("Removing live " + sip_id + " => " + jid ); mappings.remove(m); SessionManager.removeSession(SessionManager.getSession(jid)); return null; } } } return jid; } return null; } public static String toSipId(JID jid) { for (Mapping m : mappings) { if (m.jid.match(jid)) { return m.sip_id; } } return jid.getNode() + "+" + jid.getDomain(); } public static void addVoiceResource(JID jid) { for (Mapping m : mappings) { if (m.jid.match(jid)) { m.voiceResource = jid.getResource(); log.info("Resource for " + m.jid + " set to " + jid.getResource()); } } } public static String getVoiceResource(JID jid) { for (Mapping m : mappings) { if (m.jid.match(jid)) { return m.voiceResource; } } return null; } public static boolean isDup(String sip_id){ for (Mapping m : mappings) { if (m.sip_id.equals(sip_id)) { return true; } } return false; } }