All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.granite.httpcache.api.Headers Maven / Gradle / Ivy

/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2012 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/

package com.adobe.granite.httpcache.api;

import org.apache.commons.lang.time.FastDateFormat;

import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

/**
 * Container class for HTTP headers.
 */
public class Headers {

    private final List entries = new ArrayList(16);

    /** GMT Timezone. */
    private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
    
    /** Date formatter. */
    private static final FastDateFormat RFC1123 =
            FastDateFormat.getInstance("EEE, dd MMM yyyy HH:mm:ss z", GMT, Locale.US);

    /**
     * A header entry.
     */
    public static class Entry {
        
        public static enum Type {
            STRING, LONG, INT
        };
        
        final String name;
        final Type type;
        private String s;
        private long l;
        private int i;
        
        Entry(String name, String value) {
            this.type = Type.STRING;
            this.name = name;
            this.s = value;
        }

        Entry(String name, long value) {
            this.type = Type.LONG;
            this.name = name;
            this.l = value;
        }
        
        Entry(String name, int value) {
            this.type = Type.INT;
            this.name = name;
            this.i = value;
        }
        
        /**
         * Return the string representation of this entry's value. If the value's
         * type is not STRING, it is converted to a string as follows:
         * 
    *
  • a long is formatted as a date in RFC1123 format
  • *
  • an integer is formatted as decimal number
  • *
* * @return string representation */ public String getString() { switch (type) { case STRING: return s; case LONG: return RFC1123.format(l); case INT: return String.valueOf(i); default: throw new InternalError("Illegal type: " + type); } } /** * Return a long value if the type is LONG, otherwise -1 * * @return long */ public long getLong() { if (type == Type.LONG) { return l; } return -1; } /** * Return an integer value if the type is INT, otherwise 0 * * @return integer */ public int getInt() { if (type == Type.INT) { return i; } return 0; } /** * Return the header type. * * @return type */ public Type getType() { return type; } /** * Return the header name. * * @return name */ public String getName() { return name; } @Override public String toString() { StringBuilder s = new StringBuilder(32); s.append(name); s.append(": "); s.append(getString()); return s.toString(); } } /** * Return the first header matching a given name. * * @param name * name * @return value of header or null */ public String getHeader(String name) { for (int i = 0; i < entries.size(); i++) { Entry e = entries.get(i); if (e.name.equalsIgnoreCase(name)) { return e.getString(); } } return null; } /** * Return all headers matching a given name. * * @param name name * @return matching values or null */ public String[] getHeaders(String name) { ArrayList values = null; for (int i = 0; i < entries.size(); i++) { Entry e = entries.get(i); if (e.name.equalsIgnoreCase(name)) { if (values == null) { values = new ArrayList(); } values.add(e.getString()); } } if (values != null) { String[] result = new String[values.size()]; return values.toArray(result); } return null; } /** * Return the first header matching a given name. * * @param name name * @return value of date header or -1 */ public long getDateHeader(String name) { for (int i = 0; i < entries.size(); i++) { Entry e = entries.get(i); if (e.name.equalsIgnoreCase(name)) { return e.getLong(); } } return -1; } /** * Return the first header matching a given name. * * @param name name * @return value of date header or 0 */ public int getIntHeader(String name) { for (int i = 0; i < entries.size(); i++) { Entry e = entries.get(i); if (e.name.equalsIgnoreCase(name)) { return e.getInt(); } } return 0; } /** * Set a header. This will replace the first existing entry or add * a new one. * * @param name name * @param value value, if null remove an existing header */ public void setHeader(String name, String value) { if (value == null) { for (int i = 0; i < entries.size(); i++) { if (entries.get(i).name.equalsIgnoreCase(name)) { entries.remove(i); } } return; } setHeader(new Entry(name, value)); } /** * Set a header. This will replace the first existing entry or add * a new one. * * @param name name * @param value value */ public void setHeader(String name, long value) { setHeader(new Entry(name, value)); } /** * Set a header. This will replace the first existing entry or add * a new one. * * @param name name * @param value value */ public void setHeader(String name, int value) { setHeader(new Entry(name, value)); } private void setHeader(Entry e) { for (int i = 0; i < entries.size(); i++) { if (entries.get(i).name.equalsIgnoreCase(e.name)) { entries.set(i, e); return; } } entries.add(e); } /** * Add a header. * * @param name name * @param value value */ public void addHeader(String name, String value) { entries.add(new Entry(name, value)); } /** * Add a header. * * @param name name * @param value value */ public void addHeader(String name, long value) { entries.add(new Entry(name, value)); } /** * Add a header. * * @param name name * @param value value */ public void addHeader(String name, int value) { entries.add(new Entry(name, value)); } /** * Return all entries. * * @return entries */ public Entry[] getEntries() { Entry[] result = new Entry[entries.size()]; entries.toArray(result); return result; } //----------------------------------------------------------- Serialization // TODO: should the serialization format be customizable? /** * Store headers to an output stream. * * @param out output stream * @throws java.io.IOException if an I/O error occurs */ public void save(OutputStream out) throws IOException { // Store data in a byte array first ByteArrayOutputStream bout = new ByteArrayOutputStream(256); writeShort(bout, entries.size()); for (int i = 0; i < entries.size(); i++) { Entry e = entries.get(i); writeString(bout, e.name); switch (e.type) { case STRING: bout.write('S'); writeString(bout, e.getString()); break; case LONG: bout.write('L'); writeLong(bout, e.getLong()); break; case INT: bout.write('I'); writeInt(bout, e.getInt()); break; default: throw new InternalError("Illegal type: " + e.type); } } out.write(bout.toByteArray()); } private static void writeShort(OutputStream out, int n) throws IOException { if (n > 65535) { throw new IOException("Number too big to be saved as short: " + n); } out.write((n >>> 8) & 0xFF); out.write((n >>> 0) & 0xFF); } private static void writeString(OutputStream out, String s) throws IOException { byte[] b = s.getBytes("8859_1"); writeShort(out, b.length); out.write(b); } private static void writeInt(OutputStream out, int n) throws IOException { out.write((n >>> 24) & 0xff); out.write((n >>> 16) & 0xff); out.write((n >>> 8) & 0xff); out.write((n >>> 0) & 0xff); } private static void writeLong(OutputStream out, long l) throws IOException { writeInt(out, (int) (l >>> 32)); writeInt(out, (int) l & 0xffffffff); } /** * Load stored headers from an input stream. * * @param in input stream * @throws java.io.IOException if an I/O error occurs */ public void load(InputStream in) throws IOException { int count = readUnsignedShort(in); for (int i = 0; i < count; i++) { String name = readString(in); char ch = (char) in.read(); switch (ch) { case 'S': addHeader(name, readString(in)); break; case 'L': addHeader(name, readLong(in)); break; case 'I': addHeader(name, readInt(in)); break; default: throw new InternalError("Illegal type: " + ch); } } } private static int readUnsignedShort(InputStream in) throws IOException { int ch1 = in.read(); int ch2 = in.read(); if ((ch1 | ch2) < 0) { throw new EOFException(); } return (ch1 << 8) + (ch2 << 0); } private static int readInt(InputStream in) throws IOException { int ch1 = in.read(); int ch2 = in.read(); int ch3 = in.read(); int ch4 = in.read(); if ((ch1 | ch2 | ch3 | ch4) < 0) { throw new EOFException(); } return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); } private static long readLong(InputStream in) throws IOException { long h = readInt(in) & 0xffffffffL; long l = readInt(in) & 0xffffffffL; return h << 32 | l; } private static String readString(InputStream in) throws IOException { byte[] b = new byte[readUnsignedShort(in)]; int off = 0; while (off < b.length) { int len = in.read(b, off, b.length - off); if (len == -1) { throw new EOFException(); } off += len; } return new String(b, "8859_1"); } @Override public String toString() { StringBuilder s = new StringBuilder(256); for (Entry e : entries) { s.append(e.toString()); s.append("\r\n"); } return s.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy