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     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      */
NetObject()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      */
equals(Object that)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 
match(Object other)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      */
debugDump()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      */
debugDump(int indent)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      */
toString()393     public String toString() {
394         return this.encode();
395     }
396 }
397