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  *******************************************************************************/
29 package gov.nist.javax.sip.address;
30 
31 import gov.nist.core.*;
32 
33 import 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  */
44 public 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      */
NetObject()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      */
equals(Object that)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 
match(Object other)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      */
debugDump()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      */
debugDump(int indent)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      */
toString()397     public String toString() {
398         return this.encode();
399     }
400 }
401