• 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 HDR 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 HDR 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 HDR removeFirst() {
281         if (hlist.size() != 0) {
282             return hlist.remove(0);
283         }
284         return null;
285     }
286 
287     /**
288      * Remove the last element of this list.
289      */
removeLast()290     public HDR removeLast() {
291         if (hlist.size() != 0) {
292             return hlist.remove(hlist.size() - 1);
293         }
294         return null;
295     }
296 
297     /**
298      * Remove a sip header from this list of sip headers.
299      *
300      * @param obj
301      *            SIPHeader to remove
302      * @return boolean
303      */
remove(HDR obj)304     public boolean remove(HDR obj) {
305         if (hlist.size() == 0)
306             return false;
307         else
308             return hlist.remove(obj);
309     }
310 
311     /**
312      * Set the root class for all objects inserted into my list (for assertion
313      * check)
314      *
315      * @param cl
316      *            class to set
317      */
setMyClass(Class<HDR> cl)318     protected void setMyClass(Class<HDR> cl) {
319         this.myClass = cl;
320     }
321 
322     /**
323      * convert to a string representation (for printing).
324      *
325      * @param indentation
326      *            int to set
327      * @return String string representation of object (for printing).
328      */
debugDump(int indentation)329     public String debugDump(int indentation) {
330         stringRepresentation = "";
331         String indent = new Indentation(indentation).getIndentation();
332 
333         String className = this.getClass().getName();
334         sprint(indent + className);
335         sprint(indent + "{");
336 
337         for (Iterator<HDR> it = hlist.iterator(); it.hasNext();) {
338             HDR sipHeader = (HDR) it.next();
339             sprint(indent + sipHeader.debugDump());
340         }
341         sprint(indent + "}");
342         return stringRepresentation;
343     }
344 
345     /**
346      * convert to a string representation
347      *
348      * @return String
349      */
debugDump()350     public String debugDump() {
351         return debugDump(0);
352     }
353 
354     /**
355      * Array conversion.
356      *
357      * @return SIPHeader []
358      */
toArray()359     public Object[] toArray() {
360         return hlist.toArray();
361 
362     }
363 
364     /**
365      * index of an element.
366      *
367      * @return index of the given element (-1) if element does not exist.
368      */
indexOf(GenericObject gobj)369     public int indexOf(GenericObject gobj) {
370         return hlist.indexOf(gobj);
371     }
372 
373     /**
374      * insert at a location.
375      *
376      * @param index
377      *            location where to add the sipHeader.
378      * @param sipHeader
379      *            SIPHeader structure to add.
380      */
381 
add(int index, HDR sipHeader)382     public void add(int index, HDR  sipHeader)
383             throws IndexOutOfBoundsException {
384         hlist.add(index, sipHeader);
385     }
386 
387     /**
388      * Equality comparison operator.
389      *
390      * @param other
391      *            the other object to compare with. true is returned iff the
392      *            classes match and list of headers herein is equal to the list
393      *            of headers in the target (order of the headers is not
394      *            important).
395      */
396     @SuppressWarnings("unchecked")
equals(Object other)397     public boolean equals(Object other) {
398 
399         if (other == this)
400             return true;
401 
402         if (other instanceof SIPHeaderList) {
403             SIPHeaderList<SIPHeader> that = (SIPHeaderList<SIPHeader>) other;
404             if (this.hlist == that.hlist)
405                 return true;
406             else if (this.hlist == null)
407                 return that.hlist == null || that.hlist.size() == 0;
408             return this.hlist.equals(that.hlist);
409         }
410         return false;
411     }
412 
413     /**
414      * Template match against a template. null field in template indicates wild
415      * card match.
416      */
match(SIPHeaderList<?> template)417     public boolean match(SIPHeaderList<?> template) {
418         if (template == null)
419             return true;
420         if (!this.getClass().equals(template.getClass()))
421             return false;
422         SIPHeaderList<SIPHeader> that = (SIPHeaderList<SIPHeader>) template;
423         if (this.hlist == that.hlist)
424             return true;
425         else if (this.hlist == null)
426             return false;
427         else {
428 
429             for (Iterator<SIPHeader> it = that.hlist.iterator(); it.hasNext();) {
430                 SIPHeader sipHeader = (SIPHeader) it.next();
431 
432                 boolean found = false;
433                 for (Iterator<HDR> it1 = this.hlist.iterator(); it1.hasNext()
434                         && !found;) {
435                     SIPHeader sipHeader1 = (SIPHeader) it1.next();
436                     found = sipHeader1.match(sipHeader);
437                 }
438                 if (!found)
439                     return false;
440             }
441             return true;
442         }
443     }
444 
445 
446     /**
447      * make a clone of this header list.
448      *
449      * @return clone of this Header.
450      */
clone()451     public Object clone() {
452         try {
453             Class<?> clazz = this.getClass();
454 
455             Constructor<?> cons = clazz.getConstructor((Class[])null);
456             SIPHeaderList<HDR> retval = (SIPHeaderList<HDR>) cons.newInstance((Object[])null);
457             retval.headerName = this.headerName;
458             retval.myClass  = this.myClass;
459             return retval.clonehlist(this.hlist);
460         } catch (Exception ex) {
461             throw new RuntimeException("Could not clone!", ex);
462         }
463     }
464 
clonehlist(List<HDR> hlistToClone)465     protected final SIPHeaderList<HDR> clonehlist(List<HDR> hlistToClone) {
466         if (hlistToClone != null) {
467             for (Iterator<HDR> it = (Iterator<HDR>) hlistToClone.iterator(); it.hasNext();) {
468                 Header h = it.next();
469                 this.hlist.add((HDR)h.clone());
470             }
471         }
472         return this;
473     }
474 
475     /**
476      * Get the number of headers in the list.
477      */
size()478     public int size() {
479         return hlist.size();
480     }
481 
482     /**
483      * Return true if this is a header list (overrides the base class method
484      * which returns false).
485      *
486      * @return true
487      */
isHeaderList()488     public boolean isHeaderList() {
489         return true;
490     }
491 
492     /**
493      * Encode the body of this header (the stuff that follows headerName). A.K.A
494      * headerValue. This will not give a reasonable result for WWW-Authenticate,
495      * Authorization, Proxy-Authenticate and Proxy-Authorization and hence this
496      * is protected.
497      */
encodeBody()498     protected String encodeBody() {
499         return encodeBody(new StringBuffer()).toString();
500     }
501 
encodeBody(StringBuffer buffer)502     protected StringBuffer encodeBody(StringBuffer buffer) {
503         ListIterator<HDR> iterator = this.listIterator();
504         while (true) {
505             SIPHeader sipHeader = (SIPHeader) iterator.next();
506             if ( sipHeader == this ) throw new RuntimeException ("Unexpected circularity in SipHeaderList");
507             sipHeader.encodeBody(buffer);
508             // if (body.equals("")) System.out.println("BODY == ");
509             if (iterator.hasNext()) {
510                 if (!this.headerName.equals(PrivacyHeader.NAME))
511                     buffer.append(Separators.COMMA);
512                 else
513                     buffer.append(Separators.SEMICOLON);
514                 continue;
515             } else
516                 break;
517 
518         }
519         return buffer;
520     }
521 
addAll(Collection<? extends HDR> collection)522     public boolean addAll(Collection<? extends HDR> collection) {
523         return this.hlist.addAll(collection);
524     }
525 
addAll(int index, Collection<? extends HDR> collection)526     public boolean addAll(int index, Collection<? extends HDR> collection) {
527         return this.hlist.addAll(index, collection);
528 
529     }
530 
containsAll(Collection<?> collection)531     public boolean containsAll(Collection<?> collection) {
532         return this.hlist.containsAll(collection);
533     }
534 
535 
536 
537 
clear()538     public void clear() {
539         this.hlist.clear();
540     }
541 
contains(Object header)542     public boolean contains(Object header) {
543         return this.hlist.contains(header);
544     }
545 
546 
547     /**
548      * Get the object at the specified location.
549      *
550      * @param index --
551      *            location from which to get the object.
552      *
553      */
get(int index)554     public HDR get(int index) {
555         return  this.hlist.get(index);
556     }
557 
558     /**
559      * Return the index of a given object.
560      *
561      * @param obj --
562      *            object whose index to compute.
563      */
indexOf(Object obj)564     public int indexOf(Object obj) {
565         return this.hlist.indexOf(obj);
566     }
567 
568     /**
569      * Return the iterator to the imbedded list.
570      *
571      * @return iterator to the imbedded list.
572      *
573      */
574 
iterator()575     public java.util.Iterator<HDR> iterator() {
576         return this.hlist.listIterator();
577     }
578 
579     /**
580      * Get the last index of the given object.
581      *
582      * @param obj --
583      *            object whose index to find.
584      */
lastIndexOf(Object obj)585     public int lastIndexOf(Object obj) {
586 
587         return this.hlist.lastIndexOf(obj);
588     }
589 
590     /**
591      * Remove the given object.
592      *
593      * @param obj --
594      *            object to remove.
595      *
596      */
597 
remove(Object obj)598     public boolean remove(Object obj) {
599 
600         return this.hlist.remove(obj);
601     }
602 
603     /**
604      * Remove the object at a given index.
605      *
606      * @param index --
607      *            index at which to remove the object
608      */
609 
remove(int index)610     public HDR remove(int index) {
611         return this.hlist.remove(index);
612     }
613 
614     /**
615      * Remove all the elements.
616      * @see List#removeAll(java.util.Collection)
617      */
removeAll(java.util.Collection<?> collection)618     public boolean removeAll(java.util.Collection<?> collection) {
619         return this.hlist.removeAll(collection);
620     }
621 
622 
623     /**
624      * @see List#retainAll(java.util.Collection)
625      * @param collection
626      */
retainAll(java.util.Collection<?> collection)627     public boolean retainAll(java.util.Collection<?> collection) {
628         return this.hlist.retainAll(collection);
629     }
630 
631     /**
632      * Get a sublist of the list.
633      *
634      * @see List#subList(int, int)
635      */
subList(int index1, int index2)636     public java.util.List<HDR> subList(int index1, int index2) {
637         return this.hlist.subList(index1, index2);
638 
639     }
640 
641     /**
642      * @see Object#hashCode()
643      * @return -- the computed hashcode.
644      */
hashCode()645     public int hashCode() {
646 
647         return this.headerName.hashCode();
648     }
649 
650     /**
651      * Set a SIPHeader at a particular position in the list.
652      *
653      * @see List#set(int, java.lang.Object)
654      */
set(int position, HDR sipHeader)655     public HDR set(int position, HDR sipHeader) {
656 
657         return hlist.set(position, sipHeader);
658 
659     }
660 
661 
setPrettyEncode(boolean flag)662     public static void setPrettyEncode(boolean flag) {
663         prettyEncode = flag;
664     }
665 
666 
toArray(T[] array)667     public <T> T[] toArray(T[] array) {
668         return this.hlist.toArray(array);
669     }
670 
671 
672 }
673