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  
20  package org.eclipse.jetty.http;
21  
22  import java.nio.ByteBuffer;
23  import java.util.ArrayList;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.ServiceLoader;
27  
28  import org.eclipse.jetty.util.log.Log;
29  import org.eclipse.jetty.util.log.Logger;
30  
31  
32  /* ------------------------------------------------------------ */
33  /** Pre encoded HttpField.
34   * <p>A HttpField that will be cached and used many times can be created as 
35   * a {@link PreEncodedHttpField}, which will use the {@link HttpFieldPreEncoder}
36   * instances discovered by the {@link ServiceLoader} to pre-encode the header 
37   * for each version of HTTP in use.  This will save garbage 
38   * and CPU each time the field is encoded into a response.
39   * </p>
40   */
41  public class PreEncodedHttpField extends HttpField
42  {
43      private final static Logger LOG = Log.getLogger(PreEncodedHttpField.class);
44      private final static HttpFieldPreEncoder[] __encoders;
45      
46      static
47      { 
48          List<HttpFieldPreEncoder> encoders = new ArrayList<>();
49          Iterator<HttpFieldPreEncoder> iter = ServiceLoader.load(HttpFieldPreEncoder.class,PreEncodedHttpField.class.getClassLoader()).iterator();
50          while (iter.hasNext())
51          {
52              try
53              {
54                  encoders.add(iter.next());
55              }
56              catch(Error|RuntimeException e)
57              {
58                  LOG.debug(e);
59              }
60          }
61          // TODO avoid needing this catch all
62          if (encoders.size()==0)
63              encoders.add(new Http1FieldPreEncoder());
64          LOG.debug("HttpField encoders loaded: {}",encoders);
65          __encoders = encoders.toArray(new HttpFieldPreEncoder[encoders.size()]);
66      }
67      
68      private final byte[][] _encodedField=new byte[2][];
69  
70      public PreEncodedHttpField(HttpHeader header,String name,String value)
71      {
72          super(header,name, value);
73          
74          for (HttpFieldPreEncoder e:__encoders)
75          {
76              _encodedField[e.getHttpVersion()==HttpVersion.HTTP_2?1:0]=e.getEncodedField(header,header.asString(),value);
77          }
78      }
79      
80      public PreEncodedHttpField(HttpHeader header,String value)
81      {
82          this(header,header.asString(),value);
83      }
84      
85      public PreEncodedHttpField(String name,String value)
86      {
87          this(null,name,value);
88      }
89      
90      public void putTo(ByteBuffer bufferInFillMode, HttpVersion version)
91      {
92          bufferInFillMode.put(_encodedField[version==HttpVersion.HTTP_2?1:0]);
93      }
94  }