001: /*
002: * Portions Copyright 2000-2007 Sun Microsystems, Inc. All Rights
003: * Reserved. Use is subject to license terms.
004: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License version
008: * 2 only, as published by the Free Software Foundation.
009: *
010: * This program is distributed in the hope that it will be useful, but
011: * WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * General Public License version 2 for more details (a copy is
014: * included at /legal/license.txt).
015: *
016: * You should have received a copy of the GNU General Public License
017: * version 2 along with this work; if not, write to the Free Software
018: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
022: * Clara, CA 95054 or visit www.sun.com if you need additional
023: * information or have any questions.
024: */
025: /*
026: */
027: package gov.nist.siplite.header;
028:
029: import gov.nist.core.*;
030: import java.util.Calendar;
031:
032: /**
033: * Generic SipHeader class
034: * All the Headers inherit of this class
035: *
036: * @version JAIN-SIP-1.1
037: *
038: *
039: * <a href="{@docRoot}/uncopyright.html">This code is in the public domain.</a>
040: *
041: */
042: public abstract class Header extends GenericObject {
043:
044: /**
045: * Constant ERROR_INFO field.
046: */
047: public static final String ERROR_INFO = "Error-Info";
048:
049: /**
050: * Constant MIME_VERSION field.
051: */
052: public static final String MIME_VERSION = "Mime-Version";
053:
054: /**
055: * Constant IN_REPLY_TO field.
056: */
057: public static final String IN_REPLY_TO = "In-Reply-To";
058:
059: /**
060: * Constant ALLOW field.
061: */
062: public static final String ALLOW = "Allow";
063:
064: /**
065: * Constant ALLOW_EVENTS field.
066: */
067: public static final String ALLOW_EVENTS = "Allow-Events";
068:
069: /**
070: * Constant CONTENT_LANGUAGE field.
071: */
072: public static final String CONTENT_LANGUAGE = "Content-Language";
073:
074: /**
075: * Constant CALL_INFO field.
076: */
077: public static final String CALL_INFO = "Call-Info";
078:
079: /**
080: * Constant CSEQ field.
081: */
082: public static final String CSEQ = "CSeq";
083:
084: /**
085: * Constant ALERT_INFO field.
086: */
087: public static final String ALERT_INFO = "Alert-Info";
088:
089: /**
090: * Constant ACCEPT_ENCODING field.
091: */
092: public static final String ACCEPT_ENCODING = "Accept-Encoding";
093:
094: /**
095: * Constant ACCEPT field.
096: */
097: public static final String ACCEPT = "Accept";
098:
099: /**
100: * Constant ENCRYPTION field.
101: */
102: public static final String ENCRYPTION = "Encryption";
103:
104: /**
105: * Constant ACCEPT_LANGUAGE field.
106: */
107: public static final String ACCEPT_LANGUAGE = "Accept-Language";
108:
109: /**
110: * Constant ACCEPT_CONTACT field.
111: */
112: public static final String ACCEPT_CONTACT = "Accept-Contact";
113:
114: /**
115: * Constant RECORD_ROUTE field.
116: */
117: public static final String RECORD_ROUTE = "Record-Route";
118:
119: /**
120: * Constant TIMESTAMP field.
121: */
122: public static final String TIMESTAMP = "Timestamp";
123:
124: /**
125: * Constant TO field.
126: */
127: public static final String TO = "To";
128:
129: /**
130: * Constant VIA field.
131: */
132: public static final String VIA = "Via";
133:
134: /**
135: * Constant FROM field.
136: */
137: public static final String FROM = "From";
138:
139: /**
140: * Constant CALL_ID field.
141: */
142: public static final String CALL_ID = "Call-ID";
143:
144: /**
145: * Constant AUTHENTICATION_INFO field.
146: */
147: public static final String AUTHENTICATION_INFO = "Authentication-Info";
148:
149: /**
150: * Constant AUTHORIZATION field.
151: */
152: public static final String AUTHORIZATION = "Authorization";
153:
154: /**
155: * Constant PROXY_AUTHENTICATE field.
156: */
157: public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
158:
159: /**
160: * Constant SERVER field.
161: */
162: public static final String SERVER = "Server";
163:
164: /**
165: * Constant UNSUPPORTED field.
166: */
167: public static final String UNSUPPORTED = "Unsupported";
168:
169: /**
170: * Constant RETRY_AFTER field.
171: */
172: public static final String RETRY_AFTER = "Retry-After";
173:
174: /**
175: * Constant CONTENT_TYP field.
176: */
177: public static final String CONTENT_TYPE = "Content-Type";
178:
179: /**
180: * Constant CONTENT_ENCODING field.
181: */
182: public static final String CONTENT_ENCODING = "Content-Encoding";
183:
184: /**
185: * Constant CONTENT_LENGTH field.
186: */
187: public static final String CONTENT_LENGTH = "Content-Length";
188:
189: /**
190: * Constant HIDE field.
191: */
192: public static final String HIDE = "Hide";
193:
194: /**
195: * Constant ROUTE field.
196: */
197: public static final String ROUTE = "Route";
198:
199: /**
200: * Constant CONTACT field.
201: */
202: public static final String CONTACT = "Contact";
203:
204: /**
205: * Constant WWW_AUTHENTICATE field.
206: */
207: public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
208:
209: /**
210: * Constant MAX_FORWARDS field.
211: */
212: public static final String MAX_FORWARDS = "Max-Forwards";
213:
214: /**
215: * Constant ORGANIZATION field.
216: */
217: public static final String ORGANIZATION = "Organization";
218:
219: /**
220: * Constant PROXY_AUTHORIZATION field.
221: */
222: public static final String PROXY_AUTHORIZATION = "Proxy-Authorization";
223:
224: /**
225: * Constant PROXY_REQUIRE field.
226: */
227: public static final String PROXY_REQUIRE = "Proxy-Require";
228:
229: /**
230: * Constant REQUIRE field.
231: */
232: public static final String REQUIRE = "Require";
233:
234: /**
235: * Constant CONTENT_DISPOSITION field.
236: */
237: public static final String CONTENT_DISPOSITION = "Content-Disposition";
238:
239: /**
240: * Constant SUBJECT field.
241: */
242: public static final String SUBJECT = "Subject";
243:
244: /**
245: * Constant USER_AGENT field.
246: */
247: public static final String USER_AGENT = "User-Agent";
248:
249: /**
250: * Constant WARNING field.
251: */
252: public static final String WARNING = "Warning";
253:
254: /**
255: * Constant PRIORITY field.
256: */
257: public static final String PRIORITY = "Priority";
258:
259: /**
260: * Constant DATE field.
261: */
262: public static final String DATE = "Date";
263:
264: /**
265: * Constant MIN_EXPIRES field.
266: */
267: public static final String MIN_EXPIRES = "Min-Expires";
268:
269: /**
270: * Constant EXPIRES field.
271: */
272: public static final String EXPIRES = "Expires";
273:
274: /**
275: * Constant RESPONSE_KEY field.
276: */
277: public static final String RESPONSE_KEY = "Response-Key";
278:
279: /**
280: * Constant WARN_AGENT field.
281: */
282: public static final String WARN_AGENT = "Warn-Agent";
283:
284: /**
285: * Constant SUPPORTED field.
286: */
287: public static final String SUPPORTED = "Supported";
288:
289: /** Constant EVENT field. */
290: public static final String EVENT = "Event";
291:
292: /** Constant EXTENSION field. */
293: public static final String EXTENSION = "Extension";
294:
295: /** Constant SUBSCRIPTION_STATE field. */
296: public static final String SUBSCRIPTION_STATE = "Subscription-State";
297:
298: /** Constant SIP_ETAG field (RFC 3903, p. 21). */
299: public static final String SIP_ETAG = "SIP-ETag";
300:
301: /** Constant SIP_IF_MATCH field (RFC 3903, p. 22). */
302: public static final String SIP_IF_MATCH = "SIP-If-Match";
303:
304: /** Constant Refer-To field (RFC 3515, p. 3). */
305: public static final String REFER_TO = "Refer-To";
306:
307: /** Constant RSEQ field (RFC 3262, p. 11). */
308: public static final String RSEQ = "RSeq";
309:
310: /** Constant RAck field (RFC 3262, p. 11). */
311: public static final String RACK = "RAck";
312:
313: /**
314: * Name of the header.
315: */
316: public String headerName;
317:
318: /**
319: * Value of the header.
320: */
321: public String headerValue;
322:
323: /**
324: * Array of the headers that can not have any parameters.
325: *
326: * NOTE: If the size of this array is changed,
327: * getStringHash() method also must be changed!
328: */
329: public static final String[] parameterLessHeaders = {
330: AUTHENTICATION_INFO, // hash = 0
331: null, ALLOW, // 2
332: null, null, null, null, null, IN_REPLY_TO, // 8
333: PRIORITY, // 9
334: null, null, MIME_VERSION, // 12
335: SERVER, // 13
336: TIMESTAMP, // 14
337: USER_AGENT, // 15
338: null, MIN_EXPIRES, // 17
339: SUBJECT, // 18
340: null, null,
341: // We can't create an instance of ParameterLessHeader class for
342: // Content-Length header, because there is a check like
343: // "header instanceof ContentLengthHeader" in Message.encodeAsBytes().
344: null, // CONTENT_LENGTH, // 21
345: CONTENT_LANGUAGE, // 22
346: null, WARNING, // 24
347: CONTENT_ENCODING, // 25
348: ORGANIZATION, // 26
349: UNSUPPORTED, // 27
350: null, null, null, REQUIRE, // 31
351: SUPPORTED, // 32
352: null, null, null, PROXY_REQUIRE, // 36
353: null, null };
354:
355: /**
356: * Default constructor.
357: */
358: public Header() {
359: }
360:
361: /**
362: * Constructor given the name.
363: * @param headerName the initial header field name
364: */
365: public Header(String headerName) {
366: this .headerName = headerName;
367: }
368:
369: /**
370: * Constructor given the name and value.
371: * @param headerName is the header name.
372: * @param headerValue is the header value.
373: */
374: public Header(String headerName, String headerValue) {
375: this .headerName = headerName;
376: this .headerValue = headerValue;
377: }
378:
379: /**
380: * Sets the header name field.
381: * @param name is the header name to set.
382: */
383: public void setHeaderName(String name) {
384: this .headerName = name;
385: }
386:
387: /**
388: * Sets the header value field.
389: * @param value is the value field to set.
390: */
391: public void setHeaderValue(String value) {
392: this .headerValue = value;
393: }
394:
395: /**
396: * Gets the header name.
397: * @return headerName field
398: */
399: public String getHeaderName() {
400: return this .headerName;
401: }
402:
403: /**
404: * Alias for getHeaderName.
405: * @return headerName field
406: */
407: public String getName() {
408: return this .headerName;
409: }
410:
411: /**
412: * Gets the header value.
413: * @return headerValue field
414: */
415: public String getHeaderValue() {
416: return this .encodeBody();
417: }
418:
419: /**
420: * Encodes the header into a String.
421: * @return String
422: */
423: public String encode() {
424: if (headerName == null) {
425: return "";
426: } else {
427: return headerName + Separators.COLON + Separators.SP
428: + encodeBody() + Separators.NEWLINE;
429: }
430: }
431:
432: /**
433: * A place holder -- this should be overriden with an actual
434: * clone method.
435: * @return need revisit copy of the current object
436: */
437: public Object clone() {
438: return this ;
439:
440: }
441:
442: /**
443: * A utility for encoding dates.
444: * @param date the object to encode
445: * @return the encode date string
446: */
447: public static String encodeCalendar(Calendar date) {
448: StringBuffer sbuf = new StringBuffer();
449: int wkday = date.get(Calendar.DAY_OF_WEEK);
450: switch (wkday) {
451: case Calendar.MONDAY:
452: sbuf.append("Mon");
453: break;
454: case Calendar.TUESDAY:
455: sbuf.append("Tue");
456: break;
457: case Calendar.WEDNESDAY:
458: sbuf.append("Wed");
459: break;
460: case Calendar.THURSDAY:
461: sbuf.append("Thu");
462: break;
463: case Calendar.FRIDAY:
464: sbuf.append("Fri");
465: break;
466: case Calendar.SATURDAY:
467: sbuf.append("Sat");
468: break;
469: case Calendar.SUNDAY:
470: sbuf.append("Sun");
471: break;
472: default:
473: new Exception("bad day of week?? Huh?? " + wkday)
474: .printStackTrace();
475: return null;
476: }
477: int day = date.get(Calendar.DAY_OF_MONTH);
478: if (day < 10)
479: sbuf.append(", 0" + day);
480: else
481: sbuf.append(", " + day);
482: sbuf.append(" ");
483: int month = date.get(Calendar.MONTH);
484: switch (month) {
485: case Calendar.JANUARY:
486: sbuf.append("Jan");
487: break;
488: case Calendar.FEBRUARY:
489: sbuf.append("Feb");
490: break;
491: case Calendar.MARCH:
492: sbuf.append("Mar");
493: break;
494: case Calendar.APRIL:
495: sbuf.append("Apr");
496: break;
497: case Calendar.MAY:
498: sbuf.append("May");
499: break;
500: case Calendar.JUNE:
501: sbuf.append("Jun");
502: break;
503: case Calendar.JULY:
504: sbuf.append("Jul");
505: break;
506: case Calendar.AUGUST:
507: sbuf.append("Aug");
508: break;
509: case Calendar.SEPTEMBER:
510: sbuf.append("Sep");
511: break;
512: case Calendar.OCTOBER:
513: sbuf.append("Oct");
514: break;
515: case Calendar.NOVEMBER:
516: sbuf.append("Nov");
517: break;
518: case Calendar.DECEMBER:
519: sbuf.append("Dec");
520: break;
521: default:
522: return null;
523: }
524:
525: sbuf.append(" ");
526: int year = date.get(Calendar.YEAR);
527: sbuf.append(year);
528: sbuf.append(" ");
529: int hour = date.get(Calendar.HOUR_OF_DAY);
530: if (hour < 10)
531: sbuf.append("0" + hour);
532: else
533: sbuf.append(hour);
534: sbuf.append(":");
535: int min = date.get(Calendar.MINUTE);
536: if (min < 10)
537: sbuf.append("0" + min);
538: else
539: sbuf.append(min);
540: sbuf.append(":");
541: int sec = date.get(Calendar.SECOND);
542: if (sec < 10)
543: sbuf.append("0" + sec);
544: else
545: sbuf.append(sec);
546:
547: sbuf.append(" GMT");
548: return sbuf.toString();
549:
550: }
551:
552: /**
553: * Gets the parameters for the header as a nameValue list.
554: * @return the name value list of header field paramaters
555: */
556: public abstract NameValueList getParameters();
557:
558: /**
559: * Gets the value for the header as opaque object (returned value
560: * will depend upon the header. Note that this is not the same as
561: * the getHeaderValue above.
562: * @return the header field value
563: */
564: public abstract Object getValue();
565:
566: /**
567: * Gets the stuff that follows the headerName.
568: * @return a string representation of the stuff that follows the
569: * headerName
570: */
571: protected abstract String encodeBody();
572:
573: /**
574: * Returns the encoded text contents.
575: * @return encode string of object contents
576: */
577: public String toString() {
578: return this .encode();
579: }
580:
581: /**
582: * Calculates a signle-byte hash code of the string.
583: * @param s is a string for which a hash code must be calculated
584: * @return hash code (from 0 to parameterLessHeaders.length) of the string
585: */
586: public static byte getStringHash(String s) {
587: String sl = s.toLowerCase();
588: int len = sl.length(), headersCount = parameterLessHeaders.length;
589: int hash = len;
590:
591: for (int i = 0; i < len; i++) {
592: hash += sl.charAt(i);
593: }
594:
595: hash = (byte) (hash % headersCount);
596:
597: if (hash == 6) {
598: hash = (hash + 9 + sl.charAt(0)) % headersCount;
599: } else if (hash == 7) {
600: hash = (hash + 13 + sl.charAt(0)) % headersCount;
601: }
602:
603: // System.out.println("hash('" + s + "') = " + hash);
604:
605: return (byte) hash;
606: }
607:
608: /**
609: * Checks if the specified header can have some parameters.
610: * @param name the name of the header
611: * @return true if the header can not have any parameters, false otherwise
612: */
613: public static boolean isParameterLess(String name) {
614: byte hash;
615:
616: // IMPL_NOTE: remove!!!
617: // for (int i = 0; i < parameterLessHeaders.length; i++) {
618: // if (parameterLessHeaders[i] != null)
619: // getStringHash(parameterLessHeaders[i]);
620: // }
621:
622: hash = getStringHash(name);
623:
624: return (parameterLessHeaders[hash] != null && parameterLessHeaders[hash]
625: .equalsIgnoreCase(name));
626: }
627:
628: /**
629: * Checks if a header with the given name is an Authorization
630: * or Authentication header.
631: * @param name the name of the header
632: * @return true if the header is an Authorization or Authentication header
633: */
634: public static boolean isAuthorization(String name) {
635: if (name == null) {
636: return false;
637: }
638:
639: return (name.equalsIgnoreCase(Header.AUTHORIZATION)
640: || name.equalsIgnoreCase(Header.PROXY_AUTHORIZATION)
641: || name.equalsIgnoreCase(Header.PROXY_AUTHENTICATE) || name
642: .equalsIgnoreCase(Header.WWW_AUTHENTICATE));
643: }
644:
645: /**
646: * Search for the reliable tag, "100rel" in a "Require" Header value.
647: * This method is internally used to identify if the response
648: * received at UAC is reliable provisional response
649: * @param strOptionTags List of option tags that is actually a value
650: * of Require Header
651: * @return true if "100rel" tags is found; else false
652: */
653: public static boolean isReliableTagPresent(String strOptionTags) {
654: if (Utils.equalsIgnoreCase(strOptionTags, "100rel")) {
655: return true;
656: } else {
657: String tag = null;
658: // int tagsLength = strOptionTags.length();
659: int delimIndex = strOptionTags.indexOf(Separators.COMMA);
660: while (delimIndex > 0) {
661: tag = strOptionTags.substring(0, delimIndex).trim();
662: strOptionTags = strOptionTags.substring(delimIndex + 1,
663: strOptionTags.length()).trim();
664: if (Utils.equalsIgnoreCase(tag, "100rel")
665: || Utils.equalsIgnoreCase(strOptionTags,
666: "100rel")) {
667: return true;
668: }
669: delimIndex = strOptionTags.indexOf(Separators.COMMA);
670: }
671: }
672: return false;
673: }
674:
675: }
|