PageRenderTime 65ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/servers/diameter/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/controller/RealmTableImpl.java

http://mobicents.googlecode.com/
Java | 409 lines | 245 code | 51 blank | 113 comment | 42 complexity | 03e45533ecf04b04337480edd77709a0 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause
  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright 2011, Red Hat, Inc. and individual contributors
  4. * by the @authors tag. See the copyright.txt in the distribution for a
  5. * full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.jdiameter.client.impl.controller;
  23. import java.util.ArrayList;
  24. import java.util.Collection;
  25. import java.util.HashMap;
  26. import java.util.HashSet;
  27. import java.util.List;
  28. import java.util.Map;
  29. import java.util.Set;
  30. import org.jdiameter.api.ApplicationId;
  31. import org.jdiameter.api.Avp;
  32. import org.jdiameter.api.InternalException;
  33. import org.jdiameter.api.LocalAction;
  34. import org.jdiameter.api.Realm;
  35. import org.jdiameter.api.Statistic;
  36. import org.jdiameter.client.api.IAnswer;
  37. import org.jdiameter.client.api.IAssembler;
  38. import org.jdiameter.client.api.IContainer;
  39. import org.jdiameter.client.api.IMessage;
  40. import org.jdiameter.client.api.IRequest;
  41. import org.jdiameter.client.api.controller.IRealm;
  42. import org.jdiameter.client.api.controller.IRealmTable;
  43. import org.jdiameter.server.api.agent.IAgent;
  44. import org.jdiameter.server.api.agent.IAgentConfiguration;
  45. import org.jdiameter.server.api.agent.IProxy;
  46. import org.jdiameter.server.api.agent.IRedirect;
  47. import org.slf4j.Logger;
  48. import org.slf4j.LoggerFactory;
  49. /**
  50. *
  51. * @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
  52. * @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
  53. */
  54. public class RealmTableImpl implements IRealmTable {
  55. private static final Logger logger = LoggerFactory.getLogger(RealmTableImpl.class);
  56. // maps name->realms (cause there might be more than one realm defined, with different app id.
  57. protected Map<String, RealmSet> realmNameToRealmSet = new HashMap<String, RealmSet>();
  58. // "cache" so we don't have to combine all realms
  59. protected List<String> allRealmsSet = new ArrayList<String>();
  60. protected String localRealmName;
  61. protected String localHost;
  62. protected IAssembler assembler;
  63. public RealmTableImpl(IContainer con) {
  64. this.assembler = con.getAssemblerFacility();
  65. }
  66. public boolean realmExists(String realmName) {
  67. // NOTE: this is still valid for local realm
  68. return (this.realmNameToRealmSet.containsKey(realmName) && this.realmNameToRealmSet.get(realmName).size() > 0);
  69. }
  70. public Realm addRealm(String realmName, ApplicationId applicationId, LocalAction action, String agentConfiguration, boolean dynamic, long expirationTime, String[] hosts) throws InternalException {
  71. logger.debug("Adding realm [{}] into network map", realmName);
  72. IAgentConfiguration agentConf = this.assembler.getComponentInstance(IAgentConfiguration.class);
  73. if(agentConf != null) {
  74. agentConf = agentConf.parse(agentConfiguration);
  75. }
  76. return addRealm(realmName, applicationId, action, agentConf, dynamic, expirationTime, hosts);
  77. }
  78. public Realm addRealm(String realmName, ApplicationId applicationId, LocalAction action, IAgentConfiguration agentConf, boolean dynamic, long expirationTime, String[] hosts) throws InternalException {
  79. IAgent agent = null;
  80. switch (action) {
  81. case LOCAL:
  82. case RELAY:
  83. break;
  84. case PROXY:
  85. agent = this.assembler.getComponentInstance(IProxy.class);
  86. break;
  87. case REDIRECT:
  88. agent = this.assembler.getComponentInstance(IRedirect.class);
  89. break;
  90. }
  91. RealmImpl realmImpl = new RealmImpl(realmName, applicationId, action, agent,agentConf, dynamic, expirationTime, hosts);
  92. addRealm(realmImpl);
  93. return realmImpl;
  94. }
  95. /*
  96. * (non-Javadoc)
  97. * @see org.jdiameter.client.api.controller.IRealmTable#getRealm(java.lang.String, org.jdiameter.api.ApplicationId)
  98. */
  99. public Realm getRealm(String realmName, ApplicationId applicationId) {
  100. RealmSet rs = this.realmNameToRealmSet.get(realmName);
  101. return rs == null ? null : rs.getRealm(applicationId);
  102. }
  103. /*
  104. * (non-Javadoc)
  105. * @see org.jdiameter.client.api.controller.IRealmTable#removeRealmApplicationId(java.lang.String, org.jdiameter.api.ApplicationId)
  106. */
  107. public Realm removeRealmApplicationId(String realmName, ApplicationId appId) {
  108. RealmSet set = this.realmNameToRealmSet.get(realmName);
  109. if (set != null) {
  110. Realm r = set.getRealm(appId);
  111. set.removeRealm(appId);
  112. if (set.size() == 0 && !realmName.equals(this.localRealmName)) {
  113. this.realmNameToRealmSet.remove(realmName);
  114. this.allRealmsSet.remove(realmName);
  115. }
  116. return r;
  117. }
  118. return null;
  119. }
  120. /*
  121. * (non-Javadoc)
  122. * @see org.jdiameter.client.api.controller.IRealmTable#removeRealms(java.lang.String)
  123. */
  124. public Collection<Realm> removeRealm(String realmName) {
  125. RealmSet set = null;
  126. if (realmName.equals(this.localRealmName)) {
  127. set = this.realmNameToRealmSet.get(realmName);
  128. }
  129. else {
  130. set = this.realmNameToRealmSet.remove(realmName);
  131. if (set != null) {
  132. Collection<Realm> present = set.values();
  133. allRealmsSet.remove(realmName);
  134. return new ArrayList<Realm>(present);
  135. }
  136. }
  137. return null;
  138. }
  139. /*
  140. * (non-Javadoc)
  141. * @see org.jdiameter.client.api.controller.IRealmTable#getRealms(java.lang.String)
  142. */
  143. public Collection<Realm> getRealms(String realmName) {
  144. RealmSet set = this.realmNameToRealmSet.get(realmName);
  145. if (set != null) {
  146. Collection<Realm> present = set.values();
  147. return new ArrayList<Realm>(present);
  148. }
  149. return null;
  150. }
  151. /*
  152. * (non-Javadoc)
  153. * @see org.jdiameter.client.api.controller.IRealmTable#getRealms()
  154. */
  155. public Collection<Realm> getRealms() {
  156. ArrayList<Realm> rss = new ArrayList<Realm>();
  157. Set<String> keys = new HashSet<String>(this.realmNameToRealmSet.keySet());
  158. for (String key : keys) {
  159. RealmSet rs = this.realmNameToRealmSet.get(key);
  160. rss.addAll(rs.values());
  161. }
  162. return rss;
  163. }
  164. /*
  165. * (non-Javadoc)
  166. * @see org.jdiameter.client.api.controller.IRealmTable#matchRealm(org.jdiameter.client.api.IRequest)
  167. */
  168. public Realm matchRealm(IRequest request) {
  169. try {
  170. // once again casting...
  171. IMessage req = (IMessage) request;
  172. String destinationRealm = req.getAvps().getAvp(Avp.DESTINATION_REALM).getDiameterIdentity();
  173. // we have req, we need match, not dummy longest from right BS match.
  174. return this.matchRealm(req, destinationRealm);
  175. }
  176. catch (Exception e) {
  177. logger.error("Unable to read Destination-Realm AVP to match realm to request", e);
  178. }
  179. return null;
  180. }
  181. /*
  182. * (non-Javadoc)
  183. * @see org.jdiameter.client.api.controller.IRealmTable#matchRealm(org.jdiameter.client.api.IAnswer, java.lang.String)
  184. */
  185. public Realm matchRealm(IAnswer message, String destRealm) {
  186. return this.matchRealm((IMessage) message, destRealm);
  187. }
  188. /*
  189. * (non-Javadoc)
  190. * @see org.jdiameter.client.api.controller.IRealmTable#getRealmForPeer(java.lang.String)
  191. */
  192. public String getRealmForPeer(String fqdn) {
  193. //
  194. Collection<Realm> realms = getRealms();
  195. for (Realm r : realms) {
  196. IRealm ir = (IRealm) r;
  197. if (ir.hasPeerName(fqdn)) {
  198. return ir.getName();
  199. }
  200. }
  201. return null;
  202. }
  203. /**
  204. * @param appId
  205. */
  206. public void addLocalApplicationId(ApplicationId appId) {
  207. RealmSet rs = getRealmSet(localRealmName, false);
  208. rs.addRealm(new RealmImpl(localRealmName, appId, LocalAction.LOCAL, null,null, true, -1, this.localHost) {
  209. public boolean isLocal() {
  210. return true;
  211. }
  212. });
  213. }
  214. /**
  215. * @param appId
  216. */
  217. public void removeLocalApplicationId(ApplicationId appId) {
  218. RealmSet rs = getRealmSet(localRealmName, false);
  219. Realm realm = rs.getRealm(appId);
  220. if (realm.isDynamic()) {
  221. rs.removeRealm(appId);
  222. }
  223. }
  224. /**
  225. * @param localRealm
  226. * @param fqdn
  227. */
  228. public void addLocalRealm(String localRealm, String fqdn) {
  229. this.localRealmName = localRealm;
  230. this.localHost = fqdn;
  231. getRealmSet(localRealm, true /* adds realm if not present */);
  232. }
  233. // -------------------- helper methods --------------------
  234. protected Realm matchRealm(IMessage message, String realm) {
  235. if (realmExists(realm)) {
  236. ApplicationId singleId = message.getSingleApplicationId();
  237. // check on single app id, than we iterate.
  238. Realm r = getRealm(realm, singleId);
  239. if (r == null) {
  240. List<ApplicationId> appIds = message.getApplicationIdAvps();
  241. for (int index = 0; index < appIds.size(); index++) {
  242. r = getRealm(realm, appIds.get(index));
  243. if (r != null) {
  244. break;
  245. }
  246. }
  247. }
  248. return r;
  249. }
  250. return null;
  251. }
  252. protected void addRealm(Realm realm) throws InternalException {
  253. RealmSet rs = getRealmSet(realm.getName(), true);
  254. rs.addRealm(realm);
  255. allRealmsSet.add(realm.getName());
  256. }
  257. protected RealmSet getRealmSet(String pKey, boolean create) {
  258. RealmSet rs = realmNameToRealmSet.get(pKey);
  259. if (rs == null && create) {
  260. rs = new RealmSet();
  261. realmNameToRealmSet.put(pKey, rs);
  262. }
  263. return rs;
  264. }
  265. private class RealmSet {
  266. // TODO: use two lists and iterate over index?
  267. protected Map<ApplicationId, Realm> appIdToRealm = new HashMap<ApplicationId, Realm>();
  268. /**
  269. * @param realm
  270. * @throws InternalException
  271. */
  272. public void addRealm(Realm realm) {
  273. if (this.appIdToRealm.containsKey(realm.getApplicationId())) {
  274. Realm presentRealm = this.appIdToRealm.get(realm.getApplicationId());
  275. if (realm.getName().equals(localRealmName)) {
  276. // we need to merge - its a local realm, possibly definition
  277. // of hosts that can handle requests for us.
  278. RealmImpl realmImpl = (RealmImpl) presentRealm;
  279. realmImpl.dynamic = false; // ensure its static
  280. for (String peerName : ((RealmImpl) realm).getPeerNames()) {
  281. realmImpl.addPeerName(peerName);
  282. }
  283. }
  284. else if (!presentRealm.isDynamic() && realm.isDynamic()) {
  285. // its a dynamic realm, present is static, we dont have to
  286. // do a thing?
  287. }
  288. else if (presentRealm.isDynamic() && !realm.isDynamic()) {
  289. // we need to merge?
  290. RealmImpl realmImpl = (RealmImpl) presentRealm;
  291. realmImpl.dynamic = false; // make it static :)
  292. for (String peerName : ((RealmImpl) realm).getPeerNames()) {
  293. realmImpl.addPeerName(peerName);
  294. }
  295. }
  296. else {
  297. if(logger.isDebugEnabled()) {
  298. logger.debug("Entry for realm '{}', already exists: {}", realm, this);
  299. }
  300. }
  301. }
  302. else {
  303. this.appIdToRealm.put(realm.getApplicationId(), realm);
  304. }
  305. }
  306. /**
  307. * @return
  308. */
  309. public Collection<Realm> values() {
  310. return this.appIdToRealm.values();
  311. }
  312. /**
  313. * @return
  314. */
  315. public int size() {
  316. return this.appIdToRealm.size();
  317. }
  318. /**
  319. * @param appId
  320. * @return
  321. */
  322. public Realm getRealm(ApplicationId appId) {
  323. return this.appIdToRealm.get(appId);
  324. }
  325. /**
  326. * @param appId
  327. * @return
  328. */
  329. public Realm removeRealm(ApplicationId appId) {
  330. return this.appIdToRealm.remove(appId);
  331. }
  332. }
  333. /*
  334. * (non-Javadoc)
  335. * @see org.jdiameter.api.RealmTable#getStatistic(java.lang.String)
  336. */
  337. @Override
  338. public Statistic getStatistic(String realmName) {
  339. // FIXME: ...
  340. return null;
  341. }
  342. /*
  343. * (non-Javadoc)
  344. * @see org.jdiameter.api.Wrapper#isWrapperFor(java.lang.Class)
  345. */
  346. @Override
  347. public boolean isWrapperFor(Class<?> iface) throws InternalException {
  348. return false;
  349. }
  350. /*
  351. * (non-Javadoc)
  352. * @see org.jdiameter.api.Wrapper#unwrap(java.lang.Class)
  353. */
  354. @Override
  355. public <T> T unwrap(Class<T> iface) throws InternalException {
  356. return null;
  357. }
  358. }