Home | History | Annotate | Download | only in address
      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.address;
     30 
     31 /*
     32  *Bug fix contributions
     33  *Daniel J. Martinez Manzano <dani (at) dif.um.es>
     34  *Stefan Marx.
     35  *pmusgrave (at) newheights.com (Additions for gruu and outbound drafts)
     36  *Jeroen van Bemmel ( additions for SCTP transport )
     37  */
     38 import gov.nist.core.*;
     39 import java.util.*;
     40 import java.text.ParseException;
     41 
     42 import javax.sip.PeerUnavailableException;
     43 import javax.sip.SipFactory;
     44 import javax.sip.address.SipURI;
     45 import javax.sip.header.Header;
     46 import javax.sip.header.HeaderFactory;
     47 
     48 
     49 /**
     50  * Implementation of the SipURI interface.
     51  *
     52  *
     53  * @author M. Ranganathan   <br/>
     54  * @version 1.2 $Revision: 1.22 $ $Date: 2009/11/15 19:50:45 $
     55  *
     56  *
     57  *
     58  */
     59 public class SipUri extends GenericURI implements javax.sip.address.SipURI , SipURIExt{
     60 
     61 
     62     private static final long serialVersionUID = 7749781076218987044L;
     63 
     64     /** Authority for the uri.
     65      */
     66 
     67     protected Authority authority;
     68 
     69     /** uriParms list
     70      */
     71     protected NameValueList uriParms;
     72 
     73     /** qheaders list
     74      */
     75     protected NameValueList qheaders;
     76 
     77     /** telephoneSubscriber field
     78      */
     79     protected TelephoneNumber telephoneSubscriber;
     80 
     81     public SipUri() {
     82         this.scheme = SIP;
     83         this.uriParms = new NameValueList();
     84         this.qheaders = new NameValueList();
     85         this.qheaders.setSeparator("&");
     86     }
     87 
     88     /** Constructor given the scheme.
     89     * The scheme must be either Sip or Sips
     90     */
     91     public void setScheme(String scheme) {
     92         if (scheme.compareToIgnoreCase(SIP) != 0
     93             && scheme.compareToIgnoreCase(SIPS) != 0)
     94             throw new IllegalArgumentException("bad scheme " + scheme);
     95         this.scheme = scheme.toLowerCase();
     96     }
     97 
     98     /** Get the scheme.
     99      */
    100     public String getScheme() {
    101         return scheme;
    102     }
    103 
    104     /**
    105      * clear all URI Parameters.
    106      * @since v1.0
    107      */
    108     public void clearUriParms() {
    109         uriParms = new NameValueList();
    110     }
    111     /**
    112     *Clear the password from the user part if it exists.
    113     */
    114     public void clearPassword() {
    115         if (this.authority != null) {
    116             UserInfo userInfo = authority.getUserInfo();
    117             if (userInfo != null)
    118                 userInfo.clearPassword();
    119         }
    120     }
    121 
    122     /** Get the authority.
    123     */
    124     public Authority getAuthority() {
    125         return this.authority;
    126     }
    127 
    128     /**
    129      * Clear all Qheaders.
    130      */
    131     public void clearQheaders() {
    132         qheaders = new NameValueList();
    133     }
    134 
    135     /**
    136      * Compare two URIs and return true if they are equal.
    137      * @param that the object to compare to.
    138      * @return true if the object is equal to this object.
    139      *
    140      * JvB: Updated to define equality in terms of API methods, according to the rules
    141      * in RFC3261 section 19.1.4
    142      *
    143      * Jean Deruelle: Updated to define equality of API methods, according to the rules
    144      * in RFC3261 section 19.1.4 convert potential ie :
    145      *    %HEX HEX encoding parts of the URI before comparing them
    146      *    transport param added in comparison
    147      *    header equality enforced in comparison
    148      *
    149      */
    150     @SuppressWarnings("unchecked")
    151     @Override
    152     public boolean equals(Object that) {
    153 
    154         // Shortcut for same object
    155         if (that==this) return true;
    156 
    157         if (that instanceof SipURI) {
    158             final SipURI a = this;
    159             final SipURI b = (SipURI) that;
    160 
    161             // A SIP and SIPS URI are never equivalent
    162             if ( a.isSecure() ^ b.isSecure() ) return false;
    163 
    164             // For two URIs to be equal, the user, password, host, and port
    165             // components must match; comparison of userinfo is case-sensitive
    166             if (a.getUser()==null ^ b.getUser()==null) return false;
    167             if (a.getUserPassword()==null ^ b.getUserPassword()==null) return false;
    168 
    169             if (a.getUser()!=null && !RFC2396UrlDecoder.decode(a.getUser()).equals(RFC2396UrlDecoder.decode(b.getUser()))) return false;
    170             if (a.getUserPassword()!=null && !RFC2396UrlDecoder.decode(a.getUserPassword()).equals(RFC2396UrlDecoder.decode(b.getUserPassword()))) return false;
    171             if (a.getHost() == null ^ b.getHost() == null) return false;
    172             if (a.getHost() != null && !a.getHost().equalsIgnoreCase(b.getHost())) return false;
    173             if (a.getPort() != b.getPort()) return false;
    174 
    175             // URI parameters
    176             for (Iterator i = a.getParameterNames(); i.hasNext();) {
    177                 String pname = (String) i.next();
    178 
    179                 String p1 = a.getParameter(pname);
    180                 String p2 = b.getParameter(pname);
    181 
    182                 // those present in both must match (case-insensitive)
    183                 if (p1!=null && p2!=null && !RFC2396UrlDecoder.decode(p1).equalsIgnoreCase(RFC2396UrlDecoder.decode(p2))) return false;
    184             }
    185 
    186             // transport, user, ttl or method must match when present in either
    187             if (a.getTransportParam()==null ^ b.getTransportParam()==null) return false;
    188             if (a.getUserParam()==null ^ b.getUserParam()==null) return false;
    189             if (a.getTTLParam()==-1 ^ b.getTTLParam()==-1) return false;
    190             if (a.getMethodParam()==null ^ b.getMethodParam()==null) return false;
    191             if (a.getMAddrParam()==null ^ b.getMAddrParam()==null) return false;
    192 
    193             // Headers: must match according to their definition.
    194             if(a.getHeaderNames().hasNext() && !b.getHeaderNames().hasNext()) return false;
    195             if(!a.getHeaderNames().hasNext() && b.getHeaderNames().hasNext()) return false;
    196 
    197             if(a.getHeaderNames().hasNext() && b.getHeaderNames().hasNext()) {
    198                 HeaderFactory headerFactory = null;
    199                 try {
    200                     headerFactory = SipFactory.getInstance().createHeaderFactory();
    201                 } catch (PeerUnavailableException e) {
    202                     Debug.logError("Cannot get the header factory to parse the header of the sip uris to compare", e);
    203                     return false;
    204                 }
    205                 for (Iterator i = a.getHeaderNames(); i.hasNext();) {
    206                     String hname = (String) i.next();
    207 
    208                     String h1 = a.getHeader(hname);
    209                     String h2 = b.getHeader(hname);
    210 
    211                     if(h1 == null && h2 != null) return false;
    212                     if(h2 == null && h1 != null) return false;
    213                     // The following check should not be needed but we add it for findbugs.
    214                     if(h1 == null && h2 == null) continue;
    215                     try {
    216                         Header header1 = headerFactory.createHeader(hname, RFC2396UrlDecoder.decode(h1));
    217                         Header header2 = headerFactory.createHeader(hname, RFC2396UrlDecoder.decode(h2));
    218                         // those present in both must match according to the equals method of the corresponding header
    219                         if (!header1.equals(header2)) return false;
    220                     } catch (ParseException e) {
    221                         Debug.logError("Cannot parse one of the header of the sip uris to compare " + a + " " + b, e);
    222                         return false;
    223                     }
    224                 }
    225             }
    226 
    227             // Finally, we can conclude that they are indeed equal
    228             return true;
    229         }
    230         return false;
    231     }
    232 
    233     /**
    234      * Construct a URL from the parsed structure.
    235      * @return String
    236      */
    237     public String encode() {
    238         return encode(new StringBuffer()).toString();
    239     }
    240 
    241     public StringBuffer encode(StringBuffer buffer) {
    242         buffer.append(scheme).append(COLON);
    243         if (authority != null)
    244             authority.encode(buffer);
    245         if (!uriParms.isEmpty()) {
    246             buffer.append(SEMICOLON);
    247             uriParms.encode(buffer);
    248         }
    249         if (!qheaders.isEmpty()) {
    250             buffer.append(QUESTION);
    251             qheaders.encode(buffer);
    252         }
    253         return buffer;
    254     }
    255 
    256     /** Return a string representation.
    257     *
    258     *@return the String representation of this URI.
    259     *
    260     */
    261     public String toString() {
    262         return this.encode();
    263     }
    264 
    265     /**
    266      * getUser@host
    267      * @return user@host portion of the uri (null if none exists).
    268      *
    269      * Peter Musgrave - handle null user
    270      */
    271     public String getUserAtHost() {
    272         String user = "";
    273         if (authority.getUserInfo() != null)
    274             user = authority.getUserInfo().getUser();
    275 
    276         String host = authority.getHost().encode();
    277         StringBuffer s = null;
    278         if (user.equals("")) {
    279             s = new StringBuffer();
    280         } else {
    281             s = new StringBuffer(user).append(AT);
    282         }
    283         return s.append(host).toString();
    284     }
    285 
    286     /**
    287      * getUser@host
    288      * @return user@host portion of the uri (null if none exists).
    289      */
    290     public String getUserAtHostPort() {
    291         String user = "";
    292         if (authority.getUserInfo() != null)
    293             user = authority.getUserInfo().getUser();
    294 
    295         String host = authority.getHost().encode();
    296         int port = authority.getPort();
    297         // If port not set assign the default.
    298         StringBuffer s = null;
    299         if (user.equals("")) {
    300             s = new StringBuffer();
    301         } else {
    302             s = new StringBuffer(user).append(AT);
    303         }
    304         if (port != -1) {
    305             return s.append(host).append(COLON).append(port).toString();
    306         } else
    307             return s.append(host).toString();
    308 
    309     }
    310 
    311     /**
    312      * get the parameter (do a name lookup) and return null if none exists.
    313      * @param parmname Name of the parameter to get.
    314      * @return Parameter of the given name (null if none exists).
    315      */
    316     public Object getParm(String parmname) {
    317         Object obj = uriParms.getValue(parmname);
    318         return obj;
    319     }
    320 
    321     /**
    322      * Get the method parameter.
    323      * @return Method parameter.
    324      */
    325     public String getMethod() {
    326         return (String) getParm(METHOD);
    327     }
    328 
    329     /**
    330      * Accessor for URI parameters
    331      * @return A name-value list containing the parameters.
    332      */
    333     public NameValueList getParameters() {
    334         return uriParms;
    335     }
    336 
    337     /** Remove the URI parameters.
    338     *
    339     */
    340     public void removeParameters() {
    341         this.uriParms = new NameValueList();
    342     }
    343 
    344     /**
    345      * Accessor forSIPObjects
    346      * @return Get the query headers (that appear after the ? in
    347      * the URL)
    348      */
    349     public NameValueList getQheaders() {
    350         return qheaders;
    351     }
    352 
    353     /**
    354      * Get the urse parameter.
    355      * @return User parameter (user= phone or user=ip).
    356      */
    357     public String getUserType() {
    358         return (String) uriParms.getValue(USER);
    359     }
    360 
    361     /**
    362      * Get the password of the user.
    363      * @return User password when it embedded as part of the uri
    364      * ( a very bad idea).
    365      */
    366     public String getUserPassword() {
    367         if (authority == null)
    368             return null;
    369         return authority.getPassword();
    370     }
    371 
    372     /** Set the user password.
    373      *@param password - password to set.
    374      */
    375     public void setUserPassword(String password) {
    376         if (this.authority == null)
    377             this.authority = new Authority();
    378         authority.setPassword(password);
    379     }
    380 
    381     /**
    382      * Returns the stucture corresponding to the telephone number
    383      * provided that the user is a telephone subscriber.
    384      * @return TelephoneNumber part of the url (only makes sense
    385      * when user = phone is specified)
    386      */
    387     public TelephoneNumber getTelephoneSubscriber() {
    388         if (telephoneSubscriber == null) {
    389 
    390             telephoneSubscriber = new TelephoneNumber();
    391         }
    392         return telephoneSubscriber;
    393     }
    394 
    395     /**
    396      * Get the host and port of the server.
    397      * @return get the host:port part of the url parsed into a
    398      * structure.
    399      */
    400     public HostPort getHostPort() {
    401 
    402         if (authority == null || authority.getHost() == null )
    403             return null;
    404         else {
    405             return authority.getHostPort();
    406         }
    407     }
    408 
    409     /** Get the port from the authority field.
    410     *
    411     *@return the port from the authority field.
    412     */
    413     public int getPort() {
    414         HostPort hp = this.getHostPort();
    415         if (hp == null)
    416             return -1;
    417         return hp.getPort();
    418     }
    419 
    420     /** Get the host protion of the URI.
    421     * @return the host portion of the url.
    422     */
    423     public String getHost() {
    424         if ( authority == null) return null;
    425         else if (authority.getHost() == null ) return null;
    426         else return authority.getHost().encode();
    427     }
    428 
    429     /**
    430      * returns true if the user is a telephone subscriber.
    431      *  If the host is an Internet telephony
    432      * gateway, a telephone-subscriber field MAY be used instead
    433      * of a user field. The telephone-subscriber field uses the
    434      * notation of RFC 2806 [19]. Any characters of the un-escaped
    435      * "telephone-subscriber" that are not either in the set
    436      * "unreserved" or "user-unreserved" MUST be escaped. The set
    437      * of characters not reserved in the RFC 2806 description of
    438      * telephone-subscriber contains a number of characters in
    439      * various syntax elements that need to be escaped when used
    440      * in SIP URLs, for example quotation marks (%22), hash (%23),
    441      * colon (%3a), at-sign (%40) and the "unwise" characters,
    442      * i.e., punctuation of %5b and above.
    443      *
    444      * The telephone number is a special case of a user name and
    445      * cannot be distinguished by a BNF. Thus, a URL parameter,
    446      * user, is added to distinguish telephone numbers from user
    447      * names.
    448      *
    449      * The user parameter value "phone" indicates that the user
    450      * part contains a telephone number. Even without this
    451      * parameter, recipients of SIP URLs MAY interpret the pre-@
    452      * part as a telephone number if local restrictions on the
    453      * @return true if the user is a telephone subscriber.
    454      */
    455     public boolean isUserTelephoneSubscriber() {
    456         String usrtype = (String) uriParms.getValue(USER);
    457         if (usrtype == null)
    458             return false;
    459         return usrtype.equalsIgnoreCase(PHONE);
    460     }
    461 
    462     /**
    463      *remove the ttl value from the parameter list if it exists.
    464      */
    465     public void removeTTL() {
    466         if (uriParms != null)
    467             uriParms.delete(TTL);
    468     }
    469 
    470     /**
    471      *Remove the maddr param if it exists.
    472      */
    473     public void removeMAddr() {
    474         if (uriParms != null)
    475             uriParms.delete(MADDR);
    476     }
    477 
    478     /**
    479      *Delete the transport string.
    480      */
    481     public void removeTransport() {
    482         if (uriParms != null)
    483             uriParms.delete(TRANSPORT);
    484     }
    485 
    486     /** Remove a header given its name (provided it exists).
    487      * @param name name of the header to remove.
    488      */
    489     public void removeHeader(String name) {
    490         if (qheaders != null)
    491             qheaders.delete(name);
    492     }
    493 
    494     /** Remove all headers.
    495      */
    496     public void removeHeaders() {
    497         qheaders = new NameValueList();
    498     }
    499 
    500     /**
    501      * Set the user type.
    502      */
    503     public void removeUserType() {
    504         if (uriParms != null)
    505             uriParms.delete(USER);
    506     }
    507 
    508     /**
    509      *remove the port setting.
    510      */
    511     public void removePort() {
    512         authority.removePort();
    513     }
    514 
    515     /**
    516      * remove the Method.
    517      */
    518     public void removeMethod() {
    519         if (uriParms != null)
    520             uriParms.delete(METHOD);
    521     }
    522 
    523     /** Sets the user of SipURI. The identifier of a particular resource at
    524      * the host being addressed. The user and the user password including the
    525      * "at" sign make up the user-info.
    526      *
    527      * @param uname The new String value of the user.
    528      * @throws ParseException which signals that an error has been reached
    529      * unexpectedly while parsing the user value.
    530      */
    531     public void setUser(String uname) {
    532         if (this.authority == null) {
    533             this.authority = new Authority();
    534         }
    535 
    536         this.authority.setUser(uname);
    537     }
    538 
    539     /** Remove the user.
    540      */
    541     public void removeUser() {
    542         this.authority.removeUserInfo();
    543     }
    544 
    545     /** Set the default parameters for this URI.
    546      * Do nothing if the parameter is already set to some value.
    547      * Otherwise set it to the given value.
    548      * @param name Name of the parameter to set.
    549      * @param value value of the parameter to set.
    550      */
    551     public void setDefaultParm(String name, Object value) {
    552         if (uriParms.getValue(name) == null) {
    553             NameValue nv = new NameValue(name, value);
    554             uriParms.set(nv);
    555         }
    556     }
    557 
    558     /** Set the authority member
    559      * @param authority Authority to set.
    560      */
    561     public void setAuthority(Authority authority) {
    562         this.authority = authority;
    563     }
    564 
    565     /** Set the host for this URI.
    566      * @param h host to set.
    567      */
    568     public void setHost(Host h) {
    569         if (this.authority == null)
    570             this.authority = new Authority();
    571         this.authority.setHost(h);
    572     }
    573 
    574     /** Set the uriParms member
    575      * @param parms URI parameters to set.
    576      */
    577     public void setUriParms(NameValueList parms) {
    578         uriParms = parms;
    579     }
    580 
    581     /**
    582      * Set a given URI parameter. Note - parameter must be properly
    583     *  encoded before the function is called.
    584      * @param name Name of the parameter to set.
    585      * @param value value of the parameter to set.
    586      */
    587     public void setUriParm(String name, Object value) {
    588         NameValue nv = new NameValue(name, value);
    589         uriParms.set(nv);
    590     }
    591 
    592     /** Set the qheaders member
    593      * @param parms query headers to set.
    594      */
    595     public void setQheaders(NameValueList parms) {
    596         qheaders = parms;
    597     }
    598 
    599     /**
    600      * Set the MADDR parameter .
    601      * @param mAddr Host Name to set
    602      */
    603     public void setMAddr(String mAddr) {
    604         NameValue nameValue = uriParms.getNameValue(MADDR);
    605         Host host = new Host();
    606         host.setAddress(mAddr);
    607         if (nameValue != null)
    608             nameValue.setValueAsObject(host);
    609         else {
    610             nameValue = new NameValue(MADDR, host);
    611             uriParms.set(nameValue);
    612         }
    613     }
    614 
    615     /** Sets the value of the user parameter. The user URI parameter exists to
    616      * distinguish telephone numbers from user names that happen to look like
    617      * telephone numbers.  This is equivalent to setParameter("user", user).
    618      *
    619      * @param usertype New value String value of the method parameter
    620      */
    621     public void setUserParam(String usertype) {
    622         uriParms.set(USER, usertype);
    623     }
    624 
    625     /**
    626      * Set the Method
    627      * @param method method parameter
    628      */
    629     public void setMethod(String method) {
    630         uriParms.set(METHOD, method);
    631     }
    632 
    633     /**
    634     * Sets ISDN subaddress of SipURL
    635     * @param isdnSubAddress ISDN subaddress
    636     */
    637     public void setIsdnSubAddress(String isdnSubAddress) {
    638         if (telephoneSubscriber == null)
    639             telephoneSubscriber = new TelephoneNumber();
    640         telephoneSubscriber.setIsdnSubaddress(isdnSubAddress);
    641     }
    642 
    643     /**
    644      * Set the telephone subscriber field.
    645      * @param tel Telephone subscriber field to set.
    646      */
    647     public void setTelephoneSubscriber(TelephoneNumber tel) {
    648         telephoneSubscriber = tel;
    649     }
    650 
    651     /** set the port to a given value.
    652      * @param p Port to set.
    653      */
    654     public void setPort(int p) {
    655         if (authority == null)
    656             authority = new Authority();
    657         authority.setPort(p);
    658     }
    659 
    660     /**
    661      * Boolean to check if a parameter of a given name exists.
    662      * @param name Name of the parameter to check on.
    663      * @return a boolean indicating whether the parameter exists.
    664      */
    665     public boolean hasParameter(String name) {
    666 
    667         return uriParms.getValue(name) != null;
    668     }
    669 
    670     /**
    671      * Set the query header when provided as a name-value pair.
    672      * @param nameValue qeuery header provided as a name,value pair.
    673      */
    674     public void setQHeader(NameValue nameValue) {
    675         this.qheaders.set(nameValue);
    676     }
    677 
    678     /** Set the parameter as given.
    679      *@param nameValue - parameter to set.
    680      */
    681     public void setUriParameter(NameValue nameValue) {
    682         this.uriParms.set(nameValue);
    683     }
    684 
    685     /** Return true if the transport parameter is defined.
    686      * @return true if transport appears as a parameter and false otherwise.
    687      */
    688     public boolean hasTransport() {
    689         return hasParameter(TRANSPORT);
    690     }
    691 
    692     /**
    693      * Remove a parameter given its name
    694      * @param name -- name of the parameter to remove.
    695      */
    696     public void removeParameter(String name) {
    697         uriParms.delete(name);
    698     }
    699 
    700     /** Set the hostPort field of the imbedded authority field.
    701      *@param hostPort is the hostPort to set.
    702      */
    703     public void setHostPort(HostPort hostPort) {
    704         if (this.authority == null) {
    705             this.authority = new Authority();
    706         }
    707         authority.setHostPort(hostPort);
    708     }
    709 
    710     /** clone this.
    711      */
    712     public Object clone() {
    713         SipUri retval = (SipUri) super.clone();
    714         if (this.authority != null)
    715             retval.authority = (Authority) this.authority.clone();
    716         if (this.uriParms != null)
    717             retval.uriParms = (NameValueList) this.uriParms.clone();
    718         if (this.qheaders != null)
    719             retval.qheaders = (NameValueList) this.qheaders.clone();
    720         if (this.telephoneSubscriber != null)
    721             retval.telephoneSubscriber = (TelephoneNumber) this.telephoneSubscriber.clone();
    722         return retval;
    723     }
    724 
    725     /**
    726      * Returns the value of the named header, or null if it is not set.
    727      * SIP/SIPS URIs may specify headers. As an example, the URI
    728      * sip:joe (at) jcp.org?priority=urgent has a header "priority" whose
    729      * value is "urgent".
    730      *
    731      * @param name name of header to retrieve
    732      * @return the value of specified header
    733      */
    734     public String getHeader(String name) {
    735         return this.qheaders.getValue(name) != null
    736             ? this.qheaders.getValue(name).toString()
    737             : null;
    738 
    739     }
    740 
    741     /**
    742      * Returns an Iterator over the names (Strings) of all headers present
    743      * in this SipURI.
    744      *
    745      * @return an Iterator over all the header names
    746      */
    747     public Iterator<String> getHeaderNames() {
    748         return this.qheaders.getNames();
    749 
    750     }
    751 
    752     /** Returns the value of the <code>lr</code> parameter, or null if this
    753      * is not set. This is equivalent to getParameter("lr").
    754      *
    755      * @return the value of the <code>lr</code> parameter
    756      */
    757     public String getLrParam() {
    758         boolean haslr = this.hasParameter(LR);
    759         return haslr ? "true" : null;
    760     }
    761 
    762     /** Returns the value of the <code>maddr</code> parameter, or null if this
    763      * is not set. This is equivalent to getParameter("maddr").
    764      *
    765      * @return the value of the <code>maddr</code> parameter
    766      */
    767     public String getMAddrParam() {
    768         NameValue maddr = uriParms.getNameValue(MADDR);
    769         if (maddr == null)
    770             return null;
    771         String host = (String) maddr.getValueAsObject();
    772         return host;
    773     }
    774 
    775     /**
    776      * Returns the value of the <code>method</code> parameter, or null if this
    777      * is not set. This is equivalent to getParameter("method").
    778      *
    779      * @return  the value of the <code>method</code> parameter
    780      */
    781     public String getMethodParam() {
    782         return this.getParameter(METHOD);
    783     }
    784 
    785     /**
    786      * Returns the value of the named parameter, or null if it is not set. A
    787      * zero-length String indicates flag parameter.
    788      *
    789      * @param name name of parameter to retrieve
    790      * @return the value of specified parameter
    791      */
    792     public String getParameter(String name) {
    793         Object val = uriParms.getValue(name);
    794         if (val == null)
    795             return null;
    796         if (val instanceof GenericObject)
    797             return ((GenericObject) val).encode();
    798         else
    799             return val.toString();
    800     }
    801 
    802     /**
    803      * Returns an Iterator over the names (Strings) of all parameters present
    804      *
    805      * in this ParametersHeader.
    806      *
    807      *
    808      *
    809      * @return an Iterator over all the parameter names
    810      *
    811      */
    812     public Iterator<String> getParameterNames() {
    813         return this.uriParms.getNames();
    814     }
    815 
    816     /** Returns the value of the "ttl" parameter, or -1 if this is not set.
    817      * This method is equivalent to getParameter("ttl").
    818      *
    819      * @return the value of the <code>ttl</code> parameter
    820      */
    821     public int getTTLParam() {
    822         Integer ttl = (Integer) uriParms.getValue("ttl");
    823         if (ttl != null)
    824             return ttl.intValue();
    825         else
    826             return -1;
    827     }
    828 
    829     /** Returns the value of the "transport" parameter, or null if this is not
    830      * set. This is equivalent to getParameter("transport").
    831      *
    832      * @return the transport paramter of the SipURI
    833      */
    834     public String getTransportParam() {
    835         if (uriParms != null) {
    836             return (String) uriParms.getValue(TRANSPORT);
    837         } else
    838             return null;
    839     }
    840 
    841     /** Returns the value of the <code>userParam</code>,
    842      *or null if this is not set.
    843      * <p>
    844      * This is equivalent to getParameter("user").
    845      *
    846      * @return the value of the <code>userParam</code> of the SipURI
    847      */
    848     public String getUser() {
    849         return authority.getUser();
    850     }
    851 
    852     /** Returns true if this SipURI is secure i.e. if this SipURI represents a
    853      * sips URI. A sip URI returns false.
    854      *
    855      * @return  <code>true</code> if this SipURI represents a sips URI, and
    856      * <code>false</code> if it represents a sip URI.
    857      */
    858     public boolean isSecure() {
    859         return this.getScheme().equalsIgnoreCase(SIPS);
    860     }
    861 
    862     /** This method determines if this is a URI with a scheme of "sip" or "sips".
    863      *
    864      * @return true if the scheme is "sip" or "sips", false otherwise.
    865      */
    866     public boolean isSipURI() {
    867         return true;
    868     }
    869 
    870     /** Sets the value of the specified header fields to be included in a
    871      * request constructed from the URI. If the header already had a value it
    872      * will be overwritten.
    873      *
    874      * @param name - a String specifying the header name
    875      * @param value - a String specifying the header value
    876      */
    877     public void setHeader(String name, String value) {
    878         NameValue nv = new NameValue(name, value);
    879         qheaders.set(nv);
    880 
    881     }
    882 
    883     /**
    884      * Set the host portion of the SipURI
    885      *
    886      * @param host host to set.
    887      */
    888     public void setHost(String host) throws ParseException {
    889         Host h = new Host(host);
    890         this.setHost(h);
    891     }
    892 
    893     /** Sets the value of the <code>lr</code> parameter of this SipURI. The lr
    894      * parameter, when present, indicates that the element responsible for
    895      * this resource implements the routing mechanisms specified in RFC 3261.
    896      * This parameter will be used in the URIs proxies place in the
    897      * Record-Route header field values, and may appear in the URIs in a
    898      * pre-existing route set.
    899      */
    900     public void setLrParam() {
    901         this.uriParms.set("lr",null);   // JvB: fixed to not add duplicates
    902     }
    903 
    904     /**
    905      * Sets the value of the <code>maddr</code> parameter of this SipURI. The
    906      * maddr parameter indicates the server address to be contacted for this
    907      * user, overriding any address derived from the host field. This is
    908      * equivalent to setParameter("maddr", maddr).
    909      *
    910      * @param  maddr New value of the <code>maddr</code> parameter
    911      */
    912     public void setMAddrParam(String maddr) throws ParseException {
    913         if (maddr == null)
    914             throw new NullPointerException("bad maddr");
    915         setParameter("maddr", maddr);
    916     }
    917 
    918     /** Sets the value of the <code>method</code> parameter. This specifies
    919      * which SIP method to use in requests directed at this URI. This is
    920      * equivalent to setParameter("method", method).
    921      *
    922      * @param  method - new value String value of the method parameter
    923      */
    924     public void setMethodParam(String method) throws ParseException {
    925         setParameter("method", method);
    926     }
    927 
    928     /**
    929      * Sets the value of the specified parameter. If the parameter already had
    930      *
    931      * a value it will be overwritten. A zero-length String indicates flag
    932      *
    933      * parameter.
    934      *
    935      *
    936      *
    937      * @param name - a String specifying the parameter name
    938      *
    939      * @param value - a String specifying the parameter value
    940      *
    941      * @throws ParseException which signals that an error has been reached
    942      *
    943      * unexpectedly while parsing the parameter name or value.
    944      *
    945      */
    946     public void setParameter(String name, String value) throws ParseException {
    947         if (name.equalsIgnoreCase("ttl")) {
    948             try {
    949                 Integer.parseInt(value);
    950             } catch (NumberFormatException ex) {
    951                 throw new ParseException("bad parameter " + value, 0);
    952             }
    953         }
    954         uriParms.set(name,value);
    955     }
    956 
    957     /** Sets the scheme of this URI to sip or sips depending on whether the
    958      * argument is true or false. The default value is false.
    959      *
    960      * @param secure - the boolean value indicating if the SipURI is secure.
    961      */
    962     public void setSecure(boolean secure) {
    963         if (secure)
    964             this.scheme = SIPS;
    965         else
    966             this.scheme = SIP;
    967     }
    968 
    969     /** Sets the value of the <code>ttl</code> parameter. The ttl parameter
    970      * specifies the time-to-live value when packets are sent using UDP
    971      * multicast. This is equivalent to setParameter("ttl", ttl).
    972      *
    973      * @param ttl - new value of the <code>ttl</code> parameter
    974      */
    975     public void setTTLParam(int ttl) {
    976         if (ttl <= 0)
    977             throw new IllegalArgumentException("Bad ttl value");
    978         if (uriParms != null) {
    979             NameValue nv = new NameValue("ttl", Integer.valueOf(ttl));
    980             uriParms.set(nv);
    981         }
    982     }
    983 
    984     /** Sets the value of the "transport" parameter. This parameter specifies
    985      * which transport protocol to use for sending requests and responses to
    986      * this entity. The following values are defined: "udp", "tcp", "sctp",
    987      * "tls", but other values may be used also. This method is equivalent to
    988      * setParameter("transport", transport). Transport parameter constants
    989      * are defined in the {@link javax.sip.ListeningPoint}.
    990      *
    991      * @param transport - new value for the "transport" parameter
    992      * @see javax.sip.ListeningPoint
    993      */
    994     public void setTransportParam(String transport) throws ParseException {
    995         if (transport == null)
    996             throw new NullPointerException("null arg");
    997         if (transport.compareToIgnoreCase("UDP") == 0
    998             || transport.compareToIgnoreCase("TLS") == 0
    999             || transport.compareToIgnoreCase("TCP") == 0
   1000             || transport.compareToIgnoreCase("SCTP") == 0) {
   1001             NameValue nv = new NameValue(TRANSPORT, transport.toLowerCase());
   1002             uriParms.set(nv);
   1003         } else
   1004             throw new ParseException("bad transport " + transport, 0);
   1005     }
   1006 
   1007     /** Returns the user part of this SipURI, or null if it is not set.
   1008      *
   1009      * @return  the user part of this SipURI
   1010      */
   1011     public String getUserParam() {
   1012         return getParameter("user");
   1013 
   1014     }
   1015 
   1016     /** Returns whether the the <code>lr</code> parameter is set. This is
   1017      * equivalent to hasParameter("lr"). This interface has no getLrParam as
   1018      * RFC3261 does not specify any values for the "lr" paramater.
   1019      *
   1020      * @return true if the "lr" parameter is set, false otherwise.
   1021      */
   1022     public boolean hasLrParam() {
   1023         return uriParms.getNameValue("lr") != null;
   1024     }
   1025 
   1026 
   1027     /**
   1028      * Returns whether the <code>gr</code> parameter is set.
   1029      *
   1030      * Not part on the interface since gruu is not part of the base RFC3261.
   1031      */
   1032     public boolean hasGrParam() {
   1033         return uriParms.getNameValue(GRUU) != null;
   1034     }
   1035 
   1036     /**
   1037      * Sets the <code>gr</code> parameter.
   1038      *
   1039      * Not part on the interface since gruu is not part of the base RFC3261.
   1040      */
   1041     public void setGrParam(String value) {
   1042             this.uriParms.set(GRUU, value); // JvB: fixed to not add duplicates
   1043     }
   1044 
   1045     /**
   1046      * Sets the <code>gr</code> parameter.
   1047      *
   1048      * Not part on the interface since gruu is not part of the base RFC3261.
   1049      */
   1050     public String getGrParam() {
   1051             return (String) this.uriParms.getValue(GRUU);   // JvB: fixed to not add duplicates
   1052     }
   1053 
   1054     /**
   1055      *remove the +sip-instance value from the parameter list if it exists.
   1056      */
   1057 
   1058 }
   1059