1/* 2* Conditions Of Use 3* 4* This software was developed by employees of the National Institute of 5* Standards and Technology (NIST), an agency of the Federal Government. 6* Pursuant to title 15 Untied States Code Section 105, works of NIST 7* employees are not subject to copyright protection in the United States 8* and are considered to be in the public domain. As a result, a formal 9* license is not needed to use the software. 10* 11* This software is provided by NIST as a service and is expressly 12* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED 13* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF 14* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT 15* AND DATA ACCURACY. NIST does not warrant or make any representations 16* regarding the use of the software or the results thereof, including but 17* not limited to the correctness, accuracy, reliability or usefulness of 18* the software. 19* 20* Permission to use this software is contingent upon your acceptance 21* of the terms of this agreement 22* 23* . 24* 25*/ 26/******************************************************************************* 27 * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * 28 *******************************************************************************/ 29package gov.nist.javax.sip.address; 30 31import gov.nist.core.*; 32 33import java.lang.reflect.*; 34 35/** 36 * Root object for all objects in this package. 37 * 38 * @version 1.2 $Revision: 1.10 $ $Date: 2009/07/17 18:57:22 $ 39 * 40 * @author M. Ranganathan <br/> 41 * 42 * 43 */ 44public abstract class NetObject extends GenericObject { 45 46 protected static final String CORE_PACKAGE = PackageNames.CORE_PACKAGE; 47 protected static final String NET_PACKAGE = PackageNames.NET_PACKAGE; 48 protected static final String PARSER_PACKAGE = PackageNames.PARSER_PACKAGE; 49 protected static final String UDP = "udp"; 50 protected static final String TCP = "tcp"; 51 protected static final String TRANSPORT = "transport"; 52 protected static final String METHOD = "method"; 53 protected static final String USER = "user"; 54 protected static final String PHONE = "phone"; 55 protected static final String MADDR = "maddr"; 56 protected static final String TTL = "ttl"; 57 protected static final String LR = "lr"; 58 protected static final String SIP = "sip"; 59 protected static final String SIPS = "sips"; 60 61 // Added by Daniel J. Martinez Manzano <dani@dif.um.es> 62 protected static final String TLS = "tls"; 63 64 // Added by Peter Musgrave <pmusgrave@newheights.com> 65 // params for outbound and gruu drafts 66 protected static final String GRUU = "gr"; 67 68 69 /** Default constructor 70 */ 71 public NetObject() { 72 super(); 73 } 74 75 /** 76 * An introspection based equality predicate for SIPObjects. 77 *@param that is the other object to test against. 78 */ 79 public boolean equals(Object that) { 80 if (!this.getClass().equals(that.getClass())) 81 return false; 82 Class<?> myclass = this.getClass(); 83 Class<?> hisclass = that.getClass(); 84 while (true) { 85 Field[] fields = myclass.getDeclaredFields(); 86 Field[] hisfields = hisclass.getDeclaredFields(); 87 for (int i = 0; i < fields.length; i++) { 88 Field f = fields[i]; 89 Field g = hisfields[i]; 90 // Only print protected and public members. 91 int modifier = f.getModifiers(); 92 if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) 93 continue; 94 Class<?> fieldType = f.getType(); 95 String fieldName = f.getName(); 96 if (fieldName.compareTo("stringRepresentation") == 0) { 97 continue; 98 } 99 if (fieldName.compareTo("indentation") == 0) { 100 continue; 101 } 102 try { 103 // Primitive fields are printed with type: value 104 if (fieldType.isPrimitive()) { 105 String fname = fieldType.toString(); 106 if (fname.compareTo("int") == 0) { 107 if (f.getInt(this) != g.getInt(that)) 108 return false; 109 } else if (fname.compareTo("short") == 0) { 110 if (f.getShort(this) != g.getShort(that)) 111 return false; 112 } else if (fname.compareTo("char") == 0) { 113 if (f.getChar(this) != g.getChar(that)) 114 return false; 115 } else if (fname.compareTo("long") == 0) { 116 if (f.getLong(this) != g.getLong(that)) 117 return false; 118 } else if (fname.compareTo("boolean") == 0) { 119 if (f.getBoolean(this) != g.getBoolean(that)) 120 return false; 121 } else if (fname.compareTo("double") == 0) { 122 if (f.getDouble(this) != g.getDouble(that)) 123 return false; 124 } else if (fname.compareTo("float") == 0) { 125 if (f.getFloat(this) != g.getFloat(that)) 126 return false; 127 } 128 } else if (g.get(that) == f.get(this)) 129 continue; 130 else if (f.get(this) == null && g.get(that) != null) 131 return false; 132 else if (g.get(that) == null && f.get(that) != null) 133 return false; 134 else if (!f.get(this).equals(g.get(that))) 135 return false; 136 } catch (IllegalAccessException ex1) { 137 InternalErrorHandler.handleException(ex1); 138 } 139 } 140 if (myclass.equals(NetObject.class)) 141 break; 142 else { 143 myclass = myclass.getSuperclass(); 144 hisclass = hisclass.getSuperclass(); 145 } 146 } 147 return true; 148 } 149 150 151 152 153 /** An introspection based predicate matching using a template 154 * object. Allows for partial match of two protocl Objects. 155 *@param other the match pattern to test against. The match object 156 * has to be of the same type (class). Primitive types 157 * and non-sip fields that are non null are matched for equality. 158 * Null in any field matches anything. Some book-keeping fields 159 * are ignored when making the comparison. 160 *@return true if match succeeds false otherwise. 161 */ 162 163 public boolean match(Object other) { 164 if (other == null) 165 return true; 166 if (!this.getClass().equals(other.getClass())) 167 return false; 168 GenericObject that = (GenericObject) other; 169 // System.out.println("Comparing " + that.encode()); 170 // System.out.println("this = " + this.encode()); 171 172 Class<?> hisclass = other.getClass(); 173 Class<?> myclass = this.getClass(); 174 while (true) { 175 Field[] fields = myclass.getDeclaredFields(); 176 Field[] hisfields = hisclass.getDeclaredFields(); 177 for (int i = 0; i < fields.length; i++) { 178 Field f = fields[i]; 179 Field g = hisfields[i]; 180 // Only print protected and public members. 181 int modifier = f.getModifiers(); 182 if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) 183 continue; 184 Class<?> fieldType = f.getType(); 185 String fieldName = f.getName(); 186 if (fieldName.compareTo("stringRepresentation") == 0) { 187 continue; 188 } 189 if (fieldName.compareTo("indentation") == 0) { 190 continue; 191 } 192 try { 193 // Primitive fields are printed with type: value 194 if (fieldType.isPrimitive()) { 195 String fname = fieldType.toString(); 196 if (fname.compareTo("int") == 0) { 197 if (f.getInt(this) != g.getInt(that)) 198 return false; 199 } else if (fname.compareTo("short") == 0) { 200 if (f.getShort(this) != g.getShort(that)) 201 return false; 202 } else if (fname.compareTo("char") == 0) { 203 if (f.getChar(this) != g.getChar(that)) 204 return false; 205 } else if (fname.compareTo("long") == 0) { 206 if (f.getLong(this) != g.getLong(that)) 207 return false; 208 } else if (fname.compareTo("boolean") == 0) { 209 if (f.getBoolean(this) != g.getBoolean(that)) 210 return false; 211 } else if (fname.compareTo("double") == 0) { 212 if (f.getDouble(this) != g.getDouble(that)) 213 return false; 214 } else if (fname.compareTo("float") == 0) { 215 if (f.getFloat(this) != g.getFloat(that)) 216 return false; 217 } 218 } else { 219 Object myObj = f.get(this); 220 Object hisObj = g.get(that); 221 if (hisObj != null && myObj == null) 222 return false; 223 else if (hisObj == null && myObj != null) 224 continue; 225 else if (hisObj == null && myObj == null) 226 continue; 227 else if ( 228 hisObj instanceof java.lang.String 229 && myObj instanceof java.lang.String) { 230 if (((String) hisObj).equals("")) 231 continue; 232 if (((String) myObj) 233 .compareToIgnoreCase((String) hisObj) 234 != 0) 235 return false; 236 } else if ( 237 GenericObject.isMySubclass(myObj.getClass()) 238 && GenericObject.isMySubclass(hisObj.getClass()) 239 && myObj.getClass().equals(hisObj.getClass()) 240 && ((GenericObject) hisObj).getMatcher() 241 != null) { 242 String myObjEncoded = 243 ((GenericObject) myObj).encode(); 244 boolean retval = 245 ((GenericObject) hisObj).getMatcher().match( 246 myObjEncoded); 247 if (!retval) 248 return false; 249 } else if ( 250 GenericObject.isMySubclass(myObj.getClass()) 251 && !((GenericObject) myObj).match(hisObj)) 252 return false; 253 else if ( 254 GenericObjectList.isMySubclass(myObj.getClass()) 255 && !((GenericObjectList) myObj).match(hisObj)) 256 return false; 257 } 258 } catch (IllegalAccessException ex1) { 259 InternalErrorHandler.handleException(ex1); 260 } 261 } 262 if (myclass.equals(NetObject.class)) 263 break; 264 else { 265 myclass = myclass.getSuperclass(); 266 hisclass = hisclass.getSuperclass(); 267 } 268 } 269 return true; 270 } 271 272 /** 273 * An introspection based string formatting method. We need this because 274 * in this package (although it is an exact duplicate of the one in 275 * the superclass) because it needs to access the protected members 276 * of the other objects in this class. 277 * @return String 278 */ 279 public String debugDump() { 280 stringRepresentation = ""; 281 Class<?> myclass = getClass(); 282 sprint(myclass.getName()); 283 sprint("{"); 284 Field[] fields = myclass.getDeclaredFields(); 285 for (int i = 0; i < fields.length; i++) { 286 Field f = fields[i]; 287 // Only print protected and public members. 288 int modifier = f.getModifiers(); 289 if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) 290 continue; 291 Class<?> fieldType = f.getType(); 292 String fieldName = f.getName(); 293 if (fieldName.compareTo("stringRepresentation") == 0) { 294 // avoid nasty recursions... 295 continue; 296 } 297 if (fieldName.compareTo("indentation") == 0) { 298 // formatting stuff - not relevant here. 299 continue; 300 } 301 sprint(fieldName + ":"); 302 try { 303 // Primitive fields are printed with type: value 304 if (fieldType.isPrimitive()) { 305 String fname = fieldType.toString(); 306 sprint(fname + ":"); 307 if (fname.compareTo("int") == 0) { 308 int intfield = f.getInt(this); 309 sprint(intfield); 310 } else if (fname.compareTo("short") == 0) { 311 short shortField = f.getShort(this); 312 sprint(shortField); 313 } else if (fname.compareTo("char") == 0) { 314 char charField = f.getChar(this); 315 sprint(charField); 316 } else if (fname.compareTo("long") == 0) { 317 long longField = f.getLong(this); 318 sprint(longField); 319 } else if (fname.compareTo("boolean") == 0) { 320 boolean booleanField = f.getBoolean(this); 321 sprint(booleanField); 322 } else if (fname.compareTo("double") == 0) { 323 double doubleField = f.getDouble(this); 324 sprint(doubleField); 325 } else if (fname.compareTo("float") == 0) { 326 float floatField = f.getFloat(this); 327 sprint(floatField); 328 } 329 } else if (GenericObject.class.isAssignableFrom(fieldType)) { 330 if (f.get(this) != null) { 331 sprint( 332 ((GenericObject) f.get(this)).debugDump( 333 indentation + 1)); 334 } else { 335 sprint("<null>"); 336 } 337 338 } else if ( 339 GenericObjectList.class.isAssignableFrom(fieldType)) { 340 if (f.get(this) != null) { 341 sprint( 342 ((GenericObjectList) f.get(this)).debugDump( 343 indentation + 1)); 344 } else { 345 sprint("<null>"); 346 } 347 348 } else { 349 // Dont do recursion on things that are not 350 // of our header type... 351 if (f.get(this) != null) { 352 sprint(f.get(this).getClass().getName() + ":"); 353 } else { 354 sprint(fieldType.getName() + ":"); 355 } 356 357 sprint("{"); 358 if (f.get(this) != null) { 359 sprint(f.get(this).toString()); 360 } else { 361 sprint("<null>"); 362 } 363 sprint("}"); 364 } 365 } catch (IllegalAccessException ex1) { 366 continue; // we are accessing a private field... 367 } 368 } 369 sprint("}"); 370 return stringRepresentation; 371 } 372 373 374 375 376 /** 377 * Formatter with a given starting indentation (for nested structs). 378 * @param indent int to set 379 * @return String 380 */ 381 public String debugDump(int indent) { 382 int save = indentation; 383 indentation = indent; 384 String retval = this.debugDump(); 385 indentation = save; 386 return retval; 387 } 388 389 /** Encode this to a string. 390 * 391 *@return string representation for this object. 392 */ 393 public String toString() { 394 return this.encode(); 395 } 396} 397