View Javadoc
1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.websocket.common;
20  
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.List;
24  import java.util.Map;
25  import java.util.Set;
26  import java.util.TreeMap;
27  
28  import org.eclipse.jetty.websocket.api.UpgradeRequest;
29  import org.eclipse.jetty.websocket.api.UpgradeResponse;
30  import org.eclipse.jetty.websocket.api.WebSocketConstants;
31  import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
32  import org.eclipse.jetty.websocket.api.util.QuoteUtil;
33  
34  public class UpgradeResponseAdapter implements UpgradeResponse
35  {
36      public static final String SEC_WEBSOCKET_PROTOCOL = WebSocketConstants.SEC_WEBSOCKET_PROTOCOL;
37      private int statusCode;
38      private String statusReason;
39      private Map<String, List<String>> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
40      private List<ExtensionConfig> extensions = new ArrayList<>();
41      private boolean success = false;
42  
43      @Override
44      public void addHeader(String name, String value)
45      {
46          String key = name;
47          List<String> values = headers.get(key);
48          if (values == null)
49          {
50              values = new ArrayList<>();
51          }
52          values.add(value);
53          headers.put(key,values);
54      }
55  
56      /**
57       * Get the accepted WebSocket protocol.
58       * 
59       * @return the accepted WebSocket protocol.
60       */
61      @Override
62      public String getAcceptedSubProtocol()
63      {
64          return getHeader(SEC_WEBSOCKET_PROTOCOL);
65      }
66  
67      /**
68       * Get the list of extensions that should be used for the websocket.
69       * 
70       * @return the list of negotiated extensions to use.
71       */
72      @Override
73      public List<ExtensionConfig> getExtensions()
74      {
75          return extensions;
76      }
77  
78      @Override
79      public String getHeader(String name)
80      {
81          List<String> values = getHeaders(name);
82          // no value list
83          if (values == null)
84          {
85              return null;
86          }
87          int size = values.size();
88          // empty value list
89          if (size <= 0)
90          {
91              return null;
92          }
93          // simple return
94          if (size == 1)
95          {
96              return values.get(0);
97          }
98          // join it with commas
99          boolean needsDelim = false;
100         StringBuilder ret = new StringBuilder();
101         for (String value : values)
102         {
103             if (needsDelim)
104             {
105                 ret.append(", ");
106             }
107             QuoteUtil.quoteIfNeeded(ret,value,QuoteUtil.ABNF_REQUIRED_QUOTING);
108             needsDelim = true;
109         }
110         return ret.toString();
111     }
112 
113     @Override
114     public Set<String> getHeaderNames()
115     {
116         return headers.keySet();
117     }
118 
119     @Override
120     public Map<String, List<String>> getHeaders()
121     {
122         return headers;
123     }
124 
125     @Override
126     public List<String> getHeaders(String name)
127     {
128         return headers.get(name);
129     }
130 
131     @Override
132     public int getStatusCode()
133     {
134         return statusCode;
135     }
136 
137     @Override
138     public String getStatusReason()
139     {
140         return statusReason;
141     }
142 
143     @Override
144     public boolean isSuccess()
145     {
146         return success;
147     }
148 
149     /**
150      * Issue a forbidden upgrade response.
151      * <p>
152      * This means that the websocket endpoint was valid, but the conditions to use a WebSocket resulted in a forbidden
153      * access.
154      * <p>
155      * Use this when the origin or authentication is invalid.
156      * 
157      * @param message
158      *            the short 1 line detail message about the forbidden response
159      * @throws IOException
160      *             if unable to send the forbidden
161      */
162     @Override
163     public void sendForbidden(String message) throws IOException
164     {
165         throw new UnsupportedOperationException("Not supported");
166     }
167 
168     /**
169      * Set the accepted WebSocket Protocol.
170      * 
171      * @param protocol
172      *            the protocol to list as accepted
173      */
174     @Override
175     public void setAcceptedSubProtocol(String protocol)
176     {
177         setHeader(SEC_WEBSOCKET_PROTOCOL,protocol);
178     }
179 
180     /**
181      * Set the list of extensions that are approved for use with this websocket.
182      * <p>
183      * Notes:
184      * <ul>
185      * <li>Per the spec you cannot add extensions that have not been seen in the {@link UpgradeRequest}, just remove entries you don't want to use</li>
186      * <li>If this is unused, or a null is passed, then the list negotiation will follow default behavior and use the complete list of extensions that are
187      * available in this WebSocket server implementation.</li>
188      * </ul>
189      * 
190      * @param extensions
191      *            the list of extensions to use.
192      */
193     @Override
194     public void setExtensions(List<ExtensionConfig> extensions)
195     {
196         this.extensions.clear();
197         if (extensions != null)
198         {
199             this.extensions.addAll(extensions);
200         }
201     }
202 
203     @Override
204     public void setHeader(String name, String value)
205     {
206         List<String> values = new ArrayList<>();
207         values.add(value);
208         headers.put(name,values);
209     }
210 
211     @Override
212     public void setStatusCode(int statusCode)
213     {
214         this.statusCode = statusCode;
215     }
216 
217     @Override
218     public void setStatusReason(String statusReason)
219     {
220         this.statusReason = statusReason;
221     }
222 
223     @Override
224     public void setSuccess(boolean success)
225     {
226         this.success = success;
227     }
228 }