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 // BEGIN android-added 47 protected static final long serialVersionUID = 6149926203633320729L; 48 // END android-added 49 50 protected static final String CORE_PACKAGE = PackageNames.CORE_PACKAGE; 51 protected static final String NET_PACKAGE = PackageNames.NET_PACKAGE; 52 protected static final String PARSER_PACKAGE = PackageNames.PARSER_PACKAGE; 53 protected static final String UDP = "udp"; 54 protected static final String TCP = "tcp"; 55 protected static final String TRANSPORT = "transport"; 56 protected static final String METHOD = "method"; 57 protected static final String USER = "user"; 58 protected static final String PHONE = "phone"; 59 protected static final String MADDR = "maddr"; 60 protected static final String TTL = "ttl"; 61 protected static final String LR = "lr"; 62 protected static final String SIP = "sip"; 63 protected static final String SIPS = "sips"; 64 65 // Added by Daniel J. Martinez Manzano <dani@dif.um.es> 66 protected static final String TLS = "tls"; 67 68 // Added by Peter Musgrave <pmusgrave@newheights.com> 69 // params for outbound and gruu drafts 70 protected static final String GRUU = "gr"; 71 72 73 /** Default constructor 74 */ 75 public NetObject() { 76 super(); 77 } 78 79 /** 80 * An introspection based equality predicate for SIPObjects. 81 *@param that is the other object to test against. 82 */ 83 public boolean equals(Object that) { 84 if (!this.getClass().equals(that.getClass())) 85 return false; 86 Class<?> myclass = this.getClass(); 87 Class<?> hisclass = that.getClass(); 88 while (true) { 89 Field[] fields = myclass.getDeclaredFields(); 90 Field[] hisfields = hisclass.getDeclaredFields(); 91 for (int i = 0; i < fields.length; i++) { 92 Field f = fields[i]; 93 Field g = hisfields[i]; 94 // Only print protected and public members. 95 int modifier = f.getModifiers(); 96 if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) 97 continue; 98 Class<?> fieldType = f.getType(); 99 String fieldName = f.getName(); 100 if (fieldName.compareTo("stringRepresentation") == 0) { 101 continue; 102 } 103 if (fieldName.compareTo("indentation") == 0) { 104 continue; 105 } 106 try { 107 // Primitive fields are printed with type: value 108 if (fieldType.isPrimitive()) { 109 String fname = fieldType.toString(); 110 if (fname.compareTo("int") == 0) { 111 if (f.getInt(this) != g.getInt(that)) 112 return false; 113 } else if (fname.compareTo("short") == 0) { 114 if (f.getShort(this) != g.getShort(that)) 115 return false; 116 } else if (fname.compareTo("char") == 0) { 117 if (f.getChar(this) != g.getChar(that)) 118 return false; 119 } else if (fname.compareTo("long") == 0) { 120 if (f.getLong(this) != g.getLong(that)) 121 return false; 122 } else if (fname.compareTo("boolean") == 0) { 123 if (f.getBoolean(this) != g.getBoolean(that)) 124 return false; 125 } else if (fname.compareTo("double") == 0) { 126 if (f.getDouble(this) != g.getDouble(that)) 127 return false; 128 } else if (fname.compareTo("float") == 0) { 129 if (f.getFloat(this) != g.getFloat(that)) 130 return false; 131 } 132 } else if (g.get(that) == f.get(this)) 133 continue; 134 else if (f.get(this) == null && g.get(that) != null) 135 return false; 136 else if (g.get(that) == null && f.get(that) != null) 137 return false; 138 else if (!f.get(this).equals(g.get(that))) 139 return false; 140 } catch (IllegalAccessException ex1) { 141 InternalErrorHandler.handleException(ex1); 142 } 143 } 144 if (myclass.equals(NetObject.class)) 145 break; 146 else { 147 myclass = myclass.getSuperclass(); 148 hisclass = hisclass.getSuperclass(); 149 } 150 } 151 return true; 152 } 153 154 155 156 157 /** An introspection based predicate matching using a template 158 * object. Allows for partial match of two protocl Objects. 159 *@param other the match pattern to test against. The match object 160 * has to be of the same type (class). Primitive types 161 * and non-sip fields that are non null are matched for equality. 162 * Null in any field matches anything. Some book-keeping fields 163 * are ignored when making the comparison. 164 *@return true if match succeeds false otherwise. 165 */ 166 167 public boolean match(Object other) { 168 if (other == null) 169 return true; 170 if (!this.getClass().equals(other.getClass())) 171 return false; 172 GenericObject that = (GenericObject) other; 173 // System.out.println("Comparing " + that.encode()); 174 // System.out.println("this = " + this.encode()); 175 176 Class<?> hisclass = other.getClass(); 177 Class<?> myclass = this.getClass(); 178 while (true) { 179 Field[] fields = myclass.getDeclaredFields(); 180 Field[] hisfields = hisclass.getDeclaredFields(); 181 for (int i = 0; i < fields.length; i++) { 182 Field f = fields[i]; 183 Field g = hisfields[i]; 184 // Only print protected and public members. 185 int modifier = f.getModifiers(); 186 if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) 187 continue; 188 Class<?> fieldType = f.getType(); 189 String fieldName = f.getName(); 190 if (fieldName.compareTo("stringRepresentation") == 0) { 191 continue; 192 } 193 if (fieldName.compareTo("indentation") == 0) { 194 continue; 195 } 196 try { 197 // Primitive fields are printed with type: value 198 if (fieldType.isPrimitive()) { 199 String fname = fieldType.toString(); 200 if (fname.compareTo("int") == 0) { 201 if (f.getInt(this) != g.getInt(that)) 202 return false; 203 } else if (fname.compareTo("short") == 0) { 204 if (f.getShort(this) != g.getShort(that)) 205 return false; 206 } else if (fname.compareTo("char") == 0) { 207 if (f.getChar(this) != g.getChar(that)) 208 return false; 209 } else if (fname.compareTo("long") == 0) { 210 if (f.getLong(this) != g.getLong(that)) 211 return false; 212 } else if (fname.compareTo("boolean") == 0) { 213 if (f.getBoolean(this) != g.getBoolean(that)) 214 return false; 215 } else if (fname.compareTo("double") == 0) { 216 if (f.getDouble(this) != g.getDouble(that)) 217 return false; 218 } else if (fname.compareTo("float") == 0) { 219 if (f.getFloat(this) != g.getFloat(that)) 220 return false; 221 } 222 } else { 223 Object myObj = f.get(this); 224 Object hisObj = g.get(that); 225 if (hisObj != null && myObj == null) 226 return false; 227 else if (hisObj == null && myObj != null) 228 continue; 229 else if (hisObj == null && myObj == null) 230 continue; 231 else if ( 232 hisObj instanceof java.lang.String 233 && myObj instanceof java.lang.String) { 234 if (((String) hisObj).equals("")) 235 continue; 236 if (((String) myObj) 237 .compareToIgnoreCase((String) hisObj) 238 != 0) 239 return false; 240 } else if ( 241 GenericObject.isMySubclass(myObj.getClass()) 242 && GenericObject.isMySubclass(hisObj.getClass()) 243 && myObj.getClass().equals(hisObj.getClass()) 244 && ((GenericObject) hisObj).getMatcher() 245 != null) { 246 String myObjEncoded = 247 ((GenericObject) myObj).encode(); 248 boolean retval = 249 ((GenericObject) hisObj).getMatcher().match( 250 myObjEncoded); 251 if (!retval) 252 return false; 253 } else if ( 254 GenericObject.isMySubclass(myObj.getClass()) 255 && !((GenericObject) myObj).match(hisObj)) 256 return false; 257 else if ( 258 GenericObjectList.isMySubclass(myObj.getClass()) 259 && !((GenericObjectList) myObj).match(hisObj)) 260 return false; 261 } 262 } catch (IllegalAccessException ex1) { 263 InternalErrorHandler.handleException(ex1); 264 } 265 } 266 if (myclass.equals(NetObject.class)) 267 break; 268 else { 269 myclass = myclass.getSuperclass(); 270 hisclass = hisclass.getSuperclass(); 271 } 272 } 273 return true; 274 } 275 276 /** 277 * An introspection based string formatting method. We need this because 278 * in this package (although it is an exact duplicate of the one in 279 * the superclass) because it needs to access the protected members 280 * of the other objects in this class. 281 * @return String 282 */ 283 public String debugDump() { 284 stringRepresentation = ""; 285 Class<?> myclass = getClass(); 286 sprint(myclass.getName()); 287 sprint("{"); 288 Field[] fields = myclass.getDeclaredFields(); 289 for (int i = 0; i < fields.length; i++) { 290 Field f = fields[i]; 291 // Only print protected and public members. 292 int modifier = f.getModifiers(); 293 if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) 294 continue; 295 Class<?> fieldType = f.getType(); 296 String fieldName = f.getName(); 297 if (fieldName.compareTo("stringRepresentation") == 0) { 298 // avoid nasty recursions... 299 continue; 300 } 301 if (fieldName.compareTo("indentation") == 0) { 302 // formatting stuff - not relevant here. 303 continue; 304 } 305 sprint(fieldName + ":"); 306 try { 307 // Primitive fields are printed with type: value 308 if (fieldType.isPrimitive()) { 309 String fname = fieldType.toString(); 310 sprint(fname + ":"); 311 if (fname.compareTo("int") == 0) { 312 int intfield = f.getInt(this); 313 sprint(intfield); 314 } else if (fname.compareTo("short") == 0) { 315 short shortField = f.getShort(this); 316 sprint(shortField); 317 } else if (fname.compareTo("char") == 0) { 318 char charField = f.getChar(this); 319 sprint(charField); 320 } else if (fname.compareTo("long") == 0) { 321 long longField = f.getLong(this); 322 sprint(longField); 323 } else if (fname.compareTo("boolean") == 0) { 324 boolean booleanField = f.getBoolean(this); 325 sprint(booleanField); 326 } else if (fname.compareTo("double") == 0) { 327 double doubleField = f.getDouble(this); 328 sprint(doubleField); 329 } else if (fname.compareTo("float") == 0) { 330 float floatField = f.getFloat(this); 331 sprint(floatField); 332 } 333 } else if (GenericObject.class.isAssignableFrom(fieldType)) { 334 if (f.get(this) != null) { 335 sprint( 336 ((GenericObject) f.get(this)).debugDump( 337 indentation + 1)); 338 } else { 339 sprint("<null>"); 340 } 341 342 } else if ( 343 GenericObjectList.class.isAssignableFrom(fieldType)) { 344 if (f.get(this) != null) { 345 sprint( 346 ((GenericObjectList) f.get(this)).debugDump( 347 indentation + 1)); 348 } else { 349 sprint("<null>"); 350 } 351 352 } else { 353 // Dont do recursion on things that are not 354 // of our header type... 355 if (f.get(this) != null) { 356 sprint(f.get(this).getClass().getName() + ":"); 357 } else { 358 sprint(fieldType.getName() + ":"); 359 } 360 361 sprint("{"); 362 if (f.get(this) != null) { 363 sprint(f.get(this).toString()); 364 } else { 365 sprint("<null>"); 366 } 367 sprint("}"); 368 } 369 } catch (IllegalAccessException ex1) { 370 continue; // we are accessing a private field... 371 } 372 } 373 sprint("}"); 374 return stringRepresentation; 375 } 376 377 378 379 380 /** 381 * Formatter with a given starting indentation (for nested structs). 382 * @param indent int to set 383 * @return String 384 */ 385 public String debugDump(int indent) { 386 int save = indentation; 387 indentation = indent; 388 String retval = this.debugDump(); 389 indentation = save; 390 return retval; 391 } 392 393 /** Encode this to a string. 394 * 395 *@return string representation for this object. 396 */ 397 public String toString() { 398 return this.encode(); 399 } 400} 401