home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 July / Chip_1998-07_cd.bin / zkuste / JBuilder / BDK / Win / bdk_sep97.exe / _SETUP.1 / MessageHeader.java < prev    next >
Encoding:
Java Source  |  1997-09-10  |  6.2 KB  |  268 lines

  1. /*-
  2.  *    news stream opener
  3.  */
  4.  
  5. package sun.beanbox;
  6.  
  7. import java.io.InputStream;
  8. import java.io.PrintWriter;
  9.  
  10. /** An RFC 844 or MIME message header.  Includes methods
  11.     for parsing headers from incoming streams, fetching
  12.     values, setting values, and printing headers.
  13.     Key values of null are legal: they indicate lines in
  14.     the header that don't have a valid key, but do have
  15.     a value (this isn't legal according to the standard,
  16.     but lines like this are everywhere). */
  17. public
  18. class MessageHeader {
  19.     private String keys[];
  20.     private String values[];
  21.     private int nkeys;
  22.  
  23.     public MessageHeader () {
  24.     grow();
  25.     }
  26.  
  27.     public MessageHeader (InputStream is) throws java.io.IOException {
  28.     parseHeader(is);
  29.     }
  30.  
  31.     /**
  32.      * Find the value that corresponds to this key.
  33.      * It finds only the first occurrence of the key.
  34.      * @param k the key to find.
  35.      * @return null if not found.
  36.      */
  37.     public String findValue(String k) {
  38.     if (k == null) {
  39.         for (int i = nkeys; --i >= 0;)
  40.         if (keys[i] == null)
  41.             return values[i];
  42.     } else
  43.         for (int i = nkeys; --i >= 0;) {
  44.         if (k.equalsIgnoreCase(keys[i]))
  45.             return values[i];
  46.         }
  47.     return null;
  48.     }
  49.  
  50.     public String getKey(int n) {
  51.     if (n < 0 || n >= nkeys) return null;
  52.     return keys[n];
  53.     }
  54.  
  55.     public String getValue(int n) {
  56.     if (n < 0 || n >= nkeys) return null;
  57.     return values[n];
  58.     }
  59.  
  60.     /** Find the next value that corresponds to this key.
  61.      *    It finds the first value that follows v. To iterate
  62.      *    over all the values of a key use:
  63.      *    <pre>
  64.      *        for(String v=h.findValue(k); v!=null; v=h.findNextValue(k, v)) {
  65.      *            ...
  66.      *        }
  67.      *    </pre>
  68.      */
  69.     public String findNextValue(String k, String v) {
  70.     boolean foundV = false;
  71.     if (k == null) {
  72.         for (int i = nkeys; --i >= 0;)
  73.         if (keys[i] == null)
  74.             if (foundV)
  75.             return values[i];
  76.             else if (values[i] == v)
  77.             foundV = true;
  78.     } else
  79.         for (int i = nkeys; --i >= 0;)
  80.         if (k.equalsIgnoreCase(keys[i]))
  81.             if (foundV)
  82.             return values[i];
  83.             else if (values[i] == v)
  84.             foundV = true;
  85.     return null;
  86.     }
  87.  
  88.     /** Prints the key-value pairs represented by this
  89.     header.  Also prints the RFC required blank line
  90.     at the end. Omits pairs with a null key. */
  91.     public void print(PrintWriter p) {
  92.     for (int i = 0; i < nkeys; i++)
  93.         if (keys[i] != null)
  94.         p.print(keys[i] + 
  95.             (values[i] != null ? ": "+values[i]: "") + "\r\n");
  96.     p.print("\r\n");
  97.     p.flush();
  98.     }
  99.  
  100.     /** Adds a key value pair to the end of the
  101.     header.  Duplicates are allowed */
  102.     public void add(String k, String v) {
  103.     grow();
  104.     keys[nkeys] = k;
  105.     values[nkeys] = v;
  106.     nkeys++;
  107.     }
  108.  
  109.     /** Prepends a key value pair to the beginning of the
  110.     header.  Duplicates are allowed */
  111.     public void prepend(String k, String v) {
  112.     grow();
  113.     for (int i = nkeys; i > 0; i--) {
  114.         keys[i] = keys[i-1];
  115.         values[i] = values[i-1];
  116.     }
  117.     keys[0] = k;
  118.     values[0] = v;
  119.     nkeys++;
  120.     }
  121.  
  122.     /** Overwrite the previous key/val pair at location 'i'
  123.      * with the new k/v.  If the index didn't exist before
  124.      * the key/val is simply tacked onto the end.
  125.      */
  126.  
  127.     public void set(int i, String k, String v) {
  128.     grow();
  129.     if (i < 0) {
  130.         return;
  131.     } else if (i > nkeys) {
  132.         add(k, v);
  133.     } else {
  134.         keys[i] = k;
  135.         values[i] = v;
  136.     }
  137.     }
  138.         
  139.  
  140.     /** grow the key/value arrays as needed */
  141.  
  142.     private void grow() {
  143.     if (keys == null || nkeys >= keys.length) {
  144.         String[] nk = new String[nkeys + 4];
  145.         String[] nv = new String[nkeys + 4];
  146.         if (keys != null)
  147.         System.arraycopy(keys, 0, nk, 0, nkeys);
  148.         if (values != null)
  149.         System.arraycopy(values, 0, nv, 0, nkeys);
  150.         keys = nk;
  151.         values = nv;
  152.     }
  153.     }
  154.  
  155.     /** Sets the value of a key.  If the key already
  156.     exists in the header, it's value will be
  157.     changed.  Otherwise a new key/value pair will
  158.     be added to the end of the header. */
  159.     public void set(String k, String v) {
  160.     for (int i = nkeys; --i >= 0;)
  161.         if (k.equalsIgnoreCase(keys[i])) {
  162.         values[i] = v;
  163.         return;
  164.         }
  165.     add(k, v);
  166.     }
  167.  
  168.     /** Convert a message-id string to canonical form (strips off
  169.     leading and trailing <>s) */
  170.     public static String canonicalID(String id) {
  171.     if (id == null)
  172.         return "";
  173.     int st = 0;
  174.     int len = id.length();
  175.     boolean substr = false;
  176.     int c;
  177.     while (st < len && ((c = id.charAt(st)) == '<' ||
  178.                 c <= ' ')) {
  179.         st++;
  180.         substr = true;
  181.     }
  182.     while (st < len && ((c = id.charAt(len - 1)) == '>' ||
  183.                 c <= ' ')) {
  184.         len--;
  185.         substr = true;
  186.     }
  187.     return substr ? id.substring(st, len) : id;
  188.     }
  189.  
  190.     /** Parse a MIME header from an input stream. */
  191.     public void parseHeader(InputStream is) throws java.io.IOException {
  192.     nkeys = 0;
  193.     if (is == null)
  194.         return;
  195.     char s[] = new char[10];
  196.     int firstc = is.read();
  197.     while (firstc != '\n' && firstc != '\r' && firstc >= 0) {
  198.         int len = 0;
  199.         int keyend = -1;
  200.         int c;
  201.         boolean inKey = firstc > ' ';
  202.         s[len++] = (char) firstc;
  203.     parseloop:{
  204.     parseloop2:    while ((c = is.read()) >= 0) {
  205.             switch (c) {
  206.               case ':':
  207.             if (inKey && len > 0)
  208.                 keyend = len;
  209.             inKey = false;
  210.             break;
  211.               case '\t':
  212.             c = ' ';
  213.               case ' ':
  214.             inKey = false;
  215.             break;
  216.               case '\r':
  217.               case '\n':
  218.             firstc = is.read();
  219.             if (c == '\r' && firstc == '\n') {
  220.                 firstc = is.read();
  221.                 if (firstc == '\r')
  222.                 firstc = is.read();
  223.             }
  224.             if (firstc == '\n' || firstc == '\r' || firstc > ' ')
  225.                 break parseloop;
  226.             /* continuation */
  227.             continue parseloop2;
  228.             }
  229.             if (len >= s.length) {
  230.             char ns[] = new char[s.length * 2];
  231.             System.arraycopy(s, 0, ns, 0, len);
  232.             s = ns;
  233.             }
  234.             s[len++] = (char) c;
  235.         }
  236.         firstc = -1;
  237.         }
  238.         while (len > 0 && s[len - 1] <= ' ')
  239.         len--;
  240.         String k;
  241.         if (keyend <= 0) {
  242.         k = null;
  243.         keyend = 0;
  244.         } else {
  245.         k = String.copyValueOf(s, 0, keyend);
  246.         if (keyend < len && s[keyend] == ':')
  247.             keyend++;
  248.         while (keyend < len && s[keyend] <= ' ')
  249.             keyend++;
  250.         }
  251.         String v;
  252.         if (keyend >= len)
  253.         v = new String();
  254.         else
  255.         v = String.copyValueOf(s, keyend, len - keyend);
  256.         add(k, v);
  257.     }
  258.     }
  259.  
  260.     public String toString() {
  261.     String result = super.toString();
  262.     for (int i = 0; i < keys.length; i++) {
  263.         result += "{"+keys[i]+": "+values[i]+"}";
  264.     }
  265.     return result;
  266.     }
  267. }
  268.