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.api.extensions;
20  
21  import java.util.ArrayList;
22  import java.util.Enumeration;
23  import java.util.HashMap;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  
29  import org.eclipse.jetty.websocket.api.util.QuoteUtil;
30  
31  /**
32   * Represents an Extension Configuration, as seen during the connection Handshake process.
33   */
34  public class ExtensionConfig
35  {
36      /**
37       * Parse a single parameterized name.
38       * 
39       * @param parameterizedName
40       *            the parameterized name
41       * @return the ExtensionConfig
42       */
43      public static ExtensionConfig parse(String parameterizedName)
44      {
45          return new ExtensionConfig(parameterizedName);
46      }
47  
48      /**
49       * Parse enumeration of <code>Sec-WebSocket-Extensions</code> header values into a {@link ExtensionConfig} list
50       * 
51       * @param valuesEnum
52       *            the raw header values enum
53       * @return the list of extension configs
54       */
55      public static List<ExtensionConfig> parseEnum(Enumeration<String> valuesEnum)
56      {
57          List<ExtensionConfig> configs = new ArrayList<>();
58  
59          if (valuesEnum != null)
60          {
61              while (valuesEnum.hasMoreElements())
62              {
63                  Iterator<String> extTokenIter = QuoteUtil.splitAt(valuesEnum.nextElement(),",");
64                  while (extTokenIter.hasNext())
65                  {
66                      String extToken = extTokenIter.next();
67                      configs.add(ExtensionConfig.parse(extToken));
68                  }
69              }
70          }
71  
72          return configs;
73      }
74  
75      /**
76       * Parse 1 or more raw <code>Sec-WebSocket-Extensions</code> header values into a {@link ExtensionConfig} list
77       * 
78       * @param rawSecWebSocketExtensions
79       *            the raw header values
80       * @return the list of extension configs
81       */
82      public static List<ExtensionConfig> parseList(String... rawSecWebSocketExtensions)
83      {
84          List<ExtensionConfig> configs = new ArrayList<>();
85  
86          for (String rawValue : rawSecWebSocketExtensions)
87          {
88              Iterator<String> extTokenIter = QuoteUtil.splitAt(rawValue,",");
89              while (extTokenIter.hasNext())
90              {
91                  String extToken = extTokenIter.next();
92                  configs.add(ExtensionConfig.parse(extToken));
93              }
94          }
95  
96          return configs;
97      }
98  
99      /**
100      * Convert a list of {@link ExtensionConfig} to a header value
101      * 
102      * @param configs
103      *            the list of extension configs
104      * @return the header value (null if no configs present)
105      */
106     public static String toHeaderValue(List<ExtensionConfig> configs)
107     {
108         if ((configs == null) || (configs.isEmpty()))
109         {
110             return null;
111         }
112         StringBuilder parameters = new StringBuilder();
113         boolean needsDelim = false;
114         for (ExtensionConfig ext : configs)
115         {
116             if (needsDelim)
117             {
118                 parameters.append(", ");
119             }
120             parameters.append(ext.getParameterizedName());
121             needsDelim = true;
122         }
123         return parameters.toString();
124     }
125 
126     private final String name;
127     private final Map<String, String> parameters;
128 
129     /**
130      * Copy constructor
131      * @param copy the extension config to copy
132      */
133     public ExtensionConfig(ExtensionConfig copy)
134     {
135         this.name = copy.name;
136         this.parameters = new HashMap<>();
137         this.parameters.putAll(copy.parameters);
138     }
139 
140     public ExtensionConfig(String parameterizedName)
141     {
142         Iterator<String> extListIter = QuoteUtil.splitAt(parameterizedName,";");
143         this.name = extListIter.next();
144         this.parameters = new HashMap<>();
145 
146         // now for parameters
147         while (extListIter.hasNext())
148         {
149             String extParam = extListIter.next();
150             Iterator<String> extParamIter = QuoteUtil.splitAt(extParam,"=");
151             String key = extParamIter.next().trim();
152             String value = null;
153             if (extParamIter.hasNext())
154             {
155                 value = extParamIter.next();
156             }
157             parameters.put(key,value);
158         }
159     }
160 
161     public String getName()
162     {
163         return name;
164     }
165 
166     public final int getParameter(String key, int defValue)
167     {
168         String val = parameters.get(key);
169         if (val == null)
170         {
171             return defValue;
172         }
173         return Integer.valueOf(val);
174     }
175 
176     public final String getParameter(String key, String defValue)
177     {
178         String val = parameters.get(key);
179         if (val == null)
180         {
181             return defValue;
182         }
183         return val;
184     }
185 
186     public final String getParameterizedName()
187     {
188         StringBuilder str = new StringBuilder();
189         str.append(name);
190         for (String param : parameters.keySet())
191         {
192             str.append(';');
193             str.append(param);
194             String value = parameters.get(param);
195             if (value != null)
196             {
197                 str.append('=');
198                 QuoteUtil.quoteIfNeeded(str,value,";=");
199             }
200         }
201         return str.toString();
202     }
203 
204     public final Set<String> getParameterKeys()
205     {
206         return parameters.keySet();
207     }
208 
209     /**
210      * Return parameters found in request URI.
211      * 
212      * @return the parameter map
213      */
214     public final Map<String, String> getParameters()
215     {
216         return parameters;
217     }
218 
219     /**
220      * Initialize the parameters on this config from the other configuration.
221      * 
222      * @param other
223      *            the other configuration.
224      */
225     public final void init(ExtensionConfig other)
226     {
227         this.parameters.clear();
228         this.parameters.putAll(other.parameters);
229     }
230 
231     public final void setParameter(String key)
232     {
233         parameters.put(key,null);
234     }
235 
236     public final void setParameter(String key, int value)
237     {
238         parameters.put(key,Integer.toString(value));
239     }
240 
241     public final void setParameter(String key, String value)
242     {
243         parameters.put(key,value);
244     }
245 
246     @Override
247     public String toString()
248     {
249         return getParameterizedName();
250     }
251 }