Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements. See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership. The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License. You may obtain a copy of the License at
   *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations under the License.
  */
 package org.apache.shindig.gadgets.http;
 
 import  com.google.common.base.Supplier;
 import  com.google.common.collect.ImmutableSet;
 import  com.google.common.collect.Lists;
 import  com.google.common.collect.MapMaker;
 import  com.google.common.collect.Maps;
 import  com.google.common.collect.Multimap;
 import  com.google.common.collect.Multimaps;
 import  com.google.inject.Inject;
 import  com.google.inject.name.Named;
 
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
Represents the results of an HTTP content retrieval operation. HttpResponse objects are immutable in order to allow them to be safely used in concurrent caches and by multiple threads without worrying about concurrent modification.
 
 public final class HttpResponse implements Externalizable {
   private static final long serialVersionUID = 7526471155622776147L;
 
   public static final int SC_CONTINUE = 100;
   public static final int SC_SWITCHING_PROTOCOLS = 101;
 
   public static final int SC_OK = 200;
   public static final int SC_CREATED = 201;
   public static final int SC_ACCEPTED = 202;
   public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;
   public static final int SC_NO_CONTENT = 204;
   public static final int SC_RESET_CONTENT = 205;
   public static final int SC_PARTIAL_CONTENT = 206;
 
   public static final int SC_MULTIPLE_CHOICES = 300;
   public static final int SC_MOVED_PERMANENTLY = 301;
   public static final int SC_FOUND = 302;
   public static final int SC_SEE_OTHER = 303;
   public static final int SC_NOT_MODIFIED = 304;
   public static final int SC_USE_PROXY = 305;
   public static final int SC_TEMPORARY_REDIRECT = 307;
 
   public static final int SC_BAD_REQUEST = 400;
   public static final int SC_UNAUTHORIZED = 401;
   public static final int SC_PAYMENT_REQUIRED = 402;
   public static final int SC_FORBIDDEN = 403;
   public static final int SC_NOT_FOUND = 404;
   public static final int SC_METHOD_NOT_ALLOWED = 405;
   public static final int SC_NOT_ACCEPTABLE = 406;
   public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
   public static final int SC_REQUEST_TIMEOUT = 408;
   public static final int SC_CONFLICT = 409;
   public static final int SC_GONE = 410;
   public static final int SC_LENGTH_REQUIRED = 411;
   public static final int SC_PRECONDITION_FAILED = 412;
   public static final int SC_REQUEST_ENTITY_TOO_LARGE = 413;
   public static final int SC_REQUEST_URI_TOO_LONG = 414;
   public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;
   public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
   public static final int SC_EXPECTATION_FAILED = 417;
 
   public static final int SC_INTERNAL_SERVER_ERROR = 500;
   public static final int SC_NOT_IMPLEMENTED = 501;
   public static final int SC_BAD_GATEWAY = 502;
  public static final int SC_SERVICE_UNAVAILABLE = 503;
  public static final int SC_GATEWAY_TIMEOUT = 504;
  public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
  // These content types can always skip encoding detection.
  private static final Set<StringBINARY_CONTENT_TYPES = ImmutableSet.of(
      "image/jpeg""image/png""image/gif""image/jpg""application/x-shockwave-flash",
      "application/octet-stream""application/ogg""application/zip""audio/mpeg",
      "audio/x-ms-wma""audio/vnd.rn-realaudio""audio/x-wav""video/mpeg""video/mp4",
      "video/quicktime""video/x-ms-wmv""video/x-flv""video/flv",
      "video/x-ms-asf""application/pdf"
  );
  // These HTTP status codes should always honor the HTTP status returned by the remote host. All
  // other error codes are treated as errors and will use the negativeCacheTtl value.
  private static final Set<IntegerNEGATIVE_CACHING_EXEMPT_STATUS
      = ImmutableSet.of();
  // TTL to use when an error response is fetched. This should be non-zero to
  // avoid high rates of requests to bad urls in high-traffic situations.
  static final long DEFAULT_NEGATIVE_CACHE_TTL = 30 * 1000;
  // Default TTL for an entry in the cache that does not have any cache control headers.
  static final long DEFAULT_TTL = 5L * 60L * 1000L;
  static final Charset DEFAULT_ENCODING = Charset.forName("UTF-8");
  @Inject(optional = true) @Named("shindig.cache.http.negativeCacheTtl")
  private static long negativeCacheTtl = ;
  @Inject(optional = true) @Named("shindig.cache.http.defaultTtl")
  private static long defaultTtl = ;
  @Inject(optional = true) @Named("shindig.http.fast-encoding-detection")
  private static boolean fastEncodingDetection = true;
  // Holds character sets for fast conversion
  private static final Map<StringCharsetencodingToCharset = new MapMaker().makeMap();
  private transient String responseString;
  private transient long date;
  private transient Charset encoding;
  private transient Map<StringStringmetadata;
  private int httpStatusCode;
  private Multimap<StringStringheaders;
  private byte[] responseBytes;

  
Needed for serialization. Do not use this for any other purpose.
  public HttpResponse() {}

  
Construct an HttpResponse from a builder (called by HttpResponseBuilder.create).
     = builder.getHttpStatusCode();
    Multimap<StringStringheaderCopy = HttpResponse.newHeaderMultimap();
    headerCopy.putAll(builder.getHeaders());
    // Always safe, HttpResponseBuilder won't modify the body.
     = builder.getResponse();
    Map<StringStringmetadataCopy = Maps.newHashMap(builder.getMetadata());
     = Collections.unmodifiableMap(metadataCopy);
    // We want to modify the headers to ensure that the proper Content-Type and Date headers
    // have been set. This allows us to avoid these expensive calculations from the cache.
     = getAndUpdateDate(headerCopy);
     = Multimaps.unmodifiableMultimap(headerCopy);
  }
  private HttpResponse(int httpStatusCodeString body) {
    this(new HttpResponseBuilder()
      .setHttpStatusCode(httpStatusCode)
      .setResponseString(body));
  }
  public HttpResponse(String body) {
    this(body);
  }
  public static HttpResponse error() {
    return new HttpResponse("");
  }
  public static HttpResponse timeout() {
    return new HttpResponse("");
  }
  public static HttpResponse notFound() {
    return new HttpResponse("");
  }
  public int getHttpStatusCode() {
    return ;
  }

  

Returns:
True if the status code is considered to be an error.
  public boolean isError() {
    return  >= 400;
  }

  

Returns:
The encoding of the response body, if we're able to determine it.
  public String getEncoding() {
    return .name();
  }

  

Returns:
the content length
  public int getContentLength() {
    return .;
  }

  

Returns:
An input stream suitable for reading the entirety of the response.
  public InputStream getResponse() {
    return new ByteArrayInputStream();
  }

  
Attempts to convert the response body to a string using the Content-Type header. If no Content-Type header is specified (or it doesn't include an encoding), we will assume it is DEFAULT_ENCODING.

Returns:
The body as a string.
  public String getResponseAsString() {
    if ( == null) {
      // Strip BOM if present
      if (.length() > 0 && .codePointAt(0) == 0xFEFF) {
      }
    }
    return ;
  }

  

Returns:
All headers for this object.
  public Multimap<StringStringgetHeaders() {
    return ;
  }

  

Returns:
All headers with the given name. If no headers are set for the given name, an empty collection will be returned.
  public Collection<StringgetHeaders(String name) {
    return .get(name);
  }

  

Returns:
The first set header with the given name or null if not set. If you need multiple values for the header, use getHeaders().
  public String getHeader(String name) {
    Collection<StringheaderList = getHeaders(name);
    if (headerList.isEmpty()) {
      return null;
    } else {
      return headerList.iterator().next();
    }
  }

  

Returns:
additional data to embed in responses sent from the JSON proxy.
  public Map<StringStringgetMetadata() {
    return ;
  }

  

Returns:
consolidated cache expiration time or -1
  public long getCacheExpiration() {
    // We intentionally ignore cache-control headers for most HTTP error responses, because if
    // we don't we end up hammering sites that have gone down with lots of requests. Certain classes
    // of client errors (authentication) have more severe behavioral implications if we cache them.
      return  + ;
    }
    // We technically shouldn't be caching certain 300 class status codes either, such as 302, but
    // in practice this is a better option for performance.
    if (isStrictNoCache()) {
      return -1;
    }
    long maxAge = getCacheControlMaxAge();
    if (maxAge != -1) {
      return  + maxAge;
    }
    long expiration = getExpiresTime();
    if (expiration != -1) {
      return expiration;
    }
    return  + ;
  }

  

Returns:
Consolidated ttl or -1.
  public long getCacheTtl() {
    long expiration = getCacheExpiration();
    if (expiration != -1) {
      return expiration - System.currentTimeMillis();
    }
    return -1;
  }

  

Returns:
True if this result is stale.
  public boolean isStale() {
    return getCacheTtl() <= 0;
  }

  

Returns:
true if a strict no-cache header is set in Cache-Control or Pragma
  public boolean isStrictNoCache() {
      return false;
    }
    String cacheControl = getHeader("Cache-Control");
    if (cacheControl != null) {
      String[] directives = cacheControl.split(",");
      for (String directive : directives) {
        directive = directive.trim();
        if (directive.equalsIgnoreCase("no-cache")
            || directive.equalsIgnoreCase("no-store")
            || directive.equalsIgnoreCase("private")) {
          return true;
        }
      }
    }
    for (String pragma : getHeaders("Pragma")) {
      if ("no-cache".equalsIgnoreCase(pragma)) {
        return true;
      }
    }
    return false;
  }

  

Returns:
the expiration time from the Expires header or -1 if not set
  private long getExpiresTime() {
    String expires = getHeader("Expires");
    if (expires != null) {
      Date expiresDate = DateUtil.parseRfc1123Date(expires);
      if (expiresDate != null) {
        return expiresDate.getTime();
      }
    }
    return -1;
  }

  

Returns:
max-age value or -1 if invalid or not set
  private long getCacheControlMaxAge() {
    String cacheControl = getHeader("Cache-Control");
    if (cacheControl != null) {
      String[] directives = cacheControl.split(",");
      for (String directive : directives) {
        directive = directive.trim();
        if (directive.startsWith("max-age")) {
          String[] parts = directive.split("=");
          if (parts.length == 2) {
            try {
              return Long.parseLong(parts[1]) * 1000;
            } catch (NumberFormatException ignore) {
              return -1;
            }
          }
        }
      }
    }
    return -1;
  }

  
Tries to find a valid date from the input headers.

Returns:
The value of the date header, in milliseconds, or -1 if no Date could be determined.
  private static long getAndUpdateDate(Multimap<StringStringheaders) {
    // Validate the Date header. Must conform to the HTTP date format.
    long timestamp = -1;
    Collection<Stringdates = headers.get("Date");
    if (!dates.isEmpty()) {
      Date d = DateUtil.parseRfc1123Date(dates.iterator().next());
      if (d != null) {
        timestamp = d.getTime();
      }
    }
    if (timestamp == -1) {
      timestamp = System.currentTimeMillis();
      headers.put("Date", DateUtil.formatRfc1123Date(timestamp));
    }
    return timestamp;
  }

  
Attempts to determine the encoding of the body. If it can't be determined, we use DEFAULT_ENCODING instead.

Returns:
The detected encoding or DEFAULT_ENCODING.
  private static Charset getAndUpdateEncoding(Multimap<StringStringheadersbyte[] body) {
    if (body == null || body.length == 0) {
      return ;
    }
    Collection<Stringvalues = headers.get("Content-Type");
    if (!values.isEmpty()) {
      String contentType = values.iterator().next();
      String[] parts = contentType.split(";");
      if (.contains(parts[0])) {
        return ;
      }
      if (parts.length == 2) {
        int offset = parts[1].indexOf("charset=");
        if (offset != -1) {
          String charset = parts[1].substring(offset + 8).toUpperCase();
          // Some servers include quotes around the charset:
          //   Content-Type: text/html; charset="UTF-8"
          if (charset.charAt(0) == '"') {
            charset = charset.substring(1, charset.length() - 1);
          }
          
          try {
            return charsetForName(charset);
          } catch (IllegalArgumentException e) {
            // fall through to detection
          }
        }
      }
      Charset encoding = EncodingDetector.detectEncoding(body);
      // Record the charset in the content-type header so that its value can be cached
      // and re-used. This is a BIG performance win.
      values.clear();
      values.add(contentType + "; charset=" + encoding.name());
      return encoding;
    } else {
      // If no content type was specified, we'll assume an unknown binary type.
      return ;
    }
  }

  
Cover for Charset.forName() that caches results.

Returns:
the charset
Throws:
IllegalArgumentException if the encoding is invalid
  private static Charset charsetForName(String encoding) {
    Charset charset = .get(encoding);
    if (charset == null) {
      charset = Charset.forName(encoding);
      .put(encodingcharset);
    }
    
    return charset;
  }
  
  public boolean equals(Object obj) {
    if (obj == this) { return true; }
    if (!(obj instanceof HttpResponse)) { return false; }
    HttpResponse response = (HttpResponse)obj;
    return  == response.httpStatusCode &&
           .equals(response.headers) &&
           Arrays.equals(response.responseBytes);
  }
  public String toString() {
    StringBuilder buf = new StringBuilder("HTTP/1.1 ").append().append("\r\n\r\n");
    for (Map.Entry<String,Stringentry : .entries()) {
      buf.append(entry.getKey()).append(": ").append(entry.getValue()).append("\r\n");
    }
    buf.append("\r\n").append(getResponseAsString()).append("\r\n");
    return buf.toString();
  }

  

Returns:
The response as a byte array. Only visible to the package to avoid copying when making a new HttpResponseBuilder.
  byte[] getResponseAsBytes() {
    return ;
  }

  
Expected layout: int - status code Map<String, List<String>> - headers int - length of body byte array - body, of previously specified length
  @SuppressWarnings("unchecked")
  public void readExternal(ObjectInput inthrows IOExceptionClassNotFoundException {
     = in.readInt();
    // We store the multimap as a Map<String,List<String>> to insulate us from google-collections API churn
    // And to remain backwards compatible
    Map<StringList<String>> headerCopyMap = (Map<StringList<String>>)in.readObject();
    Multimap headerCopy = newHeaderMultimap();
    for (Map.Entry<String,List<String>> entry : headerCopyMap.entrySet()) {
      headerCopy.putAll(entry.getKey(), entry.getValue());
    }
    int bodyLength = in.readInt();
     = new byte[bodyLength];
    int cntoffset = 0;
    while ((cnt = in.read(offsetbodyLength)) > 0) {
   	 offset += cnt;
   	 bodyLength -= cnt;
    }
    if (offset != .) {
    	throw new IOException("Invalid body! Expected length = " + . + ", bytes readed = " + offset + '.'); 
    }
     = getAndUpdateDate(headerCopy);
     = Multimaps.unmodifiableMultimap(headerCopy);
     = Collections.emptyMap();
  }
  public void writeExternal(ObjectOutput outthrows IOException {
    // Write out multimap as a map (see above)
    Map<String,List<String>> map = Maps.newHashMap();
    for (String key : .keySet()) {
      map.put(key, Lists.newArrayList(.get(key)));
    }
    out.writeObject(Maps.newHashMap(map));
    out.write();
  }
  private static final Supplier<Collection<String>> HEADER_COLLECTION_SUPPLIER = new HeaderCollectionSupplier();
  private static class HeaderCollectionSupplier implements Supplier<Collection<String>> {
    public Collection<Stringget() {
      return new LinkedList<String>();  //To change body of implemented methods use File | Settings | File Templates.
    }
  }
  public static Multimap<String,StringnewHeaderMultimap() {
    TreeMap<String,Collection<String>> map = Maps.newTreeMap(.);
    return Multimaps.newMultimap(map);
  }
New to GrepCode? Check out our FAQ X