View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.core5.http.message;
29  
30  import java.util.BitSet;
31  import java.util.Iterator;
32  import java.util.LinkedHashSet;
33  import java.util.Set;
34  
35  import org.apache.hc.core5.http.EntityDetails;
36  import org.apache.hc.core5.http.FormattedHeader;
37  import org.apache.hc.core5.http.Header;
38  import org.apache.hc.core5.http.HeaderElement;
39  import org.apache.hc.core5.http.HttpHeaders;
40  import org.apache.hc.core5.http.HttpMessage;
41  import org.apache.hc.core5.http.HttpResponse;
42  import org.apache.hc.core5.http.HttpStatus;
43  import org.apache.hc.core5.http.MessageHeaders;
44  import org.apache.hc.core5.http.Method;
45  import org.apache.hc.core5.util.Args;
46  import org.apache.hc.core5.util.CharArrayBuffer;
47  import org.apache.hc.core5.util.TextUtils;
48  
49  /**
50   * Support methods for HTTP message processing.
51   *
52   * @since 5.0
53   */
54  public class MessageSupport {
55  
56      private MessageSupport() {
57          // Do not allow utility class to be instantiated.
58      }
59  
60      public static void formatTokens(final CharArrayBuffer dst, final String... tokens) {
61          Args.notNull(dst, "Destination");
62          for (int i = 0; i < tokens.length; i++) {
63              final String element = tokens[i];
64              if (i > 0) {
65                  dst.append(", ");
66              }
67              dst.append(element);
68          }
69      }
70  
71      public static void formatTokens(final CharArrayBuffer dst, final Set<String> tokens) {
72          Args.notNull(dst, "Destination");
73          if (tokens == null || tokens.isEmpty()) {
74              return;
75          }
76          formatTokens(dst, tokens.toArray(new String[tokens.size()]));
77      }
78  
79      public static Header format(final String name, final Set<String> tokens) {
80          Args.notBlank(name, "Header name");
81          if (tokens == null || tokens.isEmpty()) {
82              return null;
83          }
84          final CharArrayBufferrayBuffer.html#CharArrayBuffer">CharArrayBuffer buffer = new CharArrayBuffer(256);
85          buffer.append(name);
86          buffer.append(": ");
87          formatTokens(buffer, tokens);
88          return BufferedHeader.create(buffer);
89      }
90  
91      public static Header format(final String name, final String... tokens) {
92          Args.notBlank(name, "Header name");
93          if (tokens == null || tokens.length == 0) {
94              return null;
95          }
96          final CharArrayBufferrayBuffer.html#CharArrayBuffer">CharArrayBuffer buffer = new CharArrayBuffer(256);
97          buffer.append(name);
98          buffer.append(": ");
99          formatTokens(buffer, tokens);
100         return BufferedHeader.create(buffer);
101     }
102 
103     private static final BitSet COMMA = TokenParser.INIT_BITSET(',');
104 
105     public static Set<String> parseTokens(final CharSequence src, final ParserCursor cursor) {
106         Args.notNull(src, "Source");
107         Args.notNull(cursor, "Cursor");
108         final Set<String> tokens = new LinkedHashSet<>();
109         while (!cursor.atEnd()) {
110             final int pos = cursor.getPos();
111             if (src.charAt(pos) == ',') {
112                 cursor.updatePos(pos + 1);
113             }
114             final String token = TokenParser.INSTANCE.parseToken(src, cursor, COMMA);
115             if (!TextUtils.isBlank(token)) {
116                 tokens.add(token);
117             }
118         }
119         return tokens;
120     }
121 
122     public static Set<String> parseTokens(final Header header) {
123         Args.notNull(header, "Header");
124         if (header instanceof FormattedHeader) {
125             final CharArrayBuffer buf = ((FormattedHeader) header).getBuffer();
126             final ParserCursorsage/ParserCursor.html#ParserCursor">ParserCursor cursor = new ParserCursor(0, buf.length());
127             cursor.updatePos(((FormattedHeader) header).getValuePos());
128             return parseTokens(buf, cursor);
129         }
130         final String value = header.getValue();
131         final ParserCursorsage/ParserCursor.html#ParserCursor">ParserCursor cursor = new ParserCursor(0, value.length());
132         return parseTokens(value, cursor);
133     }
134 
135     public static void addContentTypeHeader(final HttpMessage message, final EntityDetails entity) {
136         if (entity != null && entity.getContentType() != null && !message.containsHeader(HttpHeaders.CONTENT_TYPE)) {
137             message.addHeader(new BasicHeader(HttpHeaders.CONTENT_TYPE, entity.getContentType()));
138         }
139     }
140 
141     public static void addContentEncodingHeader(final HttpMessage message, final EntityDetails entity) {
142         if (entity != null && entity.getContentEncoding() != null && !message.containsHeader(HttpHeaders.CONTENT_ENCODING)) {
143             message.addHeader(new BasicHeader(HttpHeaders.CONTENT_ENCODING, entity.getContentEncoding()));
144         }
145     }
146 
147     public static void addTrailerHeader(final HttpMessage message, final EntityDetails entity) {
148         if (entity != null && !message.containsHeader(HttpHeaders.TRAILER)) {
149             final Set<String> trailerNames = entity.getTrailerNames();
150             if (trailerNames != null && !trailerNames.isEmpty()) {
151                 message.setHeader(MessageSupport.format(HttpHeaders.TRAILER, trailerNames));
152             }
153         }
154     }
155 
156     public static Iterator<HeaderElement> iterate(final MessageHeaders headers, final String name) {
157         Args.notNull(headers, "Message headers");
158         Args.notBlank(name, "Header name");
159         return new BasicHeaderElementIterator(headers.headerIterator(name));
160     }
161 
162     public static HeaderElement[] parse(final Header header) {
163         Args.notNull(header, "Headers");
164         final String value = header.getValue();
165         if (value == null) {
166             return new HeaderElement[] {};
167         }
168         final ParserCursorsage/ParserCursor.html#ParserCursor">ParserCursor cursor = new ParserCursor(0, value.length());
169         return BasicHeaderValueParser.INSTANCE.parseElements(value, cursor);
170     }
171 
172     /**
173      * @since  5.0
174      */
175     public static boolean canResponseHaveBody(final String method, final HttpResponse response) {
176         if (Method.HEAD.isSame(method)) {
177             return false;
178         }
179         final int status = response.getCode();
180         if (Method.CONNECT.isSame(method) && status == HttpStatus.SC_OK) {
181             return false;
182         }
183         return status >= HttpStatus.SC_SUCCESS
184                 && status != HttpStatus.SC_NO_CONTENT
185                 && status != HttpStatus.SC_NOT_MODIFIED;
186     }
187 
188 }