KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mx4j > tools > adaptor > http > HttpInputStream


1 /*
2
3  * Copyright (C) The MX4J Contributors.
4
5  * All rights reserved.
6
7  *
8
9  * This software is distributed under the terms of the MX4J License version 1.0.
10
11  * See the terms of the MX4J License in the documentation provided with this software.
12
13  */

14
15 package mx4j.tools.adaptor.http;
16
17
18 import java.io.BufferedInputStream JavaDoc;
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.net.URLDecoder JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.NoSuchElementException JavaDoc;
25 import java.util.StringTokenizer JavaDoc;
26
27
28 /**
29  * HttpInputStream processes an HTTP request
30  *
31  * @version $Revision: 1.3 $
32  */

33
34 public class HttpInputStream extends BufferedInputStream JavaDoc
35
36 {
37
38
39    /**
40     * Http method. only GET, POST implemented
41     */

42
43    private String JavaDoc method;
44
45
46    /**
47     * Path of the request
48     */

49
50    private String JavaDoc path;
51
52
53    /**
54     * Query string
55     */

56
57    private String JavaDoc queryString;
58
59
60    /**
61     * Request version
62     */

63
64    private float version;
65
66
67    /**
68     * Current headers
69     */

70
71    private Map JavaDoc headers = new HashMap JavaDoc();
72
73
74    private Map JavaDoc variables = new HashMap JavaDoc();
75
76
77    /**
78     * Constructs a new HttpInputStream
79     *
80     * @param in InputStream
81     */

82
83    public HttpInputStream(InputStream JavaDoc in)
84
85    {
86
87       super(in);
88
89    }
90
91
92    /**
93     * Returns the method of the request
94     *
95     * @return the method of the request GET/POST
96     */

97
98    public String JavaDoc getMethod()
99
100    {
101
102       return method;
103
104    }
105
106
107    /**
108     * Returns the path of the request
109     *
110     * @return the path of the request
111     */

112
113    public String JavaDoc getPath()
114
115    {
116
117       return path;
118
119    }
120
121
122    /**
123     * Returns the query string
124     *
125     * @return The queryString value
126     */

127
128    public String JavaDoc getQueryString()
129
130    {
131
132       return queryString;
133
134    }
135
136
137    /**
138     * Returns the version of the request
139     *
140     * @return The version value 1.0/1.1
141     */

142
143    public float getVersion()
144
145    {
146
147       return version;
148
149    }
150
151
152    /**
153     * Returns a given header by name, assumes lower case
154     *
155     * @param name Name of the header
156     * @return The header value
157     */

158
159    public String JavaDoc getHeader(String JavaDoc name)
160
161    {
162
163       return (String JavaDoc)headers.get(name);
164
165    }
166
167
168    /**
169     * Returns a given header by name, assumes lower case
170     *
171     * @param name Name of the header
172     * @return The header value
173     */

174
175    public Map JavaDoc getHeaders()
176
177    {
178
179       return headers;
180
181    }
182
183
184    /**
185     * Reads the request parsing the headers
186     *
187     * @throws IOException Description of Exception
188     */

189
190    public void readRequest() throws IOException JavaDoc
191
192    {
193
194       String JavaDoc request = readLine();
195
196       if (request == null)
197
198       {
199
200          throw new HttpException(HttpConstants.STATUS_BAD_REQUEST, "Null query");
201
202       }
203
204       // Parses the request
205

206       StringTokenizer JavaDoc parts = new StringTokenizer JavaDoc(request);
207
208       try
209
210       {
211
212          parseMethod(parts.nextToken());
213
214          parseRequest(parts.nextToken());
215
216       }
217
218       catch (NoSuchElementException JavaDoc ex)
219
220       {
221
222          throw new HttpException(HttpConstants.STATUS_BAD_REQUEST, request);
223
224       }
225
226       if (parts.hasMoreTokens())
227
228       {
229
230          parseVersion(parts.nextToken());
231
232       }
233
234       else
235
236       {
237
238          version = 0.9f;
239
240       }
241
242       if (version >= 1.0f)
243
244       {
245
246          readHeaders();
247
248          parseVariables();
249
250       }
251
252    }
253
254
255    /**
256     * Reads an HTTP line
257     *
258     * @return A read line
259     * @throws IOException Emmited in case of errors reading the stream
260     */

261
262    public String JavaDoc readLine() throws IOException JavaDoc
263
264    {
265
266       StringBuffer JavaDoc line = new StringBuffer JavaDoc(64);
267
268       line.delete(0, line.length());
269
270       int c;
271
272       while (((c = read()) != -1) && (c != '\n') && (c != '\r'))
273
274       {
275
276          line.append((char)c);
277
278       }
279
280       if ((c == '\r') && ((c = read()) != '\n') && (c != -1))
281
282       {
283
284          --pos;
285
286       }
287
288       if ((c == -1) && (line.length() == 0))
289
290       {
291
292          return null;
293
294       }
295
296       else
297
298       {
299
300          return line.toString();
301
302       }
303
304    }
305
306
307    /**
308     * Returns a map with the variables passed in the request.
309     *
310     * @return A map containing variables/value pairs. If a variable is
311     * <p/>
312     * present only once in the request the value will be a String.
313     * <p/>
314     * If it is present many times the variable will be a String[]
315     */

316
317    public Map JavaDoc getVariables()
318
319    {
320
321       return variables;
322
323    }
324
325
326    /**
327     * Returns one variable value. If the variable is present many times, the first
328     * <p/>
329     * instance will be returned
330     *
331     * @return A String with the variable value
332     */

333
334    public String JavaDoc getVariable(String JavaDoc name)
335
336    {
337
338       if (variables.containsKey(name))
339
340       {
341
342          Object JavaDoc variable = variables.get(name);
343
344          if (variable instanceof String JavaDoc)
345
346          {
347
348             return (String JavaDoc)variable;
349
350          }
351
352          else if (variable instanceof String JavaDoc[])
353
354          {
355
356             return ((String JavaDoc[])variable)[0];
357
358          }
359
360       }
361
362       return null;
363
364    }
365
366
367    /**
368     * Returns one variable values.
369     *
370     * @return A String array with all variable instances
371     */

372
373    public String JavaDoc[] getVariableValues(String JavaDoc name)
374
375    {
376
377       if (variables.containsKey(name))
378
379       {
380
381          Object JavaDoc variable = variables.get(name);
382
383          if (variable instanceof String JavaDoc[])
384
385          {
386
387             return (String JavaDoc[])variable;
388
389          }
390          else if (variable instanceof String JavaDoc)
391
392          {
393
394             String JavaDoc[] result = new String JavaDoc[1];
395
396             result[0] = (String JavaDoc)variable;
397
398             return result;
399
400          }
401
402       }
403
404       return null;
405
406    }
407
408
409    /**
410     * Parses the request parameters
411     */

412
413    protected void parseVariables() throws HttpException
414
415    {
416
417       try
418
419       {
420
421          // get request variables
422

423          String JavaDoc variableHolder = "";
424
425          if (method.equals(HttpConstants.METHOD_POST) && "application/x-www-form-urlencoded".equals(headers.get("content-type"))
426
427              && (headers.get("content-length") != null))
428
429          {
430
431             if ("chunked".equals(headers.get("transfer-encoding")))
432
433             {
434
435                throw new HttpException(HttpConstants.STATUS_BAD_REQUEST, "Sorry I don't understand chunked requests");
436
437             }
438
439             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
440
441             int size = Integer.parseInt((String JavaDoc)headers.get("content-length"));
442
443             mark(size);
444
445             for (int i = 0; i < size; i++)
446
447             {
448
449                int j = read();
450
451                if (j >= 0)
452
453                {
454
455                   buffer.append((char)j);
456
457                }
458
459                else
460
461                {
462
463                   throw new HttpException(HttpConstants.STATUS_BAD_REQUEST, "Request not understood");
464
465                }
466
467             }
468
469             variableHolder = buffer.toString();
470
471             reset();
472
473          }
474
475          else if (method.equals(HttpConstants.METHOD_GET))
476
477          {
478
479             variableHolder = getQueryString();
480
481          }
482
483          else
484
485          {
486
487             throw new HttpException(HttpConstants.STATUS_BAD_REQUEST, "Request not understood");
488
489          }
490
491          StringTokenizer JavaDoc parser = new StringTokenizer JavaDoc(variableHolder, "&");
492
493          while (parser.hasMoreTokens())
494
495          {
496
497             String JavaDoc command = parser.nextToken();
498
499             int equalIndex = command.indexOf('=');
500
501             if (equalIndex > 0)
502
503             {
504
505                String JavaDoc variableName = URLDecoder.decode(command.substring(0, equalIndex));
506
507                String JavaDoc variableValue = URLDecoder.decode(command.substring(equalIndex + 1, command.length()));
508
509                variableValue = new String JavaDoc(variableValue.getBytes(), "UTF-8");
510
511                if (variables.get(variableName) != null)
512                {
513
514                   Object JavaDoc value = variables.get(variableName);
515
516                   String JavaDoc[] newValue = null;
517
518                   if (value instanceof String JavaDoc)
519
520                   {
521
522                      newValue = new String JavaDoc[2];
523
524                      newValue[0] = variableValue;
525
526                      newValue[1] = (String JavaDoc)value;
527
528                   }
529
530                   else
531
532                   {
533
534                      String JavaDoc[] oldValue = (String JavaDoc[])value;
535
536                      newValue = new String JavaDoc[oldValue.length + 1];
537
538                      System.arraycopy(oldValue, 0, newValue, 1, oldValue.length);
539
540                      newValue[0] = variableValue;
541
542                   }
543
544                   variables.put(variableName, newValue);
545
546                }
547
548                else
549
550                {
551
552                   variables.put(variableName, variableValue);
553
554                }
555
556             }
557
558          }
559
560       }
561
562       catch (Exception JavaDoc e)
563
564       {
565
566          throw new HttpException(HttpConstants.STATUS_BAD_REQUEST, getQueryString());
567
568       }
569
570    }
571
572
573    /**
574     * Parses the connection method. GET/POST are allowed
575     *
576     * @param method Description of Parameter
577     * @throws HttpException Description of Exception
578     */

579
580    protected void parseMethod(String JavaDoc method) throws HttpException
581
582    {
583
584       if (method.equals(HttpConstants.METHOD_GET))
585
586       {
587
588          this.method = HttpConstants.METHOD_GET;
589
590       }
591
592       else if (method.equals(HttpConstants.METHOD_POST))
593
594       {
595
596          this.method = HttpConstants.METHOD_POST;
597
598       }
599
600       else
601
602       {
603
604          throw new HttpException(HttpConstants.STATUS_NOT_IMPLEMENTED, method);
605
606       }
607
608    }
609
610
611    /**
612     * Parses the request
613     *
614     * @param request Request string
615     * @throws HttpException Thrown if an error ocurr
616     */

617
618    protected void parseRequest(String JavaDoc request) throws HttpException
619
620    {
621
622       if (!request.startsWith("/"))
623
624       {
625
626          throw new HttpException(HttpConstants.STATUS_BAD_REQUEST, request);
627
628       }
629
630       int queryIdx = request.indexOf('?');
631
632       if (queryIdx == -1)
633
634       {
635
636          path = HttpUtil.canonicalizePath(request);
637
638          queryString = "";
639
640       }
641
642       else
643
644       {
645
646          path = HttpUtil.canonicalizePath(request.substring(0, queryIdx));
647
648          queryString = request.substring(queryIdx + 1);
649
650       }
651
652    }
653
654
655    /**
656     * Parses the request HttpConstants version
657     *
658     * @param verStr String containing the HTTP version
659     * @throws HttpException
660     */

661
662    protected void parseVersion(String JavaDoc verStr) throws HttpException
663
664    {
665
666       if (!verStr.startsWith("HTTP/"))
667
668       {
669
670          throw new HttpException(HttpConstants.STATUS_BAD_REQUEST, verStr);
671
672       }
673
674       try
675
676       {
677
678          version = Float.valueOf(verStr.substring(5)).floatValue();
679
680       }
681
682       catch (NumberFormatException JavaDoc ex)
683
684       {
685
686          throw new HttpException(HttpConstants.STATUS_BAD_REQUEST, verStr);
687
688       }
689
690    }
691
692
693    /**
694     * Reads the headers
695     *
696     * @throws IOException
697     */

698
699    protected void readHeaders() throws IOException JavaDoc
700
701    {
702
703       String JavaDoc header;
704
705       while (((header = readLine()) != null) && !header.equals(""))
706
707       {
708
709          int colonIdx = header.indexOf(':');
710
711          if (colonIdx != -1)
712
713          {
714
715             String JavaDoc name = header.substring(0, colonIdx);
716
717             String JavaDoc value = header.substring(colonIdx + 1);
718
719             headers.put(name.toLowerCase(), value.trim());
720
721          }
722
723       }
724
725    }
726
727 }
728
729
Popular Tags