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    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     */
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     */
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
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     */
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     */
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     */
393    public String toString() {
394        return this.encode();
395    }
396}
397