• 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 
31 import gov.nist.core.GenericObject;
32 import gov.nist.core.Separators;
33 import gov.nist.javax.sip.header.ims.PrivacyHeader;
34 
35 import javax.sip.header.Header;
36 import java.lang.reflect.Constructor;
37 import java.util.*;
38 
39 /**
40  *
41  * This is the root class for all lists of SIP headers. It imbeds a
42  * SIPObjectList object and extends SIPHeader Lists of ContactSIPObjects etc.
43  * derive from this class. This supports homogeneous lists (all elements in the
44  * list are of the same class). We use this for building type homogeneous lists
45  * of SIPObjects that appear in SIPHeaders
46  *
47  * @version 1.2 $Revision: 1.15 $ $Date: 2005/10/09 18:47:53
48  */
49 public abstract class SIPHeaderList<HDR extends SIPHeader> extends SIPHeader implements java.util.List<HDR>, Header {
50 
51     private static boolean prettyEncode = false;
52     /**
53      * hlist field.
54      */
55     protected List<HDR> hlist;
56 
57     private Class<HDR> myClass;
58 
getName()59     public String getName() {
60         return this.headerName;
61     }
62 
63 
SIPHeaderList()64     private SIPHeaderList() {
65         hlist = new LinkedList<HDR>();
66     }
67 
68     /**
69      * Constructor
70      *
71      * @param objclass
72      *            Class to set
73      * @param hname
74      *            String to set
75      */
SIPHeaderList(Class<HDR> objclass, String hname)76     protected SIPHeaderList(Class<HDR> objclass, String hname) {
77         this();
78         this.headerName = hname;
79         this.myClass =  objclass;
80     }
81 
82     /**
83      * Concatenate the list of stuff that we are keeping around and also the
84      * text corresponding to these structures (that we parsed).
85      *
86      * @param objectToAdd
87      */
add(HDR objectToAdd)88     public boolean add(HDR objectToAdd) {
89         hlist.add((HDR)objectToAdd);
90         return true;
91     }
92 
93     /**
94      * Concatenate the list of stuff that we are keeping around and also the
95      * text corresponding to these structures (that we parsed).
96      *
97      * @param obj
98      *            Genericobject to set
99      */
addFirst(HDR obj)100     public void addFirst(HDR obj) {
101         hlist.add(0,(HDR) obj);
102     }
103 
104     /**
105      * Add to this list.
106      *
107      * @param sipheader
108      *            SIPHeader to add.
109      * @param top
110      *            is true if we want to add to the top of the list.
111      */
add(HDR sipheader, boolean top)112     public void add(HDR sipheader, boolean top) {
113         if (top)
114             this.addFirst(sipheader);
115         else
116             this.add(sipheader);
117     }
118 
119     /**
120      * Concatenate two compatible lists. This appends or prepends the new list
121      * to the end of this list.
122      *
123      * @param other
124      *            SIPHeaderList to set
125      * @param topFlag
126      *            flag which indicates which end to concatenate
127      *            the lists.
128      * @throws IllegalArgumentException
129      *             if the two lists are not compatible
130      */
concatenate(SIPHeaderList<HDR> other, boolean topFlag)131     public void concatenate(SIPHeaderList<HDR> other, boolean topFlag)
132             throws IllegalArgumentException {
133         if (!topFlag) {
134             this.addAll(other);
135         } else {
136             // add given items to the top end of the list.
137             this.addAll(0, other);
138         }
139 
140     }
141 
142 
143 
144     /**
145      * Encode a list of sip headers. Headers are returned in cannonical form.
146      *
147      * @return String encoded string representation of this list of headers.
148      *         (Contains string append of each encoded header).
149      */
encode()150     public String encode() {
151         return encode(new StringBuffer()).toString();
152     }
153 
encode(StringBuffer buffer)154     public StringBuffer encode(StringBuffer buffer) {
155         if (hlist.isEmpty()) {
156             buffer.append(headerName).append(':').append(Separators.NEWLINE);
157         }
158         else {
159             // The following headers do not have comma separated forms for
160             // multiple headers. Thus, they must be encoded separately.
161             if (this.headerName.equals(SIPHeaderNames.WWW_AUTHENTICATE)
162                     || this.headerName.equals(SIPHeaderNames.PROXY_AUTHENTICATE)
163                     || this.headerName.equals(SIPHeaderNames.AUTHORIZATION)
164                     || this.headerName.equals(SIPHeaderNames.PROXY_AUTHORIZATION)
165                     || (prettyEncode &&
166                             (this.headerName.equals(SIPHeaderNames.VIA) || this.headerName.equals(SIPHeaderNames.ROUTE) || this.headerName.equals(SIPHeaderNames.RECORD_ROUTE))) // Less confusing to read
167                     || this.getClass().equals( ExtensionHeaderList.class) ) {
168                 ListIterator<HDR> li = hlist.listIterator();
169                 while (li.hasNext()) {
170                     HDR sipheader = (HDR) li.next();
171                     sipheader.encode(buffer);
172                 }
173             } else {
174                 // These can be concatenated together in an comma separated
175                 // list.
176                 buffer.append(headerName).append(Separators.COLON).append(Separators.SP);
177                 this.encodeBody(buffer);
178                 buffer.append(Separators.NEWLINE);
179             }
180         }
181         return buffer;
182     }
183 
184     /**
185      * Return a list of encoded strings (one for each sipheader).
186      *
187      * @return LinkedList containing encoded strings in this header list. an
188      *         empty list is returned if this header list contains no sip
189      *         headers.
190      */
191 
getHeadersAsEncodedStrings()192     public List<String> getHeadersAsEncodedStrings() {
193         List<String> retval = new LinkedList<String>();
194 
195         ListIterator<HDR> li = hlist.listIterator();
196         while (li.hasNext()) {
197             Header sipheader = li.next();
198             retval.add(sipheader.toString());
199 
200         }
201 
202         return retval;
203 
204     }
205 
206     /**
207      * Get the first element of this list.
208      *
209      * @return SIPHeader first element of the list.
210      */
getFirst()211     public Header getFirst() {
212         if (hlist == null || hlist.isEmpty())
213             return null;
214         else
215             return  hlist.get(0);
216     }
217 
218     /**
219      * Get the last element of this list.
220      *
221      * @return SIPHeader last element of the list.
222      */
getLast()223     public Header getLast() {
224         if (hlist == null || hlist.isEmpty())
225             return null;
226         return  hlist.get(hlist.size() - 1);
227     }
228 
229     /**
230      * Get the class for the headers of this list.
231      *
232      * @return Class of header supported by this list.
233      */
getMyClass()234     public Class<HDR> getMyClass() {
235         return  this.myClass;
236     }
237 
238     /**
239      * Empty check
240      *
241      * @return boolean true if list is empty
242      */
isEmpty()243     public boolean isEmpty() {
244         return hlist.isEmpty();
245     }
246 
247     /**
248      * Get an initialized iterator for my imbedded list
249      *
250      * @return the generated ListIterator
251      */
listIterator()252     public ListIterator<HDR> listIterator() {
253 
254         return hlist.listIterator(0);
255     }
256 
257     /**
258      * Get the imbedded linked list.
259      *
260      * @return the imedded linked list of SIP headers.
261      */
getHeaderList()262     public List<HDR> getHeaderList() {
263         return this.hlist;
264     }
265 
266     /**
267      * Get the list iterator for a given position.
268      *
269      * @param position
270      *            position for the list iterator to return
271      * @return the generated list iterator
272      */
listIterator(int position)273     public ListIterator<HDR> listIterator(int position) {
274         return hlist.listIterator(position);
275     }
276 
277     /**
278      * Remove the first element of this list.
279      */
removeFirst()280     public void removeFirst() {
281         if (hlist.size() != 0)
282             hlist.remove(0);
283 
284     }
285 
286     /**
287      * Remove the last element of this list.
288      */
removeLast()289     public void removeLast() {
290         if (hlist.size() != 0)
291             hlist.remove(hlist.size() - 1);
292     }
293 
294     /**
295      * Remove a sip header from this list of sip headers.
296      *
297      * @param obj
298      *            SIPHeader to remove
299      * @return boolean
300      */
remove(HDR obj)301     public boolean remove(HDR obj) {
302         if (hlist.size() == 0)
303             return false;
304         else
305             return hlist.remove(obj);
306     }
307 
308     /**
309      * Set the root class for all objects inserted into my list (for assertion
310      * check)
311      *
312      * @param cl
313      *            class to set
314      */
setMyClass(Class<HDR> cl)315     protected void setMyClass(Class<HDR> cl) {
316         this.myClass = cl;
317     }
318 
319     /**
320      * convert to a string representation (for printing).
321      *
322      * @param indentation
323      *            int to set
324      * @return String string representation of object (for printing).
325      */
debugDump(int indentation)326     public String debugDump(int indentation) {
327         stringRepresentation = "";
328         String indent = new Indentation(indentation).getIndentation();
329 
330         String className = this.getClass().getName();
331         sprint(indent + className);
332         sprint(indent + "{");
333 
334         for (Iterator<HDR> it = hlist.iterator(); it.hasNext();) {
335             HDR sipHeader = (HDR) it.next();
336             sprint(indent + sipHeader.debugDump());
337         }
338         sprint(indent + "}");
339         return stringRepresentation;
340     }
341 
342     /**
343      * convert to a string representation
344      *
345      * @return String
346      */
debugDump()347     public String debugDump() {
348         return debugDump(0);
349     }
350 
351     /**
352      * Array conversion.
353      *
354      * @return SIPHeader []
355      */
toArray()356     public Object[] toArray() {
357         return hlist.toArray();
358 
359     }
360 
361     /**
362      * index of an element.
363      *
364      * @return index of the given element (-1) if element does not exist.
365      */
indexOf(GenericObject gobj)366     public int indexOf(GenericObject gobj) {
367         return hlist.indexOf(gobj);
368     }
369 
370     /**
371      * insert at a location.
372      *
373      * @param index
374      *            location where to add the sipHeader.
375      * @param sipHeader
376      *            SIPHeader structure to add.
377      */
378 
add(int index, HDR sipHeader)379     public void add(int index, HDR  sipHeader)
380             throws IndexOutOfBoundsException {
381         hlist.add(index, sipHeader);
382     }
383 
384     /**
385      * Equality comparison operator.
386      *
387      * @param other
388      *            the other object to compare with. true is returned iff the
389      *            classes match and list of headers herein is equal to the list
390      *            of headers in the target (order of the headers is not
391      *            important).
392      */
393     @SuppressWarnings("unchecked")
equals(Object other)394     public boolean equals(Object other) {
395 
396         if (other == this)
397             return true;
398 
399         if (other instanceof SIPHeaderList) {
400             SIPHeaderList<SIPHeader> that = (SIPHeaderList<SIPHeader>) other;
401             if (this.hlist == that.hlist)
402                 return true;
403             else if (this.hlist == null)
404                 return that.hlist == null || that.hlist.size() == 0;
405             return this.hlist.equals(that.hlist);
406         }
407         return false;
408     }
409 
410     /**
411      * Template match against a template. null field in template indicates wild
412      * card match.
413      */
match(SIPHeaderList<?> template)414     public boolean match(SIPHeaderList<?> template) {
415         if (template == null)
416             return true;
417         if (!this.getClass().equals(template.getClass()))
418             return false;
419         SIPHeaderList<SIPHeader> that = (SIPHeaderList<SIPHeader>) template;
420         if (this.hlist == that.hlist)
421             return true;
422         else if (this.hlist == null)
423             return false;
424         else {
425 
426             for (Iterator<SIPHeader> it = that.hlist.iterator(); it.hasNext();) {
427                 SIPHeader sipHeader = (SIPHeader) it.next();
428 
429                 boolean found = false;
430                 for (Iterator<HDR> it1 = this.hlist.iterator(); it1.hasNext()
431                         && !found;) {
432                     SIPHeader sipHeader1 = (SIPHeader) it1.next();
433                     found = sipHeader1.match(sipHeader);
434                 }
435                 if (!found)
436                     return false;
437             }
438             return true;
439         }
440     }
441 
442 
443     /**
444      * make a clone of this header list.
445      *
446      * @return clone of this Header.
447      */
clone()448     public Object clone() {
449         try {
450             Class<?> clazz = this.getClass();
451 
452             Constructor<?> cons = clazz.getConstructor((Class[])null);
453             SIPHeaderList<HDR> retval = (SIPHeaderList<HDR>) cons.newInstance((Object[])null);
454             retval.headerName = this.headerName;
455             retval.myClass  = this.myClass;
456             return retval.clonehlist(this.hlist);
457         } catch (Exception ex) {
458             throw new RuntimeException("Could not clone!", ex);
459         }
460     }
461 
clonehlist(List<HDR> hlistToClone)462     protected final SIPHeaderList<HDR> clonehlist(List<HDR> hlistToClone) {
463         if (hlistToClone != null) {
464             for (Iterator<HDR> it = (Iterator<HDR>) hlistToClone.iterator(); it.hasNext();) {
465                 Header h = it.next();
466                 this.hlist.add((HDR)h.clone());
467             }
468         }
469         return this;
470     }
471 
472     /**
473      * Get the number of headers in the list.
474      */
size()475     public int size() {
476         return hlist.size();
477     }
478 
479     /**
480      * Return true if this is a header list (overrides the base class method
481      * which returns false).
482      *
483      * @return true
484      */
isHeaderList()485     public boolean isHeaderList() {
486         return true;
487     }
488 
489     /**
490      * Encode the body of this header (the stuff that follows headerName). A.K.A
491      * headerValue. This will not give a reasonable result for WWW-Authenticate,
492      * Authorization, Proxy-Authenticate and Proxy-Authorization and hence this
493      * is protected.
494      */
encodeBody()495     protected String encodeBody() {
496         return encodeBody(new StringBuffer()).toString();
497     }
498 
encodeBody(StringBuffer buffer)499     protected StringBuffer encodeBody(StringBuffer buffer) {
500         ListIterator<HDR> iterator = this.listIterator();
501         while (true) {
502             SIPHeader sipHeader = (SIPHeader) iterator.next();
503             if ( sipHeader == this ) throw new RuntimeException ("Unexpected circularity in SipHeaderList");
504             sipHeader.encodeBody(buffer);
505             // if (body.equals("")) System.out.println("BODY == ");
506             if (iterator.hasNext()) {
507                 if (!this.headerName.equals(PrivacyHeader.NAME))
508                     buffer.append(Separators.COMMA);
509                 else
510                     buffer.append(Separators.SEMICOLON);
511                 continue;
512             } else
513                 break;
514 
515         }
516         return buffer;
517     }
518 
addAll(Collection<? extends HDR> collection)519     public boolean addAll(Collection<? extends HDR> collection) {
520         return this.hlist.addAll(collection);
521     }
522 
addAll(int index, Collection<? extends HDR> collection)523     public boolean addAll(int index, Collection<? extends HDR> collection) {
524         return this.hlist.addAll(index, collection);
525 
526     }
527 
containsAll(Collection<?> collection)528     public boolean containsAll(Collection<?> collection) {
529         return this.hlist.containsAll(collection);
530     }
531 
532 
533 
534 
clear()535     public void clear() {
536         this.hlist.clear();
537     }
538 
contains(Object header)539     public boolean contains(Object header) {
540         return this.hlist.contains(header);
541     }
542 
543 
544     /**
545      * Get the object at the specified location.
546      *
547      * @param index --
548      *            location from which to get the object.
549      *
550      */
get(int index)551     public HDR get(int index) {
552         return  this.hlist.get(index);
553     }
554 
555     /**
556      * Return the index of a given object.
557      *
558      * @param obj --
559      *            object whose index to compute.
560      */
indexOf(Object obj)561     public int indexOf(Object obj) {
562         return this.hlist.indexOf(obj);
563     }
564 
565     /**
566      * Return the iterator to the imbedded list.
567      *
568      * @return iterator to the imbedded list.
569      *
570      */
571 
iterator()572     public java.util.Iterator<HDR> iterator() {
573         return this.hlist.listIterator();
574     }
575 
576     /**
577      * Get the last index of the given object.
578      *
579      * @param obj --
580      *            object whose index to find.
581      */
lastIndexOf(Object obj)582     public int lastIndexOf(Object obj) {
583 
584         return this.hlist.lastIndexOf(obj);
585     }
586 
587     /**
588      * Remove the given object.
589      *
590      * @param obj --
591      *            object to remove.
592      *
593      */
594 
remove(Object obj)595     public boolean remove(Object obj) {
596 
597         return this.hlist.remove(obj);
598     }
599 
600     /**
601      * Remove the object at a given index.
602      *
603      * @param index --
604      *            index at which to remove the object
605      */
606 
remove(int index)607     public HDR remove(int index) {
608         return this.hlist.remove(index);
609     }
610 
611     /**
612      * Remove all the elements.
613      * @see List#removeAll(java.util.Collection)
614      */
removeAll(java.util.Collection<?> collection)615     public boolean removeAll(java.util.Collection<?> collection) {
616         return this.hlist.removeAll(collection);
617     }
618 
619 
620     /**
621      * @see List#retainAll(java.util.Collection)
622      * @param collection
623      */
retainAll(java.util.Collection<?> collection)624     public boolean retainAll(java.util.Collection<?> collection) {
625         return this.hlist.retainAll(collection);
626     }
627 
628     /**
629      * Get a sublist of the list.
630      *
631      * @see List#subList(int, int)
632      */
subList(int index1, int index2)633     public java.util.List<HDR> subList(int index1, int index2) {
634         return this.hlist.subList(index1, index2);
635 
636     }
637 
638     /**
639      * @see Object#hashCode()
640      * @return -- the computed hashcode.
641      */
hashCode()642     public int hashCode() {
643 
644         return this.headerName.hashCode();
645     }
646 
647     /**
648      * Set a SIPHeader at a particular position in the list.
649      *
650      * @see List#set(int, java.lang.Object)
651      */
set(int position, HDR sipHeader)652     public HDR set(int position, HDR sipHeader) {
653 
654         return hlist.set(position, sipHeader);
655 
656     }
657 
658 
setPrettyEncode(boolean flag)659     public static void setPrettyEncode(boolean flag) {
660         prettyEncode = flag;
661     }
662 
663 
toArray(T[] array)664     public <T> T[] toArray(T[] array) {
665         return this.hlist.toArray(array);
666     }
667 
668 
669 }
670