1 20 21 package org.xmpp.packet; 22 23 import org.jivesoftware.stringprep.IDNA; 24 import org.jivesoftware.stringprep.Stringprep; 25 26 import java.util.*; 27 28 48 public class JID implements Comparable { 49 50 private static Map stringprepCache = Collections.synchronizedMap(new Cache(1000)); 54 55 private String node; 56 private String domain; 57 private String resource; 58 59 90 public static String escapeNode(String node) { 91 if (node == null) { 92 return null; 93 } 94 StringBuilder buf = new StringBuilder (node.length() + 8); 95 for (int i=0, n=node.length(); i<n; i++) { 96 char c = node.charAt(i); 97 switch (c) { 98 case '"': buf.append("\\22"); break; 99 case '&': buf.append("\\26"); break; 100 case '\'': buf.append("\\27"); break; 101 case '/': buf.append("\\2f"); break; 102 case ':': buf.append("\\3a"); break; 103 case '<': buf.append("\\3c"); break; 104 case '>': buf.append("\\3e"); break; 105 case '@': buf.append("\\40"); break; 106 case '\\': buf.append("\\5c"); break; 107 default: { 108 if (Character.isWhitespace(c)) { 109 buf.append("\\20"); 110 } 111 else { 112 buf.append(c); 113 } 114 } 115 } 116 } 117 return buf.toString(); 118 } 119 120 151 public static String unescapeNode(String node) { 152 if (node == null) { 153 return null; 154 } 155 char [] nodeChars = node.toCharArray(); 156 StringBuilder buf = new StringBuilder (nodeChars.length); 157 for (int i=0, n=nodeChars.length; i<n; i++) { 158 compare: { 159 char c = node.charAt(i); 160 if (c == '\\' && i+2<n) { 161 char c2 = nodeChars[i+1]; 162 char c3 = nodeChars[i+2]; 163 if (c2 == '2') { 164 switch (c3) { 165 case '0': buf.append(' '); i+=2; break compare; 166 case '2': buf.append('"'); i+=2; break compare; 167 case '6': buf.append('&'); i+=2; break compare; 168 case '7': buf.append('\''); i+=2; break compare; 169 case 'f': buf.append('/'); i+=2; break compare; 170 } 171 } 172 else if (c2 == '3') { 173 switch (c3) { 174 case 'a': buf.append(':'); i+=2; break compare; 175 case 'c': buf.append('<'); i+=2; break compare; 176 case 'e': buf.append('>'); i+=2; break compare; 177 } 178 } 179 else if (c2 == '4') { 180 if (c3 == '0') { 181 buf.append("@"); 182 i+=2; 183 break compare; 184 } 185 } 186 else if (c2 == '5') { 187 if (c3 == 'c') { 188 buf.append("\\"); 189 i+=2; 190 break compare; 191 } 192 } 193 } 194 buf.append(c); 195 } 196 } 197 return buf.toString(); 198 } 199 200 206 public JID(String jid) { 207 if (jid == null) { 208 throw new NullPointerException ("JID cannot be null"); 209 } 210 String node = null; 211 String domain = null; 212 String resource = null; 213 214 int atIndex = jid.indexOf("@"); 215 int slashIndex = jid.indexOf("/"); 216 217 if (atIndex > 0) { 219 node = jid.substring(0, atIndex); 220 } 221 222 if (atIndex + 1 > jid.length()) { 224 throw new IllegalArgumentException ("JID with empty domain not valid"); 225 } 226 if (atIndex < 0) { 227 if (slashIndex > 0) { 228 domain = jid.substring(0, slashIndex); 229 } 230 else { 231 domain = jid; 232 } 233 } 234 else { 235 if (slashIndex > 0) { 236 domain = jid.substring(atIndex + 1, slashIndex); 237 } 238 else { 239 domain = jid.substring(atIndex + 1); 240 } 241 } 242 243 if (slashIndex + 1 > jid.length() || slashIndex < 0) { 245 resource = null; 246 } 247 else { 248 resource = jid.substring(slashIndex + 1); 249 } 250 251 init(node, domain,resource); 252 } 253 254 262 public JID(String node, String domain, String resource) { 263 if (domain == null) { 264 throw new NullPointerException ("Domain cannot be null"); 265 } 266 init(node, domain, resource); 267 } 268 269 278 JID(String jid, Object fake) { 279 fake = null; if (jid == null) { 281 throw new NullPointerException ("JID cannot be null"); 282 } 283 284 int atIndex = jid.indexOf("@"); 285 int slashIndex = jid.indexOf("/"); 286 287 if (atIndex > 0) { 289 node = jid.substring(0, atIndex); 290 } 291 292 if (atIndex + 1 > jid.length()) { 294 throw new IllegalArgumentException ("JID with empty domain not valid"); 295 } 296 if (atIndex < 0) { 297 if (slashIndex > 0) { 298 domain = jid.substring(0, slashIndex); 299 } 300 else { 301 domain = jid; 302 } 303 } 304 else { 305 if (slashIndex > 0) { 306 domain = jid.substring(atIndex + 1, slashIndex); 307 } 308 else { 309 domain = jid.substring(atIndex + 1); 310 } 311 } 312 313 if (slashIndex + 1 > jid.length() || slashIndex < 0) { 315 resource = null; 316 } 317 else { 318 resource = jid.substring(slashIndex + 1); 319 } 320 } 321 322 331 private void init(String node, String domain, String resource) { 332 if (node != null && node.equals("")) { 334 node = null; 335 } 336 if (resource != null && resource.equals("")) { 337 resource = null; 338 } 339 try { 341 if (!stringprepCache.containsKey(node)) { 342 this.node = Stringprep.nodeprep(node); 343 if (node != null && node.length()*2 > 1023) { 345 throw new IllegalArgumentException ("Node cannot be larger than 1023 bytes. " + 346 "Size is " + (node.length() * 2) + " bytes."); 347 } 348 stringprepCache.put(this.node, null); 349 } 350 else { 351 this.node = node; 352 } 353 if (!stringprepCache.containsKey(domain)) { 358 this.domain = Stringprep.nameprep(IDNA.toASCII(domain), false); 359 if (domain.length()*2 > 1023) { 361 throw new IllegalArgumentException ("Domain cannot be larger than 1023 bytes. " + 362 "Size is " + (domain.length() * 2) + " bytes."); 363 } 364 stringprepCache.put(this.domain, null); 365 } 366 else { 367 this.domain = domain; 368 } 369 if (!stringprepCache.containsKey(resource)) { 370 this.resource = Stringprep.resourceprep(resource); 371 if (resource != null && resource.length()*2 > 1023) { 373 throw new IllegalArgumentException ("Resource cannot be larger than 1023 bytes. " + 374 "Size is " + (resource.length() * 2) + " bytes."); 375 } 376 stringprepCache.put(this.resource, null); 377 } 378 else { 379 this.resource = resource; 380 } 381 } 382 catch (Exception e) { 383 StringBuilder buf = new StringBuilder (); 384 if (node != null) { 385 buf.append(node).append("@"); 386 } 387 buf.append(domain); 388 if (resource != null) { 389 buf.append("/").append(resource); 390 } 391 throw new IllegalArgumentException ("Illegal JID: " + buf.toString(), e); 392 } 393 } 394 395 400 public String getNode() { 401 return node; 402 } 403 404 409 public String getDomain() { 410 return domain; 411 } 412 413 418 public String getResource() { 419 return resource; 420 } 421 422 428 public String toBareJID() { 429 StringBuilder buf = new StringBuilder (); 430 if (node != null) { 431 buf.append(node).append("@"); 432 } 433 buf.append(domain); 434 return buf.toString(); 435 } 436 437 442 public String toString() { 443 StringBuilder buf = new StringBuilder (); 444 if (node != null) { 445 buf.append(node).append("@"); 446 } 447 buf.append(domain); 448 if (resource != null) { 449 buf.append("/").append(resource); 450 } 451 return buf.toString(); 452 } 453 454 public int hashCode() { 455 return toString().hashCode(); 456 } 457 458 public boolean equals(Object object) { 459 if (!(object instanceof JID)) { 460 return false; 461 } 462 if (this == object) { 463 return true; 464 } 465 JID jid = (JID)object; 466 if (node != null) { 468 if (!node.equals(jid.node)) { 469 return false; 470 } 471 } 472 else if (jid.node != null) { 474 return false; 475 } 476 if (!domain.equals(jid.domain)) { 478 return false; 479 } 480 if (resource != null) { 482 if (!resource.equals(jid.resource)) { 483 return false; 484 } 485 } 486 else if (jid.resource != null) { 488 return false; 489 } 490 return true; 492 } 493 494 public int compareTo(Object o) { 495 if (!(o instanceof JID)) { 496 throw new ClassCastException ("Ojbect not instanceof JID: " + o); 497 } 498 JID jid = (JID)o; 499 500 int compare = domain.compareTo(jid.domain); 502 if (compare == 0 && node != null && jid.node != null) { 503 compare = node.compareTo(jid.node); 504 } 505 if (compare == 0 && resource != null && jid.resource != null) { 506 compare = resource.compareTo(jid.resource); 507 } 508 return compare; 509 } 510 511 526 public static boolean equals(String jid1, String jid2) { 527 return new JID(jid1).equals(new JID(jid2)); 528 } 529 530 534 private static class Cache extends LinkedHashMap { 535 536 private int maxSize; 537 538 public Cache(int maxSize) { 539 super(64, .75f, true); 540 this.maxSize = maxSize; 541 } 542 543 protected boolean removeEldestEntry(Map.Entry eldest) { 544 return size() > maxSize; 545 } 546 } 547 } | Popular Tags |