src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/InternetHeaders.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 368
0989ad8c0860
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.org.jvnet.mimepull;
    28 import java.io.IOException;
    29 import java.util.NoSuchElementException;
    30 import java.util.List;
    32 /**
    33  * InternetHeaders is a utility class that manages RFC822 style
    34  * headers. Given an RFC822 format message stream, it reads lines
    35  * until the blank line that indicates end of header. The input stream
    36  * is positioned at the start of the body. The lines are stored
    37  * within the object and can be extracted as either Strings or
    38  * {@link Header} objects. <p>
    39  * <p/>
    40  * This class is mostly intended for service providers. MimeMessage
    41  * and MimeBody use this class for holding their headers. <p>
    42  * <p/>
    43  * <hr> <strong>A note on RFC822 and MIME headers</strong><p>
    44  * <p/>
    45  * RFC822 and MIME header fields <strong>must</strong> contain only
    46  * US-ASCII characters. If a header contains non US-ASCII characters,
    47  * it must be encoded as per the rules in RFC 2047. The MimeUtility
    48  * class provided in this package can be used to to achieve this.
    49  * Callers of the <code>setHeader</code>, <code>addHeader</code>, and
    50  * <code>addHeaderLine</code> methods are responsible for enforcing
    51  * the MIME requirements for the specified headers.  In addition, these
    52  * header fields must be folded (wrapped) before being sent if they
    53  * exceed the line length limitation for the transport (1000 bytes for
    54  * SMTP).  Received headers may have been folded.  The application is
    55  * responsible for folding and unfolding headers as appropriate. <p>
    56  *
    57  * @author John Mani
    58  * @author Bill Shannon
    59  */
    60 final class InternetHeaders {
    62     private final FinalArrayList<Hdr> headers = new FinalArrayList<Hdr>();
    64     /**
    65      * Read and parse the given RFC822 message stream till the
    66      * blank line separating the header from the body. Store the
    67      * header lines inside this InternetHeaders object. <p>
    68      * <p/>
    69      * Note that the header lines are added into this InternetHeaders
    70      * object, so any existing headers in this object will not be
    71      * affected.
    72      *
    73      * @param   lis RFC822 input stream
    74      */
    75     InternetHeaders(MIMEParser.LineInputStream lis) {
    76         // Read header lines until a blank line. It is valid
    77         // to have BodyParts with no header lines.
    78         String line;
    79         String prevline = null; // the previous header line, as a string
    80         // a buffer to accumulate the header in, when we know it's needed
    81         StringBuilder lineBuffer = new StringBuilder();
    83         try {
    84             //while ((line = lis.readLine()) != null) {
    85             do {
    86                 line = lis.readLine();
    87                 if (line != null &&
    88                         (line.startsWith(" ") || line.startsWith("\t"))) {
    89                     // continuation of header
    90                     if (prevline != null) {
    91                         lineBuffer.append(prevline);
    92                         prevline = null;
    93                     }
    94                     lineBuffer.append("\r\n");
    95                     lineBuffer.append(line);
    96                 } else {
    97                     // new header
    98                     if (prevline != null) {
    99                         addHeaderLine(prevline);
   100                     } else if (lineBuffer.length() > 0) {
   101                         // store previous header first
   102                         addHeaderLine(lineBuffer.toString());
   103                         lineBuffer.setLength(0);
   104                     }
   105                     prevline = line;
   106                 }
   107             } while (line != null && line.length() > 0);
   108         } catch (IOException ioex) {
   109             throw new MIMEParsingException("Error in input stream", ioex);
   110         }
   111     }
   113     /**
   114      * Return all the values for the specified header. The
   115      * values are String objects.  Returns <code>null</code>
   116      * if no headers with the specified name exist.
   117      *
   118      * @param   name header name
   119      * @return          array of header values, or null if none
   120      */
   121     List<String> getHeader(String name) {
   122         // XXX - should we just step through in index order?
   123         FinalArrayList<String> v = new FinalArrayList<String>(); // accumulate return values
   125         int len = headers.size();
   126         for( int i=0; i<len; i++ ) {
   127             Hdr h = (Hdr) headers.get(i);
   128             if (name.equalsIgnoreCase(h.name)) {
   129                 v.add(h.getValue());
   130             }
   131         }
   132         return (v.size() == 0) ? null : v;
   133     }
   135     /**
   136      * Return all the headers as an Enumeration of
   137      * {@link Header} objects.
   138      *
   139      * @return  Header objects
   140      */
   141     FinalArrayList<? extends Header> getAllHeaders() {
   142         return headers; // conceptually it should be read-only, but for performance reason I'm not wrapping it here
   143     }
   145     /**
   146      * Add an RFC822 header line to the header store.
   147      * If the line starts with a space or tab (a continuation line),
   148      * add it to the last header line in the list. <p>
   149      * <p/>
   150      * Note that RFC822 headers can only contain US-ASCII characters
   151      *
   152      * @param   line    raw RFC822 header line
   153      */
   154     void addHeaderLine(String line) {
   155         try {
   156             char c = line.charAt(0);
   157             if (c == ' ' || c == '\t') {
   158                 Hdr h = (Hdr) headers.get(headers.size() - 1);
   159                 h.line += "\r\n" + line;
   160             } else {
   161                 headers.add(new Hdr(line));
   162             }
   163         } catch (StringIndexOutOfBoundsException e) {
   164             // line is empty, ignore it
   165         } catch (NoSuchElementException e) {
   166             // XXX - vector is empty?
   167         }
   168     }
   170 }
   172 /*
   173  * A private utility class to represent an individual header.
   174  */
   176 class Hdr implements Header {
   178     String name;    // the canonicalized (trimmed) name of this header
   179     // XXX - should name be stored in lower case?
   180     String line;    // the entire RFC822 header "line"
   182     /*
   183      * Constructor that takes a line and splits out
   184      * the header name.
   185      */
   186     Hdr(String l) {
   187         int i = l.indexOf(':');
   188         if (i < 0) {
   189             // should never happen
   190             name = l.trim();
   191         } else {
   192             name = l.substring(0, i).trim();
   193         }
   194         line = l;
   195     }
   197     /*
   198      * Constructor that takes a header name and value.
   199      */
   200     Hdr(String n, String v) {
   201         name = n;
   202         line = n + ": " + v;
   203     }
   205     /*
   206      * Return the "name" part of the header line.
   207      */
   208     @Override
   209     public String getName() {
   210         return name;
   211     }
   213     /*
   214      * Return the "value" part of the header line.
   215      */
   216     @Override
   217     public String getValue() {
   218         int i = line.indexOf(':');
   219         if (i < 0) {
   220             return line;
   221         }
   223         int j;
   224         if (name.equalsIgnoreCase("Content-Description")) {
   225             // Content-Description should retain the folded whitespace after header unfolding -
   226             // rf. RFC2822 section 2.2.3, rf. RFC2822 section 3.2.3
   227             for (j = i + 1; j < line.length(); j++) {
   228                 char c = line.charAt(j);
   229                 if (!(/*c == ' ' ||*/c == '\t' || c == '\r' || c == '\n')) {
   230                     break;
   231                 }
   232             }
   233         } else {
   234             // skip whitespace after ':'
   235             for (j = i + 1; j < line.length(); j++) {
   236                 char c = line.charAt(j);
   237                 if (!(c == ' ' || c == '\t' || c == '\r' || c == '\n')) {
   238                     break;
   239                 }
   240             }
   241         }
   242         return line.substring(j);
   243     }
   244 }

mercurial