View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package org.jboss.netty.handler.codec.http;
17  
18  import org.jboss.netty.handler.codec.http.cookie.ClientCookieEncoder;
19  import org.jboss.netty.handler.codec.http.cookie.ServerCookieEncoder;
20  
21  import java.util.Set;
22  import java.util.TreeSet;
23  
24  /**
25   * Encodes {@link Cookie}s into an HTTP header value.  This encoder can encode
26   * the HTTP cookie version 0, 1, and 2.
27   * <p>
28   * This encoder is stateful.  It maintains an internal data structure that
29   * holds the {@link Cookie}s added by the {@link #addCookie(String, String)}
30   * method.  Once {@link #encode()} is called, all added {@link Cookie}s are
31   * encoded into an HTTP header value and all {@link Cookie}s in the internal
32   * data structure are removed so that the encoder can start over.
33   * <pre>
34   * // Client-side example
35   * {@link HttpRequest} req = ...;
36   * {@link CookieEncoder} encoder = new {@link CookieEncoder}(false);
37   * encoder.addCookie("JSESSIONID", "1234");
38   * res.setHeader("Cookie", encoder.encode());
39   *
40   * // Server-side example
41   * {@link HttpResponse} res = ...;
42   * {@link CookieEncoder} encoder = new {@link CookieEncoder}(true);
43   * encoder.addCookie("JSESSIONID", "1234");
44   * res.setHeader("Set-Cookie", encoder.encode());
45   * </pre>
46   *
47   * @see CookieDecoder
48   *
49   * @apiviz.stereotype utility
50   * @apiviz.has        org.jboss.netty.handler.codec.http.Cookie oneway - - encodes
51   */
52  public class CookieEncoder {
53  
54      private final Set<Cookie> cookies = new TreeSet<Cookie>();
55      private final boolean server;
56      private final boolean strict;
57  
58      /**
59       * Creates a new encoder.
60       *
61       * @param server {@code true} if and only if this encoder is supposed to
62       *               encode server-side cookies.  {@code false} if and only if
63       *               this encoder is supposed to encode client-side cookies.
64       */
65      public CookieEncoder(boolean server) {
66          this(server, false);
67      }
68  
69      /**
70       * Creates a new encoder.
71       *
72       * @param server {@code true} if and only if this encoder is supposed to
73       *               encode server-side cookies.  {@code false} if and only if
74       *               this encoder is supposed to encode client-side cookies.
75       * @param strict {@code true} if and only if this encoder is supposed to
76       *               validate characters according to RFC6265.
77       */
78      public CookieEncoder(boolean server, boolean strict) {
79          this.server = server;
80          this.strict = strict;
81      }
82  
83      /**
84       * Adds a new {@link Cookie} created with the specified name and value to
85       * this encoder.
86       */
87      public void addCookie(String name, String value) {
88          cookies.add(new DefaultCookie(name, value));
89      }
90  
91      /**
92       * Adds the specified {@link Cookie} to this encoder.
93       */
94      public void addCookie(Cookie cookie) {
95          cookies.add(cookie);
96      }
97  
98      /**
99       * Encodes the {@link Cookie}s which were added by {@link #addCookie(Cookie)}
100      * so far into an HTTP header value.  If no {@link Cookie}s were added,
101      * an empty string is returned.
102      *
103      * <strong>Be aware that calling this method will clear the content of the {@link CookieEncoder}</strong>
104      */
105     public String encode() {
106         String answer;
107         if (server) {
108             answer = encodeServerSide();
109         } else {
110             answer = encodeClientSide();
111         }
112         cookies.clear();
113         return answer;
114     }
115 
116     private String encodeServerSide() {
117         if (cookies.size() > 1) {
118             throw new IllegalStateException(
119                     "encode() can encode only one cookie on server mode: " + cookies.size() + " cookies added");
120         }
121 
122         Cookie cookie = cookies.isEmpty() ? null : cookies.iterator().next();
123         ServerCookieEncoder encoder = strict ? ServerCookieEncoder.STRICT : ServerCookieEncoder.LAX;
124         return encoder.encode(cookie);
125     }
126 
127     private String encodeClientSide() {
128         ClientCookieEncoder encoder = strict ? ClientCookieEncoder.STRICT : ClientCookieEncoder.LAX;
129         return encoder.encode(cookies);
130     }
131 }