home *** CD-ROM | disk | FTP | other *** search
Java Source | 1997-09-10 | 6.2 KB | 268 lines |
- /*-
- * news stream opener
- */
-
- package sun.beanbox;
-
- import java.io.InputStream;
- import java.io.PrintWriter;
-
- /** An RFC 844 or MIME message header. Includes methods
- for parsing headers from incoming streams, fetching
- values, setting values, and printing headers.
- Key values of null are legal: they indicate lines in
- the header that don't have a valid key, but do have
- a value (this isn't legal according to the standard,
- but lines like this are everywhere). */
- public
- class MessageHeader {
- private String keys[];
- private String values[];
- private int nkeys;
-
- public MessageHeader () {
- grow();
- }
-
- public MessageHeader (InputStream is) throws java.io.IOException {
- parseHeader(is);
- }
-
- /**
- * Find the value that corresponds to this key.
- * It finds only the first occurrence of the key.
- * @param k the key to find.
- * @return null if not found.
- */
- public String findValue(String k) {
- if (k == null) {
- for (int i = nkeys; --i >= 0;)
- if (keys[i] == null)
- return values[i];
- } else
- for (int i = nkeys; --i >= 0;) {
- if (k.equalsIgnoreCase(keys[i]))
- return values[i];
- }
- return null;
- }
-
- public String getKey(int n) {
- if (n < 0 || n >= nkeys) return null;
- return keys[n];
- }
-
- public String getValue(int n) {
- if (n < 0 || n >= nkeys) return null;
- return values[n];
- }
-
- /** Find the next value that corresponds to this key.
- * It finds the first value that follows v. To iterate
- * over all the values of a key use:
- * <pre>
- * for(String v=h.findValue(k); v!=null; v=h.findNextValue(k, v)) {
- * ...
- * }
- * </pre>
- */
- public String findNextValue(String k, String v) {
- boolean foundV = false;
- if (k == null) {
- for (int i = nkeys; --i >= 0;)
- if (keys[i] == null)
- if (foundV)
- return values[i];
- else if (values[i] == v)
- foundV = true;
- } else
- for (int i = nkeys; --i >= 0;)
- if (k.equalsIgnoreCase(keys[i]))
- if (foundV)
- return values[i];
- else if (values[i] == v)
- foundV = true;
- return null;
- }
-
- /** Prints the key-value pairs represented by this
- header. Also prints the RFC required blank line
- at the end. Omits pairs with a null key. */
- public void print(PrintWriter p) {
- for (int i = 0; i < nkeys; i++)
- if (keys[i] != null)
- p.print(keys[i] +
- (values[i] != null ? ": "+values[i]: "") + "\r\n");
- p.print("\r\n");
- p.flush();
- }
-
- /** Adds a key value pair to the end of the
- header. Duplicates are allowed */
- public void add(String k, String v) {
- grow();
- keys[nkeys] = k;
- values[nkeys] = v;
- nkeys++;
- }
-
- /** Prepends a key value pair to the beginning of the
- header. Duplicates are allowed */
- public void prepend(String k, String v) {
- grow();
- for (int i = nkeys; i > 0; i--) {
- keys[i] = keys[i-1];
- values[i] = values[i-1];
- }
- keys[0] = k;
- values[0] = v;
- nkeys++;
- }
-
- /** Overwrite the previous key/val pair at location 'i'
- * with the new k/v. If the index didn't exist before
- * the key/val is simply tacked onto the end.
- */
-
- public void set(int i, String k, String v) {
- grow();
- if (i < 0) {
- return;
- } else if (i > nkeys) {
- add(k, v);
- } else {
- keys[i] = k;
- values[i] = v;
- }
- }
-
-
- /** grow the key/value arrays as needed */
-
- private void grow() {
- if (keys == null || nkeys >= keys.length) {
- String[] nk = new String[nkeys + 4];
- String[] nv = new String[nkeys + 4];
- if (keys != null)
- System.arraycopy(keys, 0, nk, 0, nkeys);
- if (values != null)
- System.arraycopy(values, 0, nv, 0, nkeys);
- keys = nk;
- values = nv;
- }
- }
-
- /** Sets the value of a key. If the key already
- exists in the header, it's value will be
- changed. Otherwise a new key/value pair will
- be added to the end of the header. */
- public void set(String k, String v) {
- for (int i = nkeys; --i >= 0;)
- if (k.equalsIgnoreCase(keys[i])) {
- values[i] = v;
- return;
- }
- add(k, v);
- }
-
- /** Convert a message-id string to canonical form (strips off
- leading and trailing <>s) */
- public static String canonicalID(String id) {
- if (id == null)
- return "";
- int st = 0;
- int len = id.length();
- boolean substr = false;
- int c;
- while (st < len && ((c = id.charAt(st)) == '<' ||
- c <= ' ')) {
- st++;
- substr = true;
- }
- while (st < len && ((c = id.charAt(len - 1)) == '>' ||
- c <= ' ')) {
- len--;
- substr = true;
- }
- return substr ? id.substring(st, len) : id;
- }
-
- /** Parse a MIME header from an input stream. */
- public void parseHeader(InputStream is) throws java.io.IOException {
- nkeys = 0;
- if (is == null)
- return;
- char s[] = new char[10];
- int firstc = is.read();
- while (firstc != '\n' && firstc != '\r' && firstc >= 0) {
- int len = 0;
- int keyend = -1;
- int c;
- boolean inKey = firstc > ' ';
- s[len++] = (char) firstc;
- parseloop:{
- parseloop2: while ((c = is.read()) >= 0) {
- switch (c) {
- case ':':
- if (inKey && len > 0)
- keyend = len;
- inKey = false;
- break;
- case '\t':
- c = ' ';
- case ' ':
- inKey = false;
- break;
- case '\r':
- case '\n':
- firstc = is.read();
- if (c == '\r' && firstc == '\n') {
- firstc = is.read();
- if (firstc == '\r')
- firstc = is.read();
- }
- if (firstc == '\n' || firstc == '\r' || firstc > ' ')
- break parseloop;
- /* continuation */
- continue parseloop2;
- }
- if (len >= s.length) {
- char ns[] = new char[s.length * 2];
- System.arraycopy(s, 0, ns, 0, len);
- s = ns;
- }
- s[len++] = (char) c;
- }
- firstc = -1;
- }
- while (len > 0 && s[len - 1] <= ' ')
- len--;
- String k;
- if (keyend <= 0) {
- k = null;
- keyend = 0;
- } else {
- k = String.copyValueOf(s, 0, keyend);
- if (keyend < len && s[keyend] == ':')
- keyend++;
- while (keyend < len && s[keyend] <= ' ')
- keyend++;
- }
- String v;
- if (keyend >= len)
- v = new String();
- else
- v = String.copyValueOf(s, keyend, len - keyend);
- add(k, v);
- }
- }
-
- public String toString() {
- String result = super.toString();
- for (int i = 0; i < keys.length; i++) {
- result += "{"+keys[i]+": "+values[i]+"}";
- }
- return result;
- }
- }
-