View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2015 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.http;
20  
21  import java.nio.ByteBuffer;
22  
23  import org.eclipse.jetty.util.ArrayTrie;
24  import org.eclipse.jetty.util.StringUtil;
25  import org.eclipse.jetty.util.Trie;
26  
27  
28  /* ------------------------------------------------------------------------------- */
29  /**
30   */
31  public enum HttpMethod
32  {
33      GET,
34      POST,
35      HEAD,
36      PUT,
37      OPTIONS,
38      DELETE,
39      TRACE,
40      CONNECT,
41      MOVE,
42      PROXY,
43      PRI;
44  
45      /* ------------------------------------------------------------ */
46      /**
47       * Optimized lookup to find a method name and trailing space in a byte array.
48       * @param bytes Array containing ISO-8859-1 characters
49       * @param position The first valid index
50       * @param limit The first non valid index
51       * @return A HttpMethod if a match or null if no easy match.
52       */
53      public static HttpMethod lookAheadGet(byte[] bytes, final int position, int limit)
54      {
55          int length=limit-position;
56          if (length<4)
57              return null;
58          switch(bytes[position])
59          {
60              case 'G':
61                  if (bytes[position+1]=='E' && bytes[position+2]=='T' && bytes[position+3]==' ')
62                      return GET;
63                  break;
64              case 'P':
65                  if (bytes[position+1]=='O' && bytes[position+2]=='S' && bytes[position+3]=='T' && length>=5 && bytes[position+4]==' ')
66                      return POST;
67                  if (bytes[position+1]=='R' && bytes[position+2]=='O' && bytes[position+3]=='X' && length>=6 && bytes[position+4]=='Y' && bytes[position+5]==' ')
68                      return PROXY;
69                  if (bytes[position+1]=='U' && bytes[position+2]=='T' && bytes[position+3]==' ')
70                      return PUT;
71                  if (bytes[position+1]=='R' && bytes[position+2]=='I' && bytes[position+3]==' ')
72                      return PRI;
73                  break;
74              case 'H':
75                  if (bytes[position+1]=='E' && bytes[position+2]=='A' && bytes[position+3]=='D' && length>=5 && bytes[position+4]==' ')
76                      return HEAD;
77                  break;
78              case 'O':
79                  if (bytes[position+1]=='P' && bytes[position+2]=='T' && bytes[position+3]=='I' && length>=8 &&
80                      bytes[position+4]=='O' && bytes[position+5]=='N' && bytes[position+6]=='S' && bytes[position+7]==' ' )
81                      return OPTIONS;
82                  break;
83              case 'D':
84                  if (bytes[position+1]=='E' && bytes[position+2]=='L' && bytes[position+3]=='E' && length>=7 &&
85                      bytes[position+4]=='T' && bytes[position+5]=='E' && bytes[position+6]==' ' )
86                      return DELETE;
87                  break;
88              case 'T':
89                  if (bytes[position+1]=='R' && bytes[position+2]=='A' && bytes[position+3]=='C' && length>=6 &&
90                      bytes[position+4]=='E' && bytes[position+5]==' ' )
91                      return TRACE;
92                  break;
93              case 'C':
94                  if (bytes[position+1]=='O' && bytes[position+2]=='N' && bytes[position+3]=='N' && length>=8 &&
95                      bytes[position+4]=='E' && bytes[position+5]=='C' && bytes[position+6]=='T' && bytes[position+7]==' ' )
96                      return CONNECT;
97                  break;
98              case 'M':
99                  if (bytes[position+1]=='O' && bytes[position+2]=='V' && bytes[position+3]=='E' && length>=5 && bytes[position+4]==' ')
100                     return MOVE;
101                 break;
102 
103             default:
104                 break;
105         }
106         return null;
107     }
108 
109     /* ------------------------------------------------------------ */
110     /**
111      * Optimized lookup to find a method name and trailing space in a byte array.
112      * @param buffer buffer containing ISO-8859-1 characters, it is not modified.
113      * @return A HttpMethod if a match or null if no easy match.
114      */
115     public static HttpMethod lookAheadGet(ByteBuffer buffer)
116     {
117         if (buffer.hasArray())
118             return lookAheadGet(buffer.array(),buffer.arrayOffset()+buffer.position(),buffer.arrayOffset()+buffer.limit());
119         
120         int l = buffer.remaining();
121         if (l>=4)
122         {
123             HttpMethod m = CACHE.getBest(buffer,0,l);
124             if (m!=null)
125             {
126                 int ml = m.asString().length();
127                 if (l>ml && buffer.get(buffer.position()+ml)==' ')
128                     return m;
129             }
130         }
131         return null;
132     }
133 
134     /* ------------------------------------------------------------ */
135     public final static Trie<HttpMethod> CACHE= new ArrayTrie<>();
136     static
137     {
138         for (HttpMethod method : HttpMethod.values())
139             CACHE.put(method.toString(),method);
140     }
141 
142     /* ------------------------------------------------------------ */
143     private final ByteBuffer _buffer;
144     private final byte[] _bytes;
145 
146     /* ------------------------------------------------------------ */
147     HttpMethod()
148     {
149         _bytes=StringUtil.getBytes(toString());
150         _buffer=ByteBuffer.wrap(_bytes);
151     }
152 
153     /* ------------------------------------------------------------ */
154     public byte[] getBytes()
155     {
156         return _bytes;
157     }
158 
159     /* ------------------------------------------------------------ */
160     public boolean is(String s)
161     {
162         return toString().equalsIgnoreCase(s);
163     }
164 
165     /* ------------------------------------------------------------ */
166     public ByteBuffer asBuffer()
167     {
168         return _buffer.asReadOnlyBuffer();
169     }
170 
171     /* ------------------------------------------------------------ */
172     public String asString()
173     {
174         return toString();
175     }
176 
177     /* ------------------------------------------------------------ */
178     /**
179      * Converts the given String parameter to an HttpMethod
180      * @param method the String to get the equivalent HttpMethod from
181      * @return the HttpMethod or null if the parameter method is unknown
182      */
183     public static HttpMethod fromString(String method)
184     {
185         return CACHE.get(method);
186     }
187 }