Home | History | Annotate | Download | only in header
      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      */
     54     protected SIPObject() {
     55         super();
     56     }
     57 
     58 
     59 
     60     /** Debug function
     61      */
     62     public void dbgPrint() {
     63         super.dbgPrint();
     64     }
     65 
     66     /** Encode the header into a String.
     67      * @return String
     68      */
     69     public abstract String encode();
     70 
     71     /** Encode the header into the given StringBuffer.
     72      * Default implemation calls encode().
     73      */
     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      */
     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      */
    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      */
    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      */
    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 
    398     public String toString() {
    399         return this.encode();
    400     }
    401 
    402 }
    403