home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 25 / CDROM25.iso / Share / prog / VJ11 / VJTRIAL.EXE / IE30Java.exe / classd.exe / sun / net / www / MessageHeader.java < prev    next >
Encoding:
Java Source  |  1997-01-27  |  6.5 KB  |  248 lines

  1. /*
  2.  * @(#)MessageHeader.java    1.9 95/12/05 James Gosling, Jonathan Payne
  3.  * 
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for NON-COMMERCIAL purposes and without fee is hereby
  8.  * granted provided that this copyright notice appears in all copies. Please
  9.  * refer to the file "copyright.html" for further important copyright and
  10.  * licensing information.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
  15.  * OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
  16.  * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
  17.  * ITS DERIVATIVES.
  18.  */
  19.  
  20. /*-
  21.  *    news stream opener
  22.  */
  23.  
  24. package sun.net.www;
  25.  
  26. import java.io.InputStream;
  27. import java.io.PrintStream;
  28.  
  29. /** An RFC 844 or MIME message header.  Includes methods
  30.     for parsing headers from incoming streams, fetching
  31.     values, setting values, and printing headers.
  32.     Key values of null are legal: they indicate lines in
  33.     the header that don't have a valid key, but do have
  34.     a value (this isn't legal according to the standard,
  35.     but lines like this are everywhere). */
  36. public
  37. class MessageHeader {
  38.     private String keys[];
  39.     private String values[];
  40.     private int nkeys;
  41.  
  42.     public MessageHeader () {
  43.     }
  44.  
  45.     public MessageHeader (InputStream is) throws java.io.IOException {
  46.     parseHeader(is);
  47.     }
  48.  
  49.     /**
  50.      * Find the value that corresponds to this key.
  51.      * It finds only the first occurrence of the key.
  52.      * @param k the key to find.
  53.      * @return null if not found.
  54.      */
  55.     public String findValue(String k) {
  56.     if (k == null) {
  57.         for (int i = nkeys; --i >= 0;)
  58.         if (keys[i] == null)
  59.             return values[i];
  60.     } else
  61.         for (int i = nkeys; --i >= 0;)
  62.         if (k.equalsIgnoreCase(keys[i]))
  63.             return values[i];
  64.     return null;
  65.     }
  66.  
  67.     public String getKey(int n) {
  68.     if (n < 0 || n >= nkeys) return null;
  69.     String k = keys[n];
  70.     return k == null ? "NULLKEY" : k;
  71.     }
  72.  
  73.     public String getValue(int n) {
  74.     if (n < 0 || n >= nkeys) return null;
  75.     return values[n];
  76.     }
  77.  
  78.     /** Find the next value that corresponds to this key.
  79.      *    It finds the first value that follows v. To iterate
  80.      *    over all the values of a key use:
  81.      *    <pre>
  82.      *        for(String v=h.findValue(k); v!=null; v=h.findNextValue(k, v)) {
  83.      *            ...
  84.      *        }
  85.      *    </pre>
  86.      */
  87.     public String findNextValue(String k, String v) {
  88.     boolean foundV = false;
  89.     if (k == null) {
  90.         for (int i = nkeys; --i >= 0;)
  91.         if (keys[i] == null)
  92.             if (foundV)
  93.             return values[i];
  94.             else if (values[i] == v)
  95.             foundV = true;
  96.     } else
  97.         for (int i = nkeys; --i >= 0;)
  98.         if (k.equalsIgnoreCase(keys[i]))
  99.             if (foundV)
  100.             return values[i];
  101.             else if (values[i] == v)
  102.             foundV = true;
  103.     return null;
  104.     }
  105.  
  106.     /** Prints the key-value pairs represented by this
  107.     header.  Also prints the RFC required blank line
  108.     at the end. Omits pairs with a null key. */
  109.     public void print(PrintStream p) {
  110.     for (int i = 0; i < nkeys; i++)
  111.         if (keys[i] != null)
  112.         p.print(keys[i] + ": " + values[i] + "\n");
  113.     p.print("\n");
  114.     }
  115.  
  116.     /** Adds a key value pair to the end of the
  117.     header.  Duplicates are allowed */
  118.     public void add(String k, String v) {
  119.     if (keys == null || nkeys >= keys.length) {
  120.         String nk[] = new String[nkeys + 4];
  121.         String nv[] = new String[nkeys + 4];
  122.         if (keys != null)
  123.         System.arraycopy(keys, 0, nk, 0, nkeys);
  124.         if (values != null)
  125.         System.arraycopy(values, 0, nv, 0, nkeys);
  126.         keys = nk;
  127.         values = nv;
  128.     }
  129.     keys[nkeys] = k;
  130.     values[nkeys] = v;
  131.     nkeys++;
  132.     }
  133.  
  134.     /** Sets the value of a key.  If the key already
  135.     exists in the header, it's value will be
  136.     changed.  Otherwise a new key/value pair will
  137.     be added to the end of the header. */
  138.     public void set(String k, String v) {
  139.     for (int i = nkeys; --i >= 0;)
  140.         if (k.equalsIgnoreCase(keys[i])) {
  141.         values[i] = v;
  142.         return;
  143.         }
  144.     add(k, v);
  145.     }
  146.  
  147.     /** Convert a message-id string to canonical form (strips off
  148.     leading and trailing <>s) */
  149.     public String canonicalID(String id) {
  150.     if (id == null)
  151.         return "";
  152.     int st = 0;
  153.     int len = id.length();
  154.     boolean substr = false;
  155.     int c;
  156.     while (st < len && ((c = id.charAt(st)) == '<' ||
  157.                 c <= ' ')) {
  158.         st++;
  159.         substr = true;
  160.     }
  161.     while (st < len && ((c = id.charAt(len - 1)) == '>' ||
  162.                 c <= ' ')) {
  163.         len--;
  164.         substr = true;
  165.     }
  166.     return substr ? id.substring(st, len) : id;
  167.     }
  168.  
  169.     /** Parse a MIME header from an input stream. */
  170.     public void parseHeader(InputStream is) throws java.io.IOException {
  171.     nkeys = 0;
  172.     if (is == null)
  173.         return;
  174.     char s[] = new char[10];
  175.     int firstc = is.read();
  176.     while (firstc != '\n' && firstc != '\r' && firstc >= 0) {
  177.         int len = 0;
  178.         int keyend = -1;
  179.         int c;
  180.         boolean inKey = firstc > ' ';
  181.         s[len++] = (char) firstc;
  182.     parseloop:{
  183.         while ((c = is.read()) >= 0) {
  184.             switch (c) {
  185.               case ':':
  186.             if (inKey && len > 0)
  187.                 keyend = len;
  188.             inKey = false;
  189.             break;
  190.               case '\t':
  191.             c = ' ';
  192.               case ' ':
  193.             inKey = false;
  194.             break;
  195.               case '\r':
  196.               case '\n':
  197.             firstc = is.read();
  198.             if (c == '\r' && firstc == '\n') {
  199.                 firstc = is.read();
  200.                 if (firstc == '\r')
  201.                 firstc = is.read();
  202.             }
  203.             if (firstc == '\n' || firstc == '\r' || firstc > ' ')
  204.                 break parseloop;
  205.             /* continuation */
  206.             c = ' ';
  207.             break;
  208.             }
  209.             if (len >= s.length) {
  210.             char ns[] = new char[s.length * 2];
  211.             System.arraycopy(s, 0, ns, 0, len);
  212.             s = ns;
  213.             }
  214.             s[len++] = (char) c;
  215.         }
  216.         firstc = -1;
  217.         }
  218.         while (len > 0 && s[len - 1] <= ' ')
  219.         len--;
  220.         String k;
  221.         if (keyend <= 0) {
  222.         k = null;
  223.         keyend = 0;
  224.         } else {
  225.         k = String.copyValueOf(s, 0, keyend);
  226.         if (keyend < len && s[keyend] == ':')
  227.             keyend++;
  228.         while (keyend < len && s[keyend] <= ' ')
  229.             keyend++;
  230.         }
  231.         String v;
  232.         if (keyend >= len)
  233.         v = new String();
  234.         else
  235.         v = String.copyValueOf(s, keyend, len - keyend);
  236.         add(k, v);
  237.     }
  238.     }
  239.  
  240.     public String toString() {
  241.     String result = super.toString();
  242.     for (int i = 0; i < keys.length; i++) {
  243.         result += "{"+keys[i]+": "+values[i]+"}";
  244.     }
  245.     return result;
  246.     }
  247. }
  248.