1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Conditions Of Use 3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software was developed by employees of the National Institute of 5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Standards and Technology (NIST), an agency of the Federal Government. 6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Pursuant to title 15 Untied States Code Section 105, works of NIST 7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * employees are not subject to copyright protection in the United States 8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and are considered to be in the public domain. As a result, a formal 9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * license is not needed to use the software. 10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software is provided by NIST as a service and is expressly 12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED 13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF 14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT 15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * AND DATA ACCURACY. NIST does not warrant or make any representations 16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * regarding the use of the software or the results thereof, including but 17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * not limited to the correctness, accuracy, reliability or usefulness of 18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the software. 19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Permission to use this software is contingent upon your acceptance 21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * of the terms of this agreement 22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * . 24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/******************************************************************************* 27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Product of NIST/ITL Advanced Networking Technologies Division (ANTD) * 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ******************************************************************************/ 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.javax.sip.message; 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.InternalErrorHandler; 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.SIPConstants; 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.Utils; 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.AlertInfo; 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Authorization; 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.CSeq; 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.CallID; 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Contact; 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ContactList; 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ContentLength; 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ContentType; 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ErrorInfo; 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ErrorInfoList; 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.From; 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.InReplyTo; 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.MaxForwards; 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Priority; 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ProxyAuthenticate; 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ProxyAuthorization; 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ProxyRequire; 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ProxyRequireList; 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.RSeq; 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.RecordRouteList; 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.RetryAfter; 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Route; 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.RouteList; 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.SIPETag; 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.SIPHeader; 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.SIPHeaderList; 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.SIPHeaderNamesCache; 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.SIPIfMatch; 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Server; 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Subject; 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.To; 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Unsupported; 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.UserAgent; 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Via; 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ViaList; 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.WWWAuthenticate; 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Warning; 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.parser.HeaderParser; 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.parser.ParserFactory; 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.parser.PipelinedMsgParser; 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.parser.StringMsgParser; 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.UnsupportedEncodingException; 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.lang.reflect.Field; 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.text.ParseException; 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Collection; 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Hashtable; 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Iterator; 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.LinkedList; 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.List; 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.ListIterator; 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.concurrent.ConcurrentLinkedQueue; 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.InvalidArgumentException; 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.SipException; 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.AuthorizationHeader; 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.CSeqHeader; 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.CallIdHeader; 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ContactHeader; 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ContentDispositionHeader; 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ContentEncodingHeader; 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ContentLanguageHeader; 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ContentLengthHeader; 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ContentTypeHeader; 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ExpiresHeader; 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.FromHeader; 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.Header; 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.MaxForwardsHeader; 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.RecordRouteHeader; 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.RouteHeader; 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ToHeader; 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ViaHeader; 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.Request; 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Acknowledgements: Yanick Belanger sent in a patch for the right content length when the content 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is a String. Bill Mccormick from Nortel Networks sent in a bug fix for setContent. 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This is the main SIP Message structure. 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see StringMsgParser 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see PipelinedMsgParser 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 $Revision: 1.53 $ $Date: 2009/12/16 14:58:40 $ 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @since 1.1 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan <br/> 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic abstract class SIPMessage extends MessageObject implements javax.sip.message.Message, 127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang MessageExt { 128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: use static here? 130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private String contentEncodingCharset = MessageFactoryImpl.getDefaultContentEncodingCharset(); 131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * True if this is a null request. 134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected boolean nullRequest; 136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * unparsed headers 139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected LinkedList<String> unrecognizedHeaders; 141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * List of parsed headers (in the order they were added) 144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected ConcurrentLinkedQueue<SIPHeader> headers; 146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Direct accessors for frequently accessed headers 149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected From fromHeader; 151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected To toHeader; 153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected CSeq cSeqHeader; 155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected CallID callIdHeader; 157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected ContentLength contentLengthHeader; 159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected MaxForwards maxForwardsHeader; 161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Cumulative size of all the headers. 163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected int size; 164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Payload 166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private String messageContent; 167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private byte[] messageContentBytes; 169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private Object messageContentObject; 171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Table of headers indexed by name. 173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private Hashtable<String, SIPHeader> nameTable; 174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The application data pointer. This is un-interpreted by the stack. This is provided as a 177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * convenient way of keeping book-keeping data for applications. 178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected Object applicationData; 180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return true if the header belongs only in a Request. 183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipHeader is the header to test. 185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public static boolean isRequestHeader(SIPHeader sipHeader) { 187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return sipHeader instanceof AlertInfo || sipHeader instanceof InReplyTo 188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipHeader instanceof Authorization || sipHeader instanceof MaxForwards 189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipHeader instanceof UserAgent || sipHeader instanceof Priority 190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipHeader instanceof ProxyAuthorization || sipHeader instanceof ProxyRequire 191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipHeader instanceof ProxyRequireList || sipHeader instanceof Route 192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipHeader instanceof RouteList || sipHeader instanceof Subject 193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipHeader instanceof SIPIfMatch; 194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return true if the header belongs only in a response. 198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipHeader is the header to test. 200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public static boolean isResponseHeader(SIPHeader sipHeader) { 202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return sipHeader instanceof ErrorInfo || sipHeader instanceof ProxyAuthenticate 203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipHeader instanceof Server || sipHeader instanceof Unsupported 204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipHeader instanceof RetryAfter || sipHeader instanceof Warning 205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipHeader instanceof WWWAuthenticate || sipHeader instanceof SIPETag 206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipHeader instanceof RSeq; 207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the headers as a linked list of encoded Strings 212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a linked list with each element of the list containing a string encoded header in 214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * canonical form. 215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public LinkedList<String> getMessageAsEncodedStrings() { 217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang LinkedList<String> retval = new LinkedList<String>(); 218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator<SIPHeader> li = headers.iterator(); 219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (li.hasNext()) { 220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sipHeader = (SIPHeader) li.next(); 221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipHeader instanceof SIPHeaderList) { 222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeaderList< ? > shl = (SIPHeaderList< ? >) sipHeader; 223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.addAll(shl.getHeadersAsEncodedStrings()); 224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.add(sipHeader.encode()); 226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Encode only the message and exclude the contents (for debugging); 234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a string with all the headers encoded. 236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected String encodeSIPHeaders() { 238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringBuffer encoding = new StringBuffer(); 239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator<SIPHeader> it = this.headers.iterator(); 240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (it.hasNext()) { 242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader siphdr = (SIPHeader) it.next(); 243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!(siphdr instanceof ContentLength)) 244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang siphdr.encode(encoding); 245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return contentLengthHeader.encode(encoding).append(NEWLINE).toString(); 248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Encode all the headers except the contents. For debug logging. 252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract String encodeMessage(); 254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get A dialog identifier constructed from this messsage. This is an id that can be used to 257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * identify dialogs. 258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param isServerTransaction is a flag that indicates whether this is a server transaction. 260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract String getDialogId(boolean isServerTransaction); 262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Template match for SIP messages. The matchObj is a SIPMessage template to match against. 265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This method allows you to do pattern matching with incoming SIP messages. Null matches wild 266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * card. 267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param other is the match template to match against. 269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return true if a match occured and false otherwise. 270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean match(Object other) { 272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (other == null) 273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return true; 274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!other.getClass().equals(this.getClass())) 275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPMessage matchObj = (SIPMessage) other; 277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator<SIPHeader> li = matchObj.getHeaders(); 278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (li.hasNext()) { 279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader hisHeaders = (SIPHeader) li.next(); 280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang List<SIPHeader> myHeaders = this.getHeaderList(hisHeaders.getHeaderName()); 281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Could not find a header to match his header. 283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (myHeaders == null || myHeaders.size() == 0) 284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (hisHeaders instanceof SIPHeaderList) { 287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ListIterator< ? > outerIterator = ((SIPHeaderList< ? >) hisHeaders) 288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .listIterator(); 289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (outerIterator.hasNext()) { 290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader hisHeader = (SIPHeader) outerIterator.next(); 291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (hisHeader instanceof ContentLength) 292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang continue; 293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ListIterator< ? > innerIterator = myHeaders.listIterator(); 294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean found = false; 295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (innerIterator.hasNext()) { 296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader myHeader = (SIPHeader) innerIterator.next(); 297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (myHeader.match(hisHeader)) { 298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang found = true; 299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!found) 303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader hisHeader = hisHeaders; 307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ListIterator<SIPHeader> innerIterator = myHeaders.listIterator(); 308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean found = false; 309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (innerIterator.hasNext()) { 310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader myHeader = (SIPHeader) innerIterator.next(); 311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (myHeader.match(hisHeader)) { 312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang found = true; 313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!found) 317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return true; 321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Merge a request with a template 326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param template -- template to merge with. 328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void merge(Object template) { 331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!template.getClass().equals(this.getClass())) 332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IllegalArgumentException("Bad class " + template.getClass()); 333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPMessage templateMessage = (SIPMessage) template; 334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Object[] templateHeaders = templateMessage.headers.toArray(); 335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (int i = 0; i < templateHeaders.length; i++) { 336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader hdr = (SIPHeader) templateHeaders[i]; 337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String hdrName = hdr.getHeaderName(); 338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang List<SIPHeader> myHdrs = this.getHeaderList(hdrName); 339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (myHdrs == null) { 340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.attachHeader(hdr); 341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ListIterator<SIPHeader> it = myHdrs.listIterator(); 343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (it.hasNext()) { 344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sipHdr = (SIPHeader) it.next(); 345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipHdr.merge(hdr); 346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Encode this message as a string. This is more efficient when the payload is a string 354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (rather than a binary array of bytes). If the payload cannot be encoded as a UTF-8 string 355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * then it is simply ignored (will not appear in the encoded message). 356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return The Canonical String representation of the message (including the canonical string 358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * representation of the SDP payload if it exists). 359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String encode() { 361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringBuffer encoding = new StringBuffer(); 362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator<SIPHeader> it = this.headers.iterator(); 363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (it.hasNext()) { 365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader siphdr = (SIPHeader) it.next(); 366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!(siphdr instanceof ContentLength)) 367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang encoding.append(siphdr.encode()); 368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Append the unrecognized headers. Headers that are not 370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // recognized are passed through unchanged. 371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (String unrecognized : this.unrecognizedHeaders) { 372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang encoding.append(unrecognized).append(NEWLINE); 373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang encoding.append(contentLengthHeader.encode()).append(NEWLINE); 376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.messageContentObject != null) { 378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String mbody = this.getContent().toString(); 379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang encoding.append(mbody); 381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (this.messageContent != null || this.messageContentBytes != null) { 382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String content = null; 384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (messageContent != null) 386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang content = messageContent; 387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else { 388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: Check for 'charset' parameter which overrides the default UTF-8 389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang content = new String(messageContentBytes, getCharset() ); 390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (UnsupportedEncodingException ex) { 392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang encoding.append(content); 396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return encoding.toString(); 398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Encode the message as a byte array. Use this when the message payload is a binary byte 402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * array. 403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return The Canonical byte array representation of the message (including the canonical 405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * byte array representation of the SDP payload if it exists all in one contiguous 406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * byte array). 407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public byte[] encodeAsBytes(String transport) { 409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this instanceof SIPRequest && ((SIPRequest) this).isNullRequest()) { 410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return "\r\n\r\n".getBytes(); 411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: added to fix case where application provides the wrong transport 413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // in the topmost Via header 414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ViaHeader topVia = (ViaHeader) this.getHeader(ViaHeader.NAME); 415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang topVia.setTransport(transport); 417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException e) { 418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(e); 419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringBuffer encoding = new StringBuffer(); 422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang synchronized (this.headers) { 423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator<SIPHeader> it = this.headers.iterator(); 424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (it.hasNext()) { 426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader siphdr = (SIPHeader) it.next(); 427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!(siphdr instanceof ContentLength)) 428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang siphdr.encode(encoding); 429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang contentLengthHeader.encode(encoding); 433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang encoding.append(NEWLINE); 434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] retval = null; 436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] content = this.getRawContent(); 437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (content != null) { 438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Append the content 439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] msgarray = null; 441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang msgarray = encoding.toString().getBytes( getCharset() ); 443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (UnsupportedEncodingException ex) { 444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval = new byte[msgarray.length + content.length]; 448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang System.arraycopy(msgarray, 0, retval, 0, msgarray.length); 449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang System.arraycopy(content, 0, retval, msgarray.length, content.length); 450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Message content does not exist. 452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval = encoding.toString().getBytes( getCharset() ); 455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (UnsupportedEncodingException ex) { 456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * clone this message (create a new deep physical copy). All headers in the message are 464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * cloned. You can modify the cloned copy without affecting the original. The content is 465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * handled as follows: If the content is a String, or a byte array, a new copy of the content 466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is allocated and copied over. If the content is an Object that supports the clone method, 467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * then the clone method is invoked and the cloned content is the new content. Otherwise, the 468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * content of the new message is set equal to the old one. 469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return A cloned copy of this object. 471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Object clone() { 473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPMessage retval = (SIPMessage) super.clone(); 474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.nameTable = new Hashtable<String, SIPHeader>(); 475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.fromHeader = null; 476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.toHeader = null; 477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.cSeqHeader = null; 478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.callIdHeader = null; 479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.contentLengthHeader = null; 480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.maxForwardsHeader = null; 481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.headers != null) { 482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.headers = new ConcurrentLinkedQueue<SIPHeader>(); 483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (Iterator<SIPHeader> iter = headers.iterator(); iter.hasNext();) { 484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader hdr = (SIPHeader) iter.next(); 485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.attachHeader((SIPHeader) hdr.clone()); 486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.messageContentBytes != null) 490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.messageContentBytes = (byte[]) this.messageContentBytes.clone(); 491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.messageContentObject != null) 492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.messageContentObject = makeClone(messageContentObject); 493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.unrecognizedHeaders = this.unrecognizedHeaders; 494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the string representation of this header (for pretty printing the generated structure). 499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return Formatted string representation of the object. Note that this is NOT the same as 501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * encode(). This is used mainly for debugging purposes. 502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String debugDump() { 504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang stringRepresentation = ""; 505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint("SIPMessage:"); 506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint("{"); 507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Field[] fields = this.getClass().getDeclaredFields(); 510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (int i = 0; i < fields.length; i++) { 511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Field f = fields[i]; 512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Class< ? > fieldType = f.getType(); 513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String fieldName = f.getName(); 514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (f.get(this) != null && SIPHeader.class.isAssignableFrom(fieldType) 515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && fieldName.compareTo("headers") != 0) { 516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint(fieldName + "="); 517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint(((SIPHeader) f.get(this)).debugDump()); 518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint("List of headers : "); 525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint(headers.toString()); 526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint("messageContent = "); 527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint("{"); 528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint(messageContent); 529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint("}"); 530600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.getContent() != null) { 531600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint(this.getContent().toString()); 532600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 533600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint("}"); 534600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return stringRepresentation; 535600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 536600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 537600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 538600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Constructor: Initializes lists and list headers. All the headers for which there can be 539600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * multiple occurances in a message are derived from the SIPHeaderListClass. All singleton 540600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * headers are derived from SIPHeader class. 541600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 542600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPMessage() { 543600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.unrecognizedHeaders = new LinkedList<String>(); 544600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.headers = new ConcurrentLinkedQueue<SIPHeader>(); 545600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nameTable = new Hashtable<String, SIPHeader>(); 546600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 547600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.attachHeader(new ContentLength(0), false); 548600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 549600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 550600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 551600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 552600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 553600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Attach a header and die if you get a duplicate header exception. 554600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 555600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param h SIPHeader to attach. 556600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 557600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private void attachHeader(SIPHeader h) { 558600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (h == null) 559600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IllegalArgumentException("null header!"); 560600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 561600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (h instanceof SIPHeaderList) { 562600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeaderList< ? > hl = (SIPHeaderList< ? >) h; 563600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (hl.isEmpty()) { 564600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 565600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 566600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 567600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang attachHeader(h, false, false); 568600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SIPDuplicateHeaderException ex) { 569600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // InternalErrorHandler.handleException(ex); 570600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 571600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 572600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 573600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 574600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Attach a header (replacing the original header). 575600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 576600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipHeader SIPHeader that replaces a header of the same type. 577600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 578600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setHeader(Header sipHeader) { 579600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader header = (SIPHeader) sipHeader; 580600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (header == null) 581600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IllegalArgumentException("null header!"); 582600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 583600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (header instanceof SIPHeaderList) { 584600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeaderList< ? > hl = (SIPHeaderList< ? >) header; 585600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Ignore empty lists. 586600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (hl.isEmpty()) 587600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 588600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 589600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.removeHeader(header.getHeaderName()); 590600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang attachHeader(header, true, false); 591600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SIPDuplicateHeaderException ex) { 592600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 593600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 594600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 595600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 596600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 597600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set a header from a linked list of headers. 598600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 599600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param headers -- a list of headers to set. 600600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 601600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setHeaders(java.util.List<SIPHeader> headers) { 602600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ListIterator<SIPHeader> listIterator = headers.listIterator(); 603600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (listIterator.hasNext()) { 604600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sipHeader = (SIPHeader) listIterator.next(); 605600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 606600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.attachHeader(sipHeader, false); 607600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SIPDuplicateHeaderException ex) { 608600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 609600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 610600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 611600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 612600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 613600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Attach a header to the end of the existing headers in this SIPMessage structure. This is 614600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * equivalent to the attachHeader(SIPHeader,replaceflag,false); which is the normal way in 615600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * which headers are attached. This was added in support of JAIN-SIP. 616600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 617600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param h header to attach. 618600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param replaceflag if true then replace a header if it exists. 619600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws SIPDuplicateHeaderException If replaceFlag is false and only a singleton header is 620600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * allowed (fpr example CSeq). 621600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 622600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void attachHeader(SIPHeader h, boolean replaceflag) throws SIPDuplicateHeaderException { 623600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.attachHeader(h, replaceflag, false); 624600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 625600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 626600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 627600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Attach the header to the SIP Message structure at a specified position in its list of 628600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * headers. 629600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 630600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param header Header to attach. 631600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param replaceFlag If true then replace the existing header. 632600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param top Location in the header list to insert the header. 633600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception SIPDuplicateHeaderException if the header is of a type that cannot tolerate 634600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * duplicates and one of this type already exists (e.g. CSeq header). 635600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws IndexOutOfBoundsException If the index specified is greater than the number of 636600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * headers that are in this message. 637600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 638600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 639600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void attachHeader(SIPHeader header, boolean replaceFlag, boolean top) 640600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throws SIPDuplicateHeaderException { 641600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (header == null) { 642600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new NullPointerException("null header"); 643600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 644600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 645600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader h; 646600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 647600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (ListMap.hasList(header) && !SIPHeaderList.class.isAssignableFrom(header.getClass())) { 648600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeaderList<SIPHeader> hdrList = ListMap.getList(header); 649600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hdrList.add(header); 650600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang h = hdrList; 651600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 652600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang h = header; 653600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 654600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 655600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String headerNameLowerCase = SIPHeaderNamesCache.toLowerCase(h.getName()); 656600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (replaceFlag) { 657600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nameTable.remove(headerNameLowerCase); 658600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (nameTable.containsKey(headerNameLowerCase) && !(h instanceof SIPHeaderList)) { 659600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (h instanceof ContentLength) { 660600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 661600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContentLength cl = (ContentLength) h; 662600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang contentLengthHeader.setContentLength(cl.getContentLength()); 663600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (InvalidArgumentException e) { 664600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 665600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 666600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Just ignore duplicate header. 667600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 668600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 669600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 670600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader originalHeader = (SIPHeader) getHeader(header.getName()); 671600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 672600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Delete the original header from our list structure. 673600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (originalHeader != null) { 674600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator<SIPHeader> li = headers.iterator(); 675600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (li.hasNext()) { 676600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader next = (SIPHeader) li.next(); 677600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (next.equals(originalHeader)) { 678600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang li.remove(); 679600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 680600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 681600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 682600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 683600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!nameTable.containsKey(headerNameLowerCase)) { 684600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nameTable.put(headerNameLowerCase, h); 685600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang headers.add(h); 686600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 687600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (h instanceof SIPHeaderList) { 688600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeaderList< ? > hdrlist = (SIPHeaderList< ? >) nameTable 689600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .get(headerNameLowerCase); 690600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (hdrlist != null) 691600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hdrlist.concatenate((SIPHeaderList) h, top); 692600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 693600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nameTable.put(headerNameLowerCase, h); 694600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 695600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nameTable.put(headerNameLowerCase, h); 696600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 697600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 698600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 699600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Direct accessor fields for frequently accessed headers. 700600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (h instanceof From) { 701600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.fromHeader = (From) h; 702600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (h instanceof ContentLength) { 703600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.contentLengthHeader = (ContentLength) h; 704600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (h instanceof To) { 705600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.toHeader = (To) h; 706600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (h instanceof CSeq) { 707600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.cSeqHeader = (CSeq) h; 708600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (h instanceof CallID) { 709600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.callIdHeader = (CallID) h; 710600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (h instanceof MaxForwards) { 711600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.maxForwardsHeader = (MaxForwards) h; 712600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 713600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 714600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 715600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 716600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 717600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Remove a header given its name. If multiple headers of a given name are present then the 718600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * top flag determines which end to remove headers from. 719600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 720600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param headerName is the name of the header to remove. 721600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param top -- flag that indicates which end of header list to process. 722600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 723600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void removeHeader(String headerName, boolean top) { 724600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 725600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String headerNameLowerCase = SIPHeaderNamesCache.toLowerCase(headerName); 726600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader toRemove = (SIPHeader) nameTable.get(headerNameLowerCase); 727600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // nothing to do then we are done. 728600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (toRemove == null) 729600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 730600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (toRemove instanceof SIPHeaderList) { 731600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeaderList< ? > hdrList = (SIPHeaderList< ? >) toRemove; 732600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (top) 733600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hdrList.removeFirst(); 734600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 735600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hdrList.removeLast(); 736600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Clean up empty list 737600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (hdrList.isEmpty()) { 738600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator<SIPHeader> li = this.headers.iterator(); 739600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (li.hasNext()) { 740600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sipHeader = (SIPHeader) li.next(); 741600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipHeader.getName().equalsIgnoreCase(headerNameLowerCase)) 742600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang li.remove(); 743600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 744600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 745600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: also remove it from the nameTable! Else NPE in 746600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // DefaultRouter 747600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nameTable.remove(headerNameLowerCase); 748600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 749600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 750600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.nameTable.remove(headerNameLowerCase); 751600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (toRemove instanceof From) { 752600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.fromHeader = null; 753600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (toRemove instanceof To) { 754600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.toHeader = null; 755600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (toRemove instanceof CSeq) { 756600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.cSeqHeader = null; 757600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (toRemove instanceof CallID) { 758600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.callIdHeader = null; 759600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (toRemove instanceof MaxForwards) { 760600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.maxForwardsHeader = null; 761600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (toRemove instanceof ContentLength) { 762600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.contentLengthHeader = null; 763600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 764600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator<SIPHeader> li = this.headers.iterator(); 765600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (li.hasNext()) { 766600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sipHeader = (SIPHeader) li.next(); 767600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipHeader.getName().equalsIgnoreCase(headerName)) 768600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang li.remove(); 769600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 770600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 771600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 772600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 773600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 774600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 775600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Remove all headers given its name. 776600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 777600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param headerName is the name of the header to remove. 778600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 779600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void removeHeader(String headerName) { 780600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 781600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (headerName == null) 782600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new NullPointerException("null arg"); 783600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String headerNameLowerCase = SIPHeaderNamesCache.toLowerCase(headerName); 784600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader removed = (SIPHeader) nameTable.remove(headerNameLowerCase); 785600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // nothing to do then we are done. 786600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (removed == null) 787600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 788600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 789600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Remove the fast accessor fields. 790600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (removed instanceof From) { 791600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.fromHeader = null; 792600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (removed instanceof To) { 793600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.toHeader = null; 794600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (removed instanceof CSeq) { 795600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.cSeqHeader = null; 796600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (removed instanceof CallID) { 797600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.callIdHeader = null; 798600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (removed instanceof MaxForwards) { 799600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.maxForwardsHeader = null; 800600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (removed instanceof ContentLength) { 801600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.contentLengthHeader = null; 802600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 803600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 804600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator<SIPHeader> li = this.headers.iterator(); 805600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (li.hasNext()) { 806600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sipHeader = (SIPHeader) li.next(); 807600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipHeader.getName().equalsIgnoreCase(headerNameLowerCase)) 808600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang li.remove(); 809600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 810600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 811600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 812600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 813600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 814600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Generate (compute) a transaction ID for this SIP message. 815600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 816600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return A string containing the concatenation of various portions of the From,To,Via and 817600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * RequestURI portions of this message as specified in RFC 2543: All responses to a 818600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * request contain the same values in the Call-ID, CSeq, To, and From fields (with the 819600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * possible addition of a tag in the To field (section 10.43)). This allows responses 820600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to be matched with requests. Incorporates a bug fix for a bug sent in by Gordon 821600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Ledgard of IPera for generating transactionIDs when no port is present in the via 822600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * header. Incorporates a bug fix for a bug report sent in by Chris Mills of Nortel 823600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Networks (converts to lower case when returning the transaction identifier). 824600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 825600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a string that can be used as a transaction identifier for this message. This can be 826600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * used for matching responses and requests (i.e. an outgoing request and its matching 827600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * response have the same computed transaction identifier). 828600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 829600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getTransactionId() { 830600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Via topVia = null; 831600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!this.getViaHeaders().isEmpty()) { 832600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang topVia = (Via) this.getViaHeaders().getFirst(); 833600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 834600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Have specified a branch Identifier so we can use it to identify 835600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // the transaction. BranchId is not case sensitive. 836600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Branch Id prefix is not case sensitive. 837600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (topVia != null 838600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && topVia.getBranch() != null 839600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && topVia.getBranch().toUpperCase().startsWith( 840600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPConstants.BRANCH_MAGIC_COOKIE_UPPER_CASE)) { 841600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Bis 09 compatible branch assignment algorithm. 842600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // implies that the branch id can be used as a transaction 843600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // identifier. 844600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.getCSeq().getMethod().equals(Request.CANCEL)) 845600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (topVia.getBranch() + ":" + this.getCSeq().getMethod()).toLowerCase(); 846600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 847600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return topVia.getBranch().toLowerCase(); 848600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 849600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Old style client so construct the transaction identifier 850600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // from various fields of the request. 851600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringBuffer retval = new StringBuffer(); 852600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang From from = (From) this.getFrom(); 853600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang To to = (To) this.getTo(); 854600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // String hpFrom = from.getUserAtHostPort(); 855600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // retval.append(hpFrom).append(":"); 856600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (from.hasTag()) 857600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(from.getTag()).append("-"); 858600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // String hpTo = to.getUserAtHostPort(); 859600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // retval.append(hpTo).append(":"); 860600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String cid = this.callIdHeader.getCallId(); 861600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(cid).append("-"); 862600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(this.cSeqHeader.getSequenceNumber()).append("-").append( 863600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.cSeqHeader.getMethod()); 864600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (topVia != null) { 865600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append("-").append(topVia.getSentBy().encode()); 866600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!topVia.getSentBy().hasPort()) { 867600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append("-").append(5060); 868600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 869600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 870600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.getCSeq().getMethod().equals(Request.CANCEL)) { 871600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(Request.CANCEL); 872600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 873600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval.toString().toLowerCase().replace(":", "-").replace("@", "-") 874600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + Utils.getSignature(); 875600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 876600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 877600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 878600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 879600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Override the hashcode method ( see issue # 55 ) Note that if you try to use this method 880600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * before you assemble a valid request, you will get a constant ( -1 ). Beware of placing any 881600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * half formed requests in a table. 882600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 883600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int hashCode() { 884600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.callIdHeader == null) 885600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new RuntimeException( 886600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Invalid message! Cannot compute hashcode! call-id header is missing !"); 887600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 888600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.callIdHeader.getCallId().hashCode(); 889600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 890600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 891600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 892600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return true if this message has a body. 893600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 894600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean hasContent() { 895600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return messageContent != null || messageContentBytes != null; 896600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 897600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 898600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 899600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return an iterator for the list of headers in this message. 900600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 901600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return an Iterator for the headers of this message. 902600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 903600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Iterator<SIPHeader> getHeaders() { 904600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return headers.iterator(); 905600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 906600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 907600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 908600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the first header of the given name. 909600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 910600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return header -- the first header of the given name. 911600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 912600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Header getHeader(String headerName) { 913600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return getHeaderLowerCase(SIPHeaderNamesCache.toLowerCase(headerName)); 914600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 915600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 916600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private Header getHeaderLowerCase(String lowerCaseHeaderName) { 917600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (lowerCaseHeaderName == null) 918600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new NullPointerException("bad name"); 919600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sipHeader = (SIPHeader) nameTable.get(lowerCaseHeaderName); 920600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipHeader instanceof SIPHeaderList) 921600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (Header) ((SIPHeaderList) sipHeader).getFirst(); 922600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 923600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (Header) sipHeader; 924600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 925600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 926600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 927600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the contentType header (null if one does not exist). 928600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 929600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return contentType header 930600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 931600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 932600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ContentType getContentTypeHeader() { 933600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (ContentType) getHeaderLowerCase(CONTENT_TYPE_LOWERCASE); 934600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 935600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 936600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String CONTENT_TYPE_LOWERCASE = SIPHeaderNamesCache 937600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(ContentTypeHeader.NAME); 938600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 939600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 940600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 941600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the contentLength header. 942600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 943600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ContentLengthHeader getContentLengthHeader() { 944600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.getContentLength(); 945600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 946600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 947600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 948600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 949600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the from header. 950600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 951600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return -- the from header. 952600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 953600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public FromHeader getFrom() { 954600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (FromHeader) fromHeader; 955600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 956600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 957600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 958600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the ErrorInfo list of headers (null if one does not exist). 959600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 960600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return List containing ErrorInfo headers. 961600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 962600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ErrorInfoList getErrorInfoHeaders() { 963600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (ErrorInfoList) getSIPHeaderListLowerCase(ERROR_LOWERCASE); 964600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 965600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 966600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String ERROR_LOWERCASE = SIPHeaderNamesCache.toLowerCase(ErrorInfo.NAME); 967600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 968600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 969600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the Contact list of headers (null if one does not exist). 970600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 971600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return List containing Contact headers. 972600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 973600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ContactList getContactHeaders() { 974600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (ContactList) this.getSIPHeaderListLowerCase(CONTACT_LOWERCASE); 975600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 976600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 977600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String CONTACT_LOWERCASE = SIPHeaderNamesCache 978600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(ContactHeader.NAME); 979600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 980600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 981600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the contact header ( the first contact header) which is all we need for the most part. 982600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 983600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 984600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Contact getContactHeader() { 985600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContactList clist = this.getContactHeaders(); 986600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (clist != null) { 987600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (Contact) clist.getFirst(); 988600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 989600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 990600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 991600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 992600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 993600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 994600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 995600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the Via list of headers (null if one does not exist). 996600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 997600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return List containing Via headers. 998600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 999600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ViaList getViaHeaders() { 1000600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (ViaList) getSIPHeaderListLowerCase(VIA_LOWERCASE); 1001600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1002600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1003600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String VIA_LOWERCASE = SIPHeaderNamesCache.toLowerCase(ViaHeader.NAME); 1004600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1005600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1006600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set A list of via headers. 1007600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1008600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param viaList a list of via headers to add. 1009600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1010600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setVia(java.util.List viaList) { 1011600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ViaList vList = new ViaList(); 1012600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ListIterator it = viaList.listIterator(); 1013600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (it.hasNext()) { 1014600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Via via = (Via) it.next(); 1015600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang vList.add(via); 1016600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1017600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(vList); 1018600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1019600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1020600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1021600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the header given a list of headers. 1022600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1023600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipHeaderList a headerList to set 1024600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1025600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1026600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setHeader(SIPHeaderList<Via> sipHeaderList) { 1027600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader((Header) sipHeaderList); 1028600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1029600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1030600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1031600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the topmost via header. 1032600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1033600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the top most via header if one exists or null if none exists. 1034600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1035600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Via getTopmostVia() { 1036600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.getViaHeaders() == null) 1037600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 1038600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 1039600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (Via) (getViaHeaders().getFirst()); 1040600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1041600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1042600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1043600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the CSeq list of header (null if one does not exist). 1044600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1045600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return CSeq header 1046600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1047600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public CSeqHeader getCSeq() { 1048600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (CSeqHeader) cSeqHeader; 1049600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1050600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1051600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1052600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the Authorization header (null if one does not exist). 1053600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1054600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return Authorization header. 1055600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1056600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Authorization getAuthorization() { 1057600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (Authorization) getHeaderLowerCase(AUTHORIZATION_LOWERCASE); 1058600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1059600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1060600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String AUTHORIZATION_LOWERCASE = SIPHeaderNamesCache 1061600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(AuthorizationHeader.NAME); 1062600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1063600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1064600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the MaxForwards header (null if one does not exist). 1065600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1066600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return Max-Forwards header 1067600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1068600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1069600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public MaxForwardsHeader getMaxForwards() { 1070600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return maxForwardsHeader; 1071600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1072600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1073600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1074600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the max forwards header. 1075600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1076600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param maxForwards is the MaxForwardsHeader to set. 1077600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1078600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setMaxForwards(MaxForwardsHeader maxForwards) { 1079600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(maxForwards); 1080600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1081600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1082600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1083600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the Route List of headers (null if one does not exist). 1084600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1085600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return List containing Route headers 1086600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1087600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public RouteList getRouteHeaders() { 1088600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (RouteList) getSIPHeaderListLowerCase(ROUTE_LOWERCASE); 1089600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1090600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1091600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String ROUTE_LOWERCASE = SIPHeaderNamesCache 1092600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(RouteHeader.NAME); 1093600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1094600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1095600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the CallID header (null if one does not exist) 1096600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1097600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return Call-ID header . 1098600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1099600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public CallIdHeader getCallId() { 1100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return callIdHeader; 1101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the call id header. 1105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param callId call idHeader (what else could it be?) 1107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setCallId(CallIdHeader callId) { 1109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(callId); 1110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the CallID header (null if one does not exist) 1114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param callId -- the call identifier to be assigned to the call id header 1116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setCallId(String callId) throws java.text.ParseException { 1118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (callIdHeader == null) { 1119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(new CallID()); 1120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang callIdHeader.setCallId(callId); 1122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the RecordRoute header list (null if one does not exist). 1126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return Record-Route header 1128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public RecordRouteList getRecordRouteHeaders() { 1130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (RecordRouteList) this.getSIPHeaderListLowerCase(RECORDROUTE_LOWERCASE); 1131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String RECORDROUTE_LOWERCASE = SIPHeaderNamesCache 1134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(RecordRouteHeader.NAME); 1135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the To header (null if one does not exist). 1138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return To header 1140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ToHeader getTo() { 1142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (ToHeader) toHeader; 1143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setTo(ToHeader to) { 1146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(to); 1147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setFrom(FromHeader from) { 1150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(from); 1151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the ContentLength header (null if one does not exist). 1156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return content-length header. 1158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ContentLengthHeader getContentLength() { 1160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.contentLengthHeader; 1161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the message body as a string. If the message contains a content type header with a 1165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * specified charset, and if the payload has been read as a byte array, then it is returned 1166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * encoded into this charset. 1167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return Message body (as a string) 1169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws UnsupportedEncodingException if the platform does not support the charset specified 1170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * in the content type header. 1171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getMessageContent() throws UnsupportedEncodingException { 1174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.messageContent == null && this.messageContentBytes == null) 1175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 1176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else if (this.messageContent == null) { 1177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageContent = new String(messageContentBytes, getCharset() ); 1178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.messageContent; 1180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the message content as an array of bytes. If the payload has been read as a String then 1184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * it is decoded using the charset specified in the content type header if it exists. 1185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Otherwise, it is encoded using the default encoding which is UTF-8. 1186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return an array of bytes that is the message payload. 1188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public byte[] getRawContent() { 1190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ( this.messageContentBytes != null ) { 1192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // return messageContentBytes; 1193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (this.messageContentObject != null) { 1194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String messageContent = this.messageContentObject.toString(); 1195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageContentBytes = messageContent.getBytes( getCharset() ); 1196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (this.messageContent != null) { 1197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageContentBytes = messageContent.getBytes( getCharset() ); 1198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.messageContentBytes; 1200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (UnsupportedEncodingException ex) { 1201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 1202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 1203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the message content given type and subtype. 1208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param type is the message type (eg. application) 1210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param subType is the message sybtype (eg. sdp) 1211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param messageContent is the messge content as a string. 1212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setMessageContent(String type, String subType, String messageContent) { 1214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (messageContent == null) 1215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IllegalArgumentException("messgeContent is null"); 1216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContentType ct = new ContentType(type, subType); 1217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(ct); 1218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageContent = messageContent; 1219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageContentBytes = null; 1220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageContentObject = null; 1221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Could be double byte so we need to compute length 1222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // after converting to byte[] 1223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang computeContentLength(messageContent); 1224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the message content after converting the given object to a String. 1228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param content -- content to set. 1230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param contentTypeHeader -- content type header corresponding to content. 1231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setContent(Object content, ContentTypeHeader contentTypeHeader) 1233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throws ParseException { 1234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (content == null) 1235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new NullPointerException("null content"); 1236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(contentTypeHeader); 1237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageContent = null; 1239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageContentBytes = null; 1240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageContentObject = null; 1241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (content instanceof String) { 1243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageContent = (String) content; 1244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (content instanceof byte[]) { 1245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageContentBytes = (byte[]) content; 1246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else 1247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageContentObject = content; 1248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang computeContentLength(content); 1250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the content (body) of the message. 1254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the content of the sip message. 1256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Object getContent() { 1258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.messageContentObject != null) 1259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return messageContentObject; 1260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else if (this.messageContent != null) 1261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.messageContent; 1262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else if (this.messageContentBytes != null) 1263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.messageContentBytes; 1264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 1265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 1266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the message content for a given type and subtype. 1270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param type is the messge type. 1272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param subType is the message subType. 1273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param messageContent is the message content as a byte array. 1274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setMessageContent(String type, String subType, byte[] messageContent) { 1276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContentType ct = new ContentType(type, subType); 1277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(ct); 1278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setMessageContent(messageContent); 1279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang computeContentLength(messageContent); 1281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the message content for this message. 1285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param content Message body as a string. 1287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setMessageContent(String content, boolean strict, boolean computeContentLength, int givenLength) 1289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throws ParseException { 1290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Note that that this could be a double byte character 1291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // set - bug report by Masafumi Watanabe 1292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang computeContentLength(content); 1293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ((!computeContentLength)) { 1294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ( (!strict && this.contentLengthHeader.getContentLength() != givenLength) 1295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || this.contentLengthHeader.getContentLength() < givenLength) { 1296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("Invalid content length " 1297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + this.contentLengthHeader.getContentLength() + " / " + givenLength, 0); 1298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang messageContent = content; 1302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang messageContentBytes = null; 1303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang messageContentObject = null; 1304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the message content as an array of bytes. 1308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param content is the content of the message as an array of bytes. 1310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setMessageContent(byte[] content) { 1312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang computeContentLength(content); 1313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang messageContentBytes = content; 1315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang messageContent = null; 1316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang messageContentObject = null; 1317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Method to set the content - called by the parser 1321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param content 1323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws ParseException 1324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setMessageContent(byte[] content, boolean computeContentLength, int givenLength) 1326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throws ParseException { 1327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang computeContentLength(content); 1328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ((!computeContentLength) && this.contentLengthHeader.getContentLength() < givenLength) { 1329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // System.out.println("!!!!!!!!!!! MISMATCH !!!!!!!!!!!"); 1330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("Invalid content length " 1331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + this.contentLengthHeader.getContentLength() + " / " + givenLength, 0); 1332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang messageContentBytes = content; 1334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang messageContent = null; 1335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang messageContentObject = null; 1336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Compute and set the Content-length header based on the given content object. 1340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param content is the content, as String, array of bytes, or other object. 1342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private void computeContentLength(Object content) { 1344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int length = 0; 1345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (content != null) { 1346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (content instanceof String) { 1347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang length = ((String) content).getBytes( getCharset() ).length; 1349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (UnsupportedEncodingException ex) { 1350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 1351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (content instanceof byte[]) { 1353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang length = ((byte[]) content).length; 1354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang length = content.toString().length(); 1356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang contentLengthHeader.setContentLength(length); 1361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (InvalidArgumentException e) { 1362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Cannot happen. 1363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Remove the message content if it exists. 1368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void removeContent() { 1370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang messageContent = null; 1371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang messageContentBytes = null; 1372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang messageContentObject = null; 1373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.contentLengthHeader.setContentLength(0); 1375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (InvalidArgumentException ex) { 1376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get a SIP header or Header list given its name. 1381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param headerName is the name of the header to get. 1383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a header or header list that contians the retrieved header. 1384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang @SuppressWarnings("unchecked") 1386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ListIterator<SIPHeader> getHeaders(String headerName) { 1387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (headerName == null) 1388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new NullPointerException("null headerName"); 1389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sipHeader = (SIPHeader) nameTable.get(SIPHeaderNamesCache 1390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(headerName)); 1391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // empty iterator 1392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipHeader == null) 1393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return new LinkedList<SIPHeader>().listIterator(); 1394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipHeader instanceof SIPHeaderList) { 1395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return ((SIPHeaderList<SIPHeader>) sipHeader).listIterator(); 1396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return new HeaderIterator(this, sipHeader); 1398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get a header of the given name as a string. This concatenates the headers of a given type 1403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * as a comma separted list. This is useful for formatting and printing headers. 1404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param name 1406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the header as a formatted string 1407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getHeaderAsFormattedString(String name) { 1409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String lowerCaseName = name.toLowerCase(); 1410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.nameTable.containsKey(lowerCaseName)) { 1411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.nameTable.get(lowerCaseName).toString(); 1412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.getHeader(name).toString(); 1414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private SIPHeader getSIPHeaderListLowerCase(String lowerCaseHeaderName) { 1418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return nameTable.get(lowerCaseHeaderName); 1419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get a list of headers of the given name ( or null if no such header exists ). 1423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param headerName -- a header name from which to retrieve the list. 1425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return -- a list of headers with that name. 1426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang @SuppressWarnings("unchecked") 1428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private List<SIPHeader> getHeaderList(String headerName) { 1429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sipHeader = (SIPHeader) nameTable.get(SIPHeaderNamesCache 1430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(headerName)); 1431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipHeader == null) 1432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 1433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else if (sipHeader instanceof SIPHeaderList) 1434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (List<SIPHeader>) (((SIPHeaderList< ? >) sipHeader).getHeaderList()); 1435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else { 1436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang LinkedList<SIPHeader> ll = new LinkedList<SIPHeader>(); 1437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ll.add(sipHeader); 1438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return ll; 1439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return true if the SIPMessage has a header of the given name. 1444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param headerName is the header name for which we are testing. 1446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return true if the header is present in the message 1447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean hasHeader(String headerName) { 1449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return nameTable.containsKey(SIPHeaderNamesCache.toLowerCase(headerName)); 1450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return true if the message has a From header tag. 1454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return true if the message has a from header and that header has a tag. 1456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean hasFromTag() { 1458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return fromHeader != null && fromHeader.getTag() != null; 1459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return true if the message has a To header tag. 1463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return true if the message has a to header and that header has a tag. 1465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean hasToTag() { 1467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return toHeader != null && toHeader.getTag() != null; 1468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return the from tag. 1472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the tag from the from header. 1474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getFromTag() { 1477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return fromHeader == null ? null : fromHeader.getTag(); 1478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the From Tag. 1482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param tag -- tag to set in the from header. 1484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setFromTag(String tag) { 1486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang fromHeader.setTag(tag); 1488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException e) { 1489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the to tag. 1494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param tag -- tag to set. 1496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setToTag(String tag) { 1498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang toHeader.setTag(tag); 1500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException e) { 1501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return the to tag. 1506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getToTag() { 1508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return toHeader == null ? null : toHeader.getTag(); 1509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return the encoded first line. 1513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract String getFirstLine(); 1515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Add a SIP header. 1518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipHeader -- sip header to add. 1520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void addHeader(Header sipHeader) { 1522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Content length is never stored. Just computed. 1523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sh = (SIPHeader) sipHeader; 1524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ((sipHeader instanceof ViaHeader) || (sipHeader instanceof RecordRouteHeader)) { 1526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang attachHeader(sh, false, true); 1527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang attachHeader(sh, false, false); 1529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1530600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SIPDuplicateHeaderException ex) { 1531600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1532600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipHeader instanceof ContentLength) { 1533600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContentLength cl = (ContentLength) sipHeader; 1534600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang contentLengthHeader.setContentLength(cl.getContentLength()); 1535600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1536600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (InvalidArgumentException e) { 1537600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1538600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1539600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1540600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1541600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1542600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Add a header to the unparsed list of headers. 1543600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1544600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param unparsed -- unparsed header to add to the list. 1545600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1546600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void addUnparsed(String unparsed) { 1547600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.unrecognizedHeaders.add(unparsed); 1548600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1549600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1550600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1551600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Add a SIP header. 1552600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1553600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipHeader -- string version of SIP header to add. 1554600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1555600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1556600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void addHeader(String sipHeader) { 1557600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String hdrString = sipHeader.trim() + "\n"; 1558600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1559600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang HeaderParser parser = ParserFactory.createParser(sipHeader); 1560600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sh = parser.parse(); 1561600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.attachHeader(sh, false); 1562600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 1563600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.unrecognizedHeaders.add(hdrString); 1564600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1565600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1566600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1567600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1568600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get a list containing the unrecognized headers. 1569600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1570600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a linked list containing unrecongnized headers. 1571600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1572600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ListIterator<String> getUnrecognizedHeaders() { 1573600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.unrecognizedHeaders.listIterator(); 1574600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1575600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1576600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1577600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the header names. 1578600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1579600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a list iterator to a list of header names. These are ordered in the same order as 1580600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * are present in the message. 1581600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1582600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ListIterator<String> getHeaderNames() { 1583600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator<SIPHeader> li = this.headers.iterator(); 1584600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang LinkedList<String> retval = new LinkedList<String>(); 1585600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (li.hasNext()) { 1586600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sipHeader = (SIPHeader) li.next(); 1587600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String name = sipHeader.getName(); 1588600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.add(name); 1589600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1590600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval.listIterator(); 1591600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1592600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1593600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1594600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Compare for equality. 1595600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1596600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param other -- the other object to compare with. 1597600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1598600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean equals(Object other) { 1599600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!other.getClass().equals(this.getClass())) { 1600600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 1601600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1602600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPMessage otherMessage = (SIPMessage) other; 1603600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Collection<SIPHeader> values = this.nameTable.values(); 1604600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator<SIPHeader> it = values.iterator(); 1605600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (nameTable.size() != otherMessage.nameTable.size()) { 1606600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 1607600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1608600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1609600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (it.hasNext()) { 1610600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader mine = (SIPHeader) it.next(); 1611600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader his = (SIPHeader) (otherMessage.nameTable.get(SIPHeaderNamesCache 1612600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(mine.getName()))); 1613600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (his == null) { 1614600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 1615600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (!his.equals(mine)) { 1616600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 1617600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1618600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1619600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return true; 1620600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1621600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1622600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1623600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * get content disposition header or null if no such header exists. 1624600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1625600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the contentDisposition header 1626600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1627600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public javax.sip.header.ContentDispositionHeader getContentDisposition() { 1628600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (ContentDispositionHeader) getHeaderLowerCase(CONTENT_DISPOSITION_LOWERCASE); 1629600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1630600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1631600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String CONTENT_DISPOSITION_LOWERCASE = SIPHeaderNamesCache 1632600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(ContentDispositionHeader.NAME); 1633600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1634600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1635600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * get the content encoding header. 1636600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1637600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the contentEncoding header. 1638600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1639600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public javax.sip.header.ContentEncodingHeader getContentEncoding() { 1640600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (ContentEncodingHeader) getHeaderLowerCase(CONTENT_ENCODING_LOWERCASE); 1641600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1642600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1643600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String CONTENT_ENCODING_LOWERCASE = SIPHeaderNamesCache 1644600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(ContentEncodingHeader.NAME); 1645600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1646600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1647600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the contentLanguage header. 1648600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1649600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the content language header. 1650600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1651600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public javax.sip.header.ContentLanguageHeader getContentLanguage() { 1652600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (ContentLanguageHeader) getHeaderLowerCase(CONTENT_LANGUAGE_LOWERCASE); 1653600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1654600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1655600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String CONTENT_LANGUAGE_LOWERCASE = SIPHeaderNamesCache 1656600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(ContentLanguageHeader.NAME); 1657600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1658600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1659600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the exipres header. 1660600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1661600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the expires header or null if one does not exist. 1662600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1663600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public javax.sip.header.ExpiresHeader getExpires() { 1664600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (ExpiresHeader) getHeaderLowerCase(EXPIRES_LOWERCASE); 1665600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1666600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1667600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String EXPIRES_LOWERCASE = SIPHeaderNamesCache 1668600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(ExpiresHeader.NAME); 1669600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1670600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1671600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the expiresHeader 1672600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1673600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param expiresHeader -- the expires header to set. 1674600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1675600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1676600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setExpires(ExpiresHeader expiresHeader) { 1677600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(expiresHeader); 1678600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1679600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1680600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1681600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the content disposition header. 1682600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1683600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param contentDispositionHeader -- content disposition header. 1684600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1685600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1686600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setContentDisposition(ContentDispositionHeader contentDispositionHeader) { 1687600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(contentDispositionHeader); 1688600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1689600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1690600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1691600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setContentEncoding(ContentEncodingHeader contentEncodingHeader) { 1692600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(contentEncodingHeader); 1693600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1694600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1695600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1696600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setContentLanguage(ContentLanguageHeader contentLanguageHeader) { 1697600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(contentLanguageHeader); 1698600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1699600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1700600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1701600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the content length header. 1702600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1703600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param contentLength -- content length header. 1704600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1705600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setContentLength(ContentLengthHeader contentLength) { 1706600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1707600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.contentLengthHeader.setContentLength(contentLength.getContentLength()); 1708600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (InvalidArgumentException ex) { 1709600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1710600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1711600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1712600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1713600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1714600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the size of all the headers. This is for book keeping. Called by the parser. 1715600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1716600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param size -- size of the headers. 1717600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1718600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setSize(int size) { 1719600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.size = size; 1720600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1721600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1722600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int getSize() { 1723600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.size; 1724600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1725600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1726600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 1727600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (non-Javadoc) 1728600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1729600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see javax.sip.message.Message#addLast(javax.sip.header.Header) 1730600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1731600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void addLast(Header header) throws SipException, NullPointerException { 1732600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (header == null) 1733600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new NullPointerException("null arg!"); 1734600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1735600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1736600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.attachHeader((SIPHeader) header, false, false); 1737600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SIPDuplicateHeaderException ex) { 1738600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new SipException("Cannot add header - header already exists"); 1739600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1740600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1741600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1742600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1743600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 1744600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (non-Javadoc) 1745600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1746600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see javax.sip.message.Message#addFirst(javax.sip.header.Header) 1747600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1748600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void addFirst(Header header) throws SipException, NullPointerException { 1749600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1750600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (header == null) 1751600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new NullPointerException("null arg!"); 1752600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1753600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1754600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.attachHeader((SIPHeader) header, false, true); 1755600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SIPDuplicateHeaderException ex) { 1756600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new SipException("Cannot add header - header already exists"); 1757600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1758600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1759600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1760600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1761600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 1762600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (non-Javadoc) 1763600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1764600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see javax.sip.message.Message#removeFirst(java.lang.String) 1765600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1766600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void removeFirst(String headerName) throws NullPointerException { 1767600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (headerName == null) 1768600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new NullPointerException("Null argument Provided!"); 1769600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.removeHeader(headerName, true); 1770600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1771600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1772600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1773600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 1774600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (non-Javadoc) 1775600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1776600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see javax.sip.message.Message#removeLast(java.lang.String) 1777600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1778600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void removeLast(String headerName) { 1779600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (headerName == null) 1780600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new NullPointerException("Null argument Provided!"); 1781600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.removeHeader(headerName, false); 1782600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1783600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1784600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1785600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1786600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the CSeq header. 1787600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1788600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param cseqHeader -- CSeq Header. 1789600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1790600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1791600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setCSeq(CSeqHeader cseqHeader) { 1792600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setHeader(cseqHeader); 1793600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1794600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1795600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1796600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the application data pointer. This method is not used the stack. It is provided as a 1797600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * convenient way of storing book-keeping data for applications. Note that null clears the 1798600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * application data pointer (releases it). 1799600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1800600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param applicationData -- application data pointer to set. null clears the application data 1801600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * pointer. 1802600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1803600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setApplicationData(Object applicationData) { 1804600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.applicationData = applicationData; 1805600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1806600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1807600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1808600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the application data associated with this message. 1809600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1810600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return stored application data. 1811600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1812600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Object getApplicationData() { 1813600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.applicationData; 1814600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1815600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1816600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1817600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the multipart MIME content 1818600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1819600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1820600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public MultipartMimeContent getMultipartMimeContent() throws ParseException { 1821600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.contentLengthHeader.getContentLength() == 0) { 1822600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 1823600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1824600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang MultipartMimeContentImpl retval = new MultipartMimeContentImpl(this 1825600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getContentTypeHeader()); 1826600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] rawContent = getRawContent(); 1827600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1828600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String body = new String( rawContent, getCharset() ); 1829600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.createContentList(body); 1830600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 1831600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (UnsupportedEncodingException e) { 1832600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(e); 1833600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 1834600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1835600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1836600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1837600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public CallIdHeader getCallIdHeader() { 1838600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.callIdHeader; 1839600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1840600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1841600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1842600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public FromHeader getFromHeader() { 1843600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.fromHeader; 1844600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1845600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1846600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1847600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ToHeader getToHeader() { 1848600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.toHeader; 1849600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1850600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1851600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1852600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ViaHeader getTopmostViaHeader() { 1853600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.getTopmostVia(); 1854600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1855600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1856600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public CSeqHeader getCSeqHeader() { 1857600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.cSeqHeader; 1858600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1859600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1860600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1861600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Returns the charset to use for encoding/decoding the body of this message 1862600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1863600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected final String getCharset() { 1864600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContentType ct = getContentTypeHeader(); 1865600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (ct!=null) { 1866600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String c = ct.getCharset(); 1867600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return c!=null ? c : contentEncodingCharset; 1868600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else return contentEncodingCharset; 1869600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1870600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1871600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1872600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return true if this is a null request (i.e. does not have a request line ). 1873600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1874600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return true if null request. 1875600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1876600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean isNullRequest() { 1877600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.nullRequest; 1878600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1879600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1880600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1881600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set a flag to indiate this is a special message ( encoded with CRLFCRLF ). 1882600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1883600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1884600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setNullRequest() { 1885600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.nullRequest = true; 1886600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1887600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1888600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1889600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract void setSIPVersion(String sipVersion) throws ParseException; 1890600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1891600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract String getSIPVersion(); 1892600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1893600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract String toString(); 1894600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1895600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 1896