1/*
2* Conditions Of Use
3*
4* This software was developed by employees of the National Institute of
5* Standards and Technology (NIST), an agency of the Federal Government.
6* Pursuant to title 15 Untied States Code Section 105, works of NIST
7* employees are not subject to copyright protection in the United States
8* and are considered to be in the public domain.  As a result, a formal
9* license is not needed to use the software.
10*
11* This software is provided by NIST as a service and is expressly
12* provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15* AND DATA ACCURACY.  NIST does not warrant or make any representations
16* regarding the use of the software or the results thereof, including but
17* not limited to the correctness, accuracy, reliability or usefulness of
18* the software.
19*
20* Permission to use this software is contingent upon your acceptance
21* of the terms of this agreement
22*
23* .
24*
25*/
26package gov.nist.javax.sip.parser;
27import gov.nist.javax.sip.parser.ims.*;
28import gov.nist.javax.sip.header.ims.*;
29import java.util.Hashtable;
30import java.lang.reflect.*;
31import javax.sip.header.*;
32import java.text.ParseException;
33import gov.nist.core.*;
34import gov.nist.javax.sip.header.extensions.*;
35import gov.nist.javax.sip.header.SIPHeaderNamesCache;
36import gov.nist.javax.sip.parser.extensions.*;
37
38/**
39 * A factory class that does a name lookup on a registered parser and
40 * returns a header parser for the given name.
41 *
42 * @version 1.2 $Revision: 1.17 $ $Date: 2010/01/12 00:05:25 $
43 *
44 * @author M. Ranganathan   <br/>
45 *
46 *
47 *
48 */
49public class ParserFactory {
50
51    private static Hashtable<String,Class<? extends HeaderParser>> parserTable;
52    private static Class[] constructorArgs;
53    private static Hashtable parserConstructorCache;
54
55    static {
56        parserTable = new Hashtable<String,Class<? extends HeaderParser>>();
57        parserConstructorCache = new Hashtable();
58        constructorArgs = new Class[1];
59        constructorArgs[0] = String.class;
60        parserTable.put(ReplyToHeader.NAME.toLowerCase(), ReplyToParser.class);
61
62        parserTable.put(
63            InReplyToHeader.NAME.toLowerCase(),
64            InReplyToParser.class);
65
66        parserTable.put(
67            AcceptEncodingHeader.NAME.toLowerCase(),
68            AcceptEncodingParser.class);
69
70        parserTable.put(
71            AcceptLanguageHeader.NAME.toLowerCase(),
72            AcceptLanguageParser.class);
73
74        parserTable.put("t", ToParser.class);
75        parserTable.put(ToHeader.NAME.toLowerCase(), ToParser.class);
76
77        parserTable.put(FromHeader.NAME.toLowerCase(), FromParser.class);
78        parserTable.put("f", FromParser.class);
79
80        parserTable.put(CSeqHeader.NAME.toLowerCase(), CSeqParser.class);
81
82        parserTable.put(ViaHeader.NAME.toLowerCase(), ViaParser.class);
83        parserTable.put("v", ViaParser.class);
84
85        parserTable.put(ContactHeader.NAME.toLowerCase(), ContactParser.class);
86        parserTable.put("m", ContactParser.class);
87
88        parserTable.put(
89            ContentTypeHeader.NAME.toLowerCase(),
90            ContentTypeParser.class);
91        parserTable.put("c", ContentTypeParser.class);
92
93        parserTable.put(
94            ContentLengthHeader.NAME.toLowerCase(),
95            ContentLengthParser.class);
96        parserTable.put("l", ContentLengthParser.class);
97
98        parserTable.put(
99            AuthorizationHeader.NAME.toLowerCase(),
100            AuthorizationParser.class);
101
102        parserTable.put(
103            WWWAuthenticateHeader.NAME.toLowerCase(),
104            WWWAuthenticateParser.class);
105
106        parserTable.put(CallIdHeader.NAME.toLowerCase(), CallIDParser.class);
107        parserTable.put("i", CallIDParser.class);
108
109        parserTable.put(RouteHeader.NAME.toLowerCase(), RouteParser.class);
110
111        parserTable.put(
112            RecordRouteHeader.NAME.toLowerCase(),
113            RecordRouteParser.class);
114
115        parserTable.put(DateHeader.NAME.toLowerCase(), DateParser.class);
116
117        parserTable.put(
118            ProxyAuthorizationHeader.NAME.toLowerCase(),
119            ProxyAuthorizationParser.class);
120
121        parserTable.put(
122            ProxyAuthenticateHeader.NAME.toLowerCase(),
123            ProxyAuthenticateParser.class);
124
125        parserTable.put(
126            RetryAfterHeader.NAME.toLowerCase(),
127            RetryAfterParser.class);
128
129        parserTable.put(RequireHeader.NAME.toLowerCase(), RequireParser.class);
130
131        parserTable.put(
132            ProxyRequireHeader.NAME.toLowerCase(),
133            ProxyRequireParser.class);
134
135        parserTable.put(
136            TimeStampHeader.NAME.toLowerCase(),
137            TimeStampParser.class);
138
139        parserTable.put(
140            UnsupportedHeader.NAME.toLowerCase(),
141            UnsupportedParser.class);
142
143        parserTable.put(
144            UserAgentHeader.NAME.toLowerCase(),
145            UserAgentParser.class);
146
147        parserTable.put(
148            SupportedHeader.NAME.toLowerCase(),
149            SupportedParser.class);
150        // bug fix by Steve Crosley
151        parserTable.put("k", SupportedParser.class);
152
153        parserTable.put(ServerHeader.NAME.toLowerCase(), ServerParser.class);
154
155        parserTable.put(SubjectHeader.NAME.toLowerCase(), SubjectParser.class);
156        parserTable.put( "s", SubjectParser.class); // JvB: added
157
158        parserTable.put(
159            SubscriptionStateHeader.NAME.toLowerCase(),
160            SubscriptionStateParser.class);
161
162        parserTable.put(
163            MaxForwardsHeader.NAME.toLowerCase(),
164            MaxForwardsParser.class);
165
166        parserTable.put(
167            MimeVersionHeader.NAME.toLowerCase(),
168            MimeVersionParser.class);
169
170        parserTable.put(
171            MinExpiresHeader.NAME.toLowerCase(),
172            MinExpiresParser.class);
173
174        parserTable.put(
175            OrganizationHeader.NAME.toLowerCase(),
176            OrganizationParser.class);
177
178        parserTable.put(
179            PriorityHeader.NAME.toLowerCase(),
180            PriorityParser.class);
181
182        parserTable.put(RAckHeader.NAME.toLowerCase(), RAckParser.class);
183
184        parserTable.put(RSeqHeader.NAME.toLowerCase(), RSeqParser.class);
185
186        parserTable.put(ReasonHeader.NAME.toLowerCase(), ReasonParser.class);
187
188        parserTable.put(WarningHeader.NAME.toLowerCase(), WarningParser.class);
189
190        parserTable.put(ExpiresHeader.NAME.toLowerCase(), ExpiresParser.class);
191
192        parserTable.put(EventHeader.NAME.toLowerCase(), EventParser.class);
193        parserTable.put("o", EventParser.class);
194
195        parserTable.put(
196            ErrorInfoHeader.NAME.toLowerCase(),
197            ErrorInfoParser.class);
198
199        parserTable.put(
200            ContentLanguageHeader.NAME.toLowerCase(),
201            ContentLanguageParser.class);
202
203        parserTable.put(
204            ContentEncodingHeader.NAME.toLowerCase(),
205            ContentEncodingParser.class);
206        parserTable.put("e", ContentEncodingParser.class);
207
208        parserTable.put(
209            ContentDispositionHeader.NAME.toLowerCase(),
210            ContentDispositionParser.class);
211
212        parserTable.put(
213            CallInfoHeader.NAME.toLowerCase(),
214            CallInfoParser.class);
215
216        parserTable.put(
217            AuthenticationInfoHeader.NAME.toLowerCase(),
218            AuthenticationInfoParser.class);
219
220        parserTable.put(AllowHeader.NAME.toLowerCase(), AllowParser.class);
221
222        parserTable.put(
223            AllowEventsHeader.NAME.toLowerCase(),
224            AllowEventsParser.class);
225        parserTable.put("u", AllowEventsParser.class);
226
227        parserTable.put(
228            AlertInfoHeader.NAME.toLowerCase(),
229            AlertInfoParser.class);
230
231        parserTable.put(AcceptHeader.NAME.toLowerCase(), AcceptParser.class);
232
233        parserTable.put(ReferToHeader.NAME.toLowerCase(), ReferToParser.class);
234        // Was missing (bug noticed by Steve Crossley)
235        parserTable.put("r", ReferToParser.class);
236
237        // JvB: added to support RFC3903 PUBLISH
238        parserTable.put(SIPETagHeader.NAME.toLowerCase(), SIPETagParser.class);
239        parserTable.put(SIPIfMatchHeader.NAME.toLowerCase(), SIPIfMatchParser.class);
240
241        //IMS headers
242        parserTable.put(PAccessNetworkInfoHeader.NAME.toLowerCase(), PAccessNetworkInfoParser.class);
243        parserTable.put(PAssertedIdentityHeader.NAME.toLowerCase(), PAssertedIdentityParser.class);
244        parserTable.put(PPreferredIdentityHeader.NAME.toLowerCase(), PPreferredIdentityParser.class);
245        parserTable.put(PChargingVectorHeader.NAME.toLowerCase(), PChargingVectorParser.class);
246        parserTable.put(PChargingFunctionAddressesHeader.NAME.toLowerCase(), PChargingFunctionAddressesParser.class);
247        parserTable.put(PMediaAuthorizationHeader.NAME.toLowerCase(), PMediaAuthorizationParser.class);
248        parserTable.put(PathHeader.NAME.toLowerCase(), PathParser.class);
249        parserTable.put(PrivacyHeader.NAME.toLowerCase(), PrivacyParser.class);
250        parserTable.put(ServiceRouteHeader.NAME.toLowerCase(), ServiceRouteParser.class);
251        parserTable.put(PVisitedNetworkIDHeader.NAME.toLowerCase(), PVisitedNetworkIDParser.class);
252
253        parserTable.put(PAssociatedURIHeader.NAME.toLowerCase(), PAssociatedURIParser.class);
254        parserTable.put(PCalledPartyIDHeader.NAME.toLowerCase(), PCalledPartyIDParser.class);
255
256        parserTable.put(SecurityServerHeader.NAME.toLowerCase(), SecurityServerParser.class);
257        parserTable.put(SecurityClientHeader.NAME.toLowerCase(), SecurityClientParser.class);
258        parserTable.put(SecurityVerifyHeader.NAME.toLowerCase(), SecurityVerifyParser.class);
259
260
261        // Per RFC 3892 (pmusgrave)
262        parserTable.put(ReferredBy.NAME.toLowerCase(), ReferredByParser.class);
263        parserTable.put("b", ReferToParser.class);
264
265        // Per RFC4028 Session Timers (pmusgrave)
266        parserTable.put(SessionExpires.NAME.toLowerCase(), SessionExpiresParser.class);
267        parserTable.put("x", SessionExpiresParser.class);
268        parserTable.put(MinSE.NAME.toLowerCase(), MinSEParser.class);
269        // (RFC4028 does not give a short form header for MinSE)
270
271        // Per RFC3891 (pmusgrave)
272        parserTable.put(Replaces.NAME.toLowerCase(), ReplacesParser.class);
273
274        // Per RFC3911 (jean deruelle)
275        parserTable.put(Join.NAME.toLowerCase(), JoinParser.class);
276
277        //http://tools.ietf.org/html/draft-worley-references-05
278        parserTable.put(References.NAME.toLowerCase(), ReferencesParser.class);
279    }
280
281    /**
282     * create a parser for a header. This is the parser factory.
283     */
284    public static HeaderParser createParser(String line)
285        throws ParseException {
286        String headerName = Lexer.getHeaderName(line);
287        String headerValue = Lexer.getHeaderValue(line);
288        if (headerName == null || headerValue == null)
289            throw new ParseException("The header name or value is null", 0);
290
291        Class parserClass = (Class) parserTable.get(SIPHeaderNamesCache.toLowerCase(headerName));
292        if (parserClass != null) {
293            try {
294                Constructor cons = (Constructor) parserConstructorCache.get(parserClass);
295                if (cons == null) {
296                    cons = parserClass.getConstructor(constructorArgs);
297                    parserConstructorCache.put(parserClass, cons);
298                }
299                Object[] args = new Object[1];
300                args[0] = line;
301                HeaderParser retval = (HeaderParser) cons.newInstance(args);
302                return retval;
303
304            } catch (Exception ex) {
305                InternalErrorHandler.handleException(ex);
306                return null; // to placate the compiler.
307            }
308
309        } else {
310            // Just generate a generic SIPHeader. We define
311            // parsers only for the above.
312            return new HeaderParser(line);
313        }
314    }
315}
316/*
317 * $Log: ParserFactory.java,v $
318 * Revision 1.17  2010/01/12 00:05:25  mranga
319 * Add support for References header draft-worley-references-05
320 *
321 * Revision 1.16  2009/07/17 18:58:01  emcho
322 * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project.
323 *
324 * Revision 1.15  2009/01/22 19:33:48  deruelle_jean
325 * Add support for JOIN (RFC 3911)
326 * Issue number:  186
327 * Obtained from:
328 * Submitted by:  Jean Deruelle
329 * Reviewed by:   Ranga, The high priest and grand poobah of Jain-SIP
330 *
331 * Revision 1.14  2007/03/07 14:29:46  belangery
332 * Yet another bunch of improvements in the parsing code.
333 *
334 * Revision 1.13  2007/02/23 14:56:06  belangery
335 * Added performance improvement around header name lowercase conversion.
336 *
337 * Revision 1.12  2007/01/08 19:24:21  mranga
338 * Issue number:
339 * Obtained from:
340 * Submitted by:  Miguel Freitas
341 * Reviewed by:   mranga
342 *
343 * Miguel -- please implement a deep clone method for the IMS headers.
344 *
345 * CVS: ----------------------------------------------------------------------
346 * CVS: Issue number:
347 * CVS:   If this change addresses one or more issues,
348 * CVS:   then enter the issue number(s) here.
349 * CVS: Obtained from:
350 * CVS:   If this change has been taken from another system,
351 * CVS:   then name the system in this line, otherwise delete it.
352 * CVS: Submitted by:
353 * CVS:   If this code has been contributed to the project by someone else; i.e.,
354 * CVS:   they sent us a patch or a set of diffs, then include their name/email
355 * CVS:   address here. If this is your work then delete this line.
356 * CVS: Reviewed by:
357 * CVS:   If we are doing pre-commit code reviews and someone else has
358 * CVS:   reviewed your changes, include their name(s) here.
359 * CVS:   If you have not had it reviewed then delete this line.
360 *
361 * Revision 1.11  2006/10/12 11:57:54  pmusgrave
362 * Issue number:  79, 80
363 * Submitted by:  pmusgrave@newheights.com
364 * Reviewed by:   mranga
365 *
366 * Revision 1.10  2006/09/29 19:40:50  jbemmel
367 * fixed missing IMS header parsing plumbing
368 *
369 * Revision 1.9  2006/09/11 18:41:32  mranga
370 * Issue number:
371 * Obtained from:
372 * Submitted by:  mranga
373 * Reviewed by:
374 * Tighter integration of IMS headers.
375 * CVS: ----------------------------------------------------------------------
376 * CVS: Issue number:
377 * CVS:   If this change addresses one or more issues,
378 * CVS:   then enter the issue number(s) here.
379 * CVS: Obtained from:
380 * CVS:   If this change has been taken from another system,
381 * CVS:   then name the system in this line, otherwise delete it.
382 * CVS: Submitted by:
383 * CVS:   If this code has been contributed to the project by someone else; i.e.,
384 * CVS:   they sent us a patch or a set of diffs, then include their name/email
385 * CVS:   address here. If this is your work then delete this line.
386 * CVS: Reviewed by:
387 * CVS:   If we are doing pre-commit code reviews and someone else has
388 * CVS:   reviewed your changes, include their name(s) here.
389 * CVS:   If you have not had it reviewed then delete this line.
390 *
391 * Revision 1.8  2006/08/15 21:44:50  mranga
392 * Issue number:
393 * Obtained from:
394 * Submitted by:  mranga
395 * Reviewed by:   mranga
396 * Incorporating the latest API changes from Phelim
397 * CVS: ----------------------------------------------------------------------
398 * CVS: Issue number:
399 * CVS:   If this change addresses one or more issues,
400 * CVS:   then enter the issue number(s) here.
401 * CVS: Obtained from:
402 * CVS:   If this change has been taken from another system,
403 * CVS:   then name the system in this line, otherwise delete it.
404 * CVS: Submitted by:
405 * CVS:   If this code has been contributed to the project by someone else; i.e.,
406 * CVS:   they sent us a patch or a set of diffs, then include their name/email
407 * CVS:   address here. If this is your work then delete this line.
408 * CVS: Reviewed by:
409 * CVS:   If we are doing pre-commit code reviews and someone else has
410 * CVS:   reviewed your changes, include their name(s) here.
411 * CVS:   If you have not had it reviewed then delete this line.
412 *
413 * Revision 1.7  2006/07/13 09:02:06  mranga
414 * Issue number:
415 * Obtained from:
416 * Submitted by:  jeroen van bemmel
417 * Reviewed by:   mranga
418 * Moved some changes from jain-sip-1.2 to java.net
419 *
420 * CVS: ----------------------------------------------------------------------
421 * CVS: Issue number:
422 * CVS:   If this change addresses one or more issues,
423 * CVS:   then enter the issue number(s) here.
424 * CVS: Obtained from:
425 * CVS:   If this change has been taken from another system,
426 * CVS:   then name the system in this line, otherwise delete it.
427 * CVS: Submitted by:
428 * CVS:   If this code has been contributed to the project by someone else; i.e.,
429 * CVS:   they sent us a patch or a set of diffs, then include their name/email
430 * CVS:   address here. If this is your work then delete this line.
431 * CVS: Reviewed by:
432 * CVS:   If we are doing pre-commit code reviews and someone else has
433 * CVS:   reviewed your changes, include their name(s) here.
434 * CVS:   If you have not had it reviewed then delete this line.
435 *
436 * Revision 1.5  2006/06/19 06:47:27  mranga
437 * javadoc fixups
438 *
439 * Revision 1.4  2006/06/16 15:26:28  mranga
440 * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak
441 *
442 * Revision 1.3  2005/10/27 20:49:00  jeroen
443 * added support for RFC3903 PUBLISH
444 *
445 * Revision 1.2  2005/10/14 19:59:00  jeroen
446 * bugfix: missing parser for shortform of Subject (s)
447 *
448 * Revision 1.1.1.1  2005/10/04 17:12:35  mranga
449 *
450 * Import
451 *
452 *
453 * Revision 1.4  2005/04/04 09:29:03  dmuresan
454 * Replaced new String().getClass() with String.class.
455 *
456 * Revision 1.3  2004/01/22 13:26:31  sverker
457 * Issue number:
458 * Obtained from:
459 * Submitted by:  sverker
460 * Reviewed by:   mranga
461 *
462 * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags.
463 *
464 * CVS: ----------------------------------------------------------------------
465 * CVS: Issue number:
466 * CVS:   If this change addresses one or more issues,
467 * CVS:   then enter the issue number(s) here.
468 * CVS: Obtained from:
469 * CVS:   If this change has been taken from another system,
470 * CVS:   then name the system in this line, otherwise delete it.
471 * CVS: Submitted by:
472 * CVS:   If this code has been contributed to the project by someone else; i.e.,
473 * CVS:   they sent us a patch or a set of diffs, then include their name/email
474 * CVS:   address here. If this is your work then delete this line.
475 * CVS: Reviewed by:
476 * CVS:   If we are doing pre-commit code reviews and someone else has
477 * CVS:   reviewed your changes, include their name(s) here.
478 * CVS:   If you have not had it reviewed then delete this line.
479 *
480 */
481