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