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    // 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     */
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     */
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
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     */
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     */
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     */
397    public String toString() {
398        return this.encode();
399    }
400}
401