View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2014 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      */
132     public ExtensionConfig(ExtensionConfig copy)
133     {
134         this.name = copy.name;
135         this.parameters = new HashMap<>();
136         this.parameters.putAll(copy.parameters);
137     }
138 
139     public ExtensionConfig(String parameterizedName)
140     {
141         Iterator<String> extListIter = QuoteUtil.splitAt(parameterizedName,";");
142         this.name = extListIter.next();
143         this.parameters = new HashMap<>();
144 
145         // now for parameters
146         while (extListIter.hasNext())
147         {
148             String extParam = extListIter.next();
149             Iterator<String> extParamIter = QuoteUtil.splitAt(extParam,"=");
150             String key = extParamIter.next().trim();
151             String value = null;
152             if (extParamIter.hasNext())
153             {
154                 value = extParamIter.next();
155             }
156             parameters.put(key,value);
157         }
158     }
159 
160     public String getName()
161     {
162         return name;
163     }
164 
165     public final int getParameter(String key, int defValue)
166     {
167         String val = parameters.get(key);
168         if (val == null)
169         {
170             return defValue;
171         }
172         return Integer.valueOf(val);
173     }
174 
175     public final String getParameter(String key, String defValue)
176     {
177         String val = parameters.get(key);
178         if (val == null)
179         {
180             return defValue;
181         }
182         return val;
183     }
184 
185     public final String getParameterizedName()
186     {
187         StringBuilder str = new StringBuilder();
188         str.append(name);
189         for (String param : parameters.keySet())
190         {
191             str.append(';');
192             str.append(param);
193             String value = parameters.get(param);
194             if (value != null)
195             {
196                 str.append('=');
197                 QuoteUtil.quoteIfNeeded(str,value,";=");
198             }
199         }
200         return str.toString();
201     }
202 
203     public final Set<String> getParameterKeys()
204     {
205         return parameters.keySet();
206     }
207 
208     /**
209      * Return parameters found in request URI.
210      * 
211      * @return the parameter map
212      */
213     public final Map<String, String> getParameters()
214     {
215         return parameters;
216     }
217 
218     /**
219      * Initialize the parameters on this config from the other configuration.
220      * 
221      * @param other
222      *            the other configuration.
223      */
224     public final void init(ExtensionConfig other)
225     {
226         this.parameters.clear();
227         this.parameters.putAll(other.parameters);
228     }
229 
230     public final void setParameter(String key)
231     {
232         parameters.put(key,null);
233     }
234 
235     public final void setParameter(String key, int value)
236     {
237         parameters.put(key,Integer.toString(value));
238     }
239 
240     public final void setParameter(String key, String value)
241     {
242         parameters.put(key,value);
243     }
244 
245     @Override
246     public String toString()
247     {
248         return getParameterizedName();
249     }
250 }