All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.mail.internet.InternetHeaders Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package javax.mail.internet;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.mail.Address;
import javax.mail.Header;
import javax.mail.MessagingException;

/**
 * Class that represents the RFC822 headers associated with a message.
 *
 * @version $Rev: 467553 $ $Date: 2006-10-24 21:01:51 -0700 (Tue, 24 Oct 2006) $
 */
public class InternetHeaders {
    // RFC822 imposes an ordering on its headers so we use a LinkedHashedMap
    private final LinkedHashMap headers = new LinkedHashMap();

    private transient String lastHeaderName;

    /**
     * Create an empty InternetHeaders
     */
    public InternetHeaders() {
        // we need to initialize the headers in the correct order
        // fields: dates source destination optional-field
        // dates:
        setHeaderList("Date", null);
        setHeaderList("Resent-Date", null);
        // source: trace originator resent
        // trace: return received
        setHeaderList("Return-path", null);
        setHeaderList("Received", null);
        // originator: authentic reply-to
        setHeaderList("Sender", null);
        setHeaderList("From", null);
        setHeaderList("Reply-To", null);
        // resent: resent-authentic resent-reply-to
        setHeaderList("Resent-Sender", null);
        setHeaderList("Resent-From", null);
        setHeaderList("Resent-Reply-To", null);
        // destination:
        setHeaderList("To", null);
        setHeaderList("Resent-To", null);
        setHeaderList("cc", null);
        setHeaderList("Resent-cc", null);
        setHeaderList("bcc", null);
        setHeaderList("Resent-bcc", null);
        // optional-field:
        setHeaderList("Message-ID", null);
        setHeaderList("Resent-Message-ID", null);
        setHeaderList("In-Reply-To", null);
        setHeaderList("References", null);
        setHeaderList("Keywords", null);
        setHeaderList("Subject", null);
        setHeaderList("Comments", null);
        setHeaderList("Encrypted", null);
    }

    /**
     * Create a new InternetHeaders initialized by reading headers from the
     * stream.
     *
     * @param in
     *            the RFC822 input stream to load from
     * @throws MessagingException
     *             if there is a problem pasring the stream
     */
    public InternetHeaders(InputStream in) throws MessagingException {
        load(in);
    }

    /**
     * Read and parse the supplied stream and add all headers to the current
     * set.
     *
     * @param in
     *            the RFC822 input stream to load from
     * @throws MessagingException
     *             if there is a problem pasring the stream
     */
    public void load(InputStream in) throws MessagingException {
        try {
            StringBuffer name = new StringBuffer(32);
            StringBuffer value = new StringBuffer(128);
            done: while (true) {
                int c = in.read();
                char ch = (char) c;
                if (c == -1) {
                    break;
                } else if (c == 13) {
                    // empty line terminates header
                    in.read(); // skip LF
                    break;
                } else if (Character.isWhitespace(ch)) {
                    // handle continuation
                    do {
                        c = in.read();
                        if (c == -1) {
                            break done;
                        }
                        ch = (char) c;
                    } while (Character.isWhitespace(ch));
                } else {
                    // new header
                    if (name.length() > 0) {
                        addHeader(name.toString().trim(), value.toString().trim());
                    }
                    name.setLength(0);
                    value.setLength(0);
                    while (true) {
                        name.append((char) c);
                        c = in.read();
                        if (c == -1) {
                            break done;
                        } else if (c == ':') {
                            break;
                        }
                    }
                    c = in.read();
                    if (c == -1) {
                        break done;
                    }
                }

                while (c != 13) {
                    ch = (char) c;
                    value.append(ch);
                    c = in.read();
                    if (c == -1) {
                        break done;
                    }
                }
                // skip LF
                c = in.read();
                if (c == -1) {
                    break;
                }
            }
            if (name.length() > 0) {
                addHeader(name.toString().trim(), value.toString().trim());
            }
        } catch (IOException e) {
            throw new MessagingException("Error loading headers", e);
        }
    }

    /**
     * Return all the values for the specified header.
     *
     * @param name
     *            the header to return
     * @return the values for that header, or null if the header is not present
     */
    public String[] getHeader(String name) {
        List headers = getHeaderList(name);
        if (headers == null) {
            return null;
        } else {
            String[] result = new String[headers.size()];
            for (int i = 0; i < headers.size(); i++) {
                InternetHeader header = (InternetHeader) headers.get(i);
                result[i] = header.getValue();
            }
            return result;
        }
    }

    /**
     * Return the values for the specified header as a single String. If the
     * header has more than one value then all values are concatenated together
     * separated by the supplied delimiter.
     *
     * @param name
     *            the header to return
     * @param delimiter
     *            the delimiter used in concatenation
     * @return the header as a single String
     */
    public String getHeader(String name, String delimiter) {
        List list = getHeaderList(name);
        if (list == null) {
            return null;
        } else if (list.isEmpty()) {
            return "";
        } else if (list.size() == 1 || delimiter == null) {
            return ((InternetHeader) list.get(0)).getValue();
        } else {
            StringBuffer buf = new StringBuffer(20 * list.size());
            buf.append(((InternetHeader) list.get(0)).getValue());
            for (int i = 1; i < list.size(); i++) {
                buf.append(delimiter);
                buf.append(((InternetHeader) list.get(i)).getValue());
            }
            return buf.toString();
        }
    }

    /**
     * Set the value of the header to the supplied value; any existing headers
     * are removed.
     *
     * @param name
     *            the name of the header
     * @param value
     *            the new value
     */
    public void setHeader(String name, String value) {
        List list = new ArrayList();
        list.add(new InternetHeader(name, value));
        setHeaderList(name, list);
    }

    /**
     * Add a new value to the header with the supplied name.
     *
     * @param name
     *            the name of the header to add a new value for
     * @param value
     *            another value
     */
    public void addHeader(String name, String value) {
        List list = getHeaderList(name);
        if (list == null) {
            list = new ArrayList();
            headers.put(name.toLowerCase(), list);
        }
        list.add(new InternetHeader(name, value));
    }

    /**
     * Remove all header entries with the supplied name
     *
     * @param name
     *            the header to remove
     */
    public void removeHeader(String name) {
        List list = getHeaderList(name);
        // it's possible we might not have the named header.  This is a nop if the header doesn't exist.
        if (list != null) {
            list.clear();
        }
    }

    /**
     * Return all headers.
     *
     * @return an Enumeration
containing all headers */ public Enumeration getAllHeaders() { List result = new ArrayList(headers.size() * 2); Iterator it = headers.values().iterator(); while (it.hasNext()) { List list = (List) it.next(); if (list != null) { result.addAll(list); } } return Collections.enumeration(result); } /** * Return all matching Header objects. */ public Enumeration getMatchingHeaders(String[] names) { Set include = new HashSet(names.length); for (int i = 0; i < names.length; i++) { String name = names[i]; include.add(name.toLowerCase()); } List result = new ArrayList(headers.size()); for (Iterator i = headers.entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); if (entry.getValue() != null && include.contains(((String) entry.getKey()).toLowerCase())) { result.addAll((List) entry.getValue()); } } return Collections.enumeration(result); } /** * Return all non matching Header objects. */ public Enumeration getNonMatchingHeaders(String[] names) { Set exclude = new HashSet(names.length); for (int i = 0; i < names.length; i++) { String name = names[i]; exclude.add(name.toLowerCase()); } List result = new ArrayList(headers.size()); for (Iterator i = headers.entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); if (entry.getValue() != null && !exclude.contains(((String) entry.getKey()).toLowerCase())) { result.addAll((List) entry.getValue()); } } return Collections.enumeration(result); } /** * Add an RFC822 header line to the header store. If the line starts with a * space or tab (a continuation line), add it to the last header line in the * list. Otherwise, append the new header line to the list. * * Note that RFC822 headers can only contain US-ASCII characters * * @param line * raw RFC822 header line */ public void addHeaderLine(String line) { StringBuffer name = new StringBuffer(32); StringBuffer value = new StringBuffer(128); boolean inName = true; boolean continuation = false; if (Character.isWhitespace(line.charAt(0))) { continuation = true; inName = false; } for (int i = 0; i < line.length(); i++) { char c = line.charAt(i); if (inName && c == ':') { inName = false; } else if (inName) { name.append(c); } else { value.append(c); } } if (continuation) { List list = getHeaderList(lastHeaderName); Header h = (Header) list.remove(list.size() - 1); list.add(new InternetHeader(lastHeaderName, (h.getValue() + value.toString()).trim())); } else { lastHeaderName = name.toString().trim(); addHeader(lastHeaderName, value.toString().trim()); } } /** * Return all the header lines as an Enumeration of Strings. */ public Enumeration getAllHeaderLines() { return new HeaderLineEnumeration(getAllHeaders()); } /** * Return all matching header lines as an Enumeration of Strings. */ public Enumeration getMatchingHeaderLines(String[] names) { return new HeaderLineEnumeration(getMatchingHeaders(names)); } /** * Return all non-matching header lines. */ public Enumeration getNonMatchingHeaderLines(String[] names) { return new HeaderLineEnumeration(getNonMatchingHeaders(names)); } void setHeader(String name, Address[] addresses) { List list = new ArrayList(addresses.length); for (int i = 0; i < addresses.length; i++) { Address address = addresses[i]; list.add(new InternetHeader(name, address.toString())); } headers.put(name.toLowerCase(), list); } private List getHeaderList(String name) { return (List) headers.get(name.toLowerCase()); } private void setHeaderList(String name, List list) { headers.put(name.toLowerCase(), list); } void writeTo(OutputStream out, String[] ignore) throws IOException { Map map = new LinkedHashMap(headers); if (ignore != null) { // remove each of these from the header list (note, they are stored as lower case keys). for (int i = 0; i < ignore.length; i++) { String key = ignore[i].toLowerCase(); map.remove(key); } } for (Iterator i = map.entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); String name = (String) entry.getKey(); List headers = (List) entry.getValue(); if (headers != null) { for (int j = 0; j < headers.size(); j++) { InternetHeader header = (InternetHeader) headers.get(j); out.write(header.getName().getBytes()); out.write(':'); out.write(' '); out.write(header.getValue().getBytes()); out.write(13); out.write(10); } } } } private static class InternetHeader extends Header { public InternetHeader(String name, String value) { super(name, value); } public boolean equals(Object obj) { if (this == obj) return true; if (obj instanceof InternetHeader == false) return false; final InternetHeader other = (InternetHeader) obj; return getName().equalsIgnoreCase(other.getName()); } public int hashCode() { return getName().toLowerCase().hashCode(); } } private static class HeaderLineEnumeration implements Enumeration { private Enumeration headers; public HeaderLineEnumeration(Enumeration headers) { this.headers = headers; } public boolean hasMoreElements() { return headers.hasMoreElements(); } public Object nextElement() { Header h = (Header) headers.nextElement(); return h.getName() + ": " + h.getValue(); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy