/* * Copyright (c) 2005-2011 Clark & Parsia, LLC. <http://www.clarkparsia.com> * * Licensed 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 com.complexible.common.web; import com.complexible.common.util.Tuple; import com.google.common.base.Splitter; import com.google.common.collect.Lists; import java.util.Collection; import java.util.LinkedList; import java.util.Map; import java.util.HashMap; import java.util.List; import java.util.Collections; /** * <p>Represents an HTTP header, either from a request or a response.</p> * * @author Michael Grove * @see Request * @see Response * @since 1.0 * @version 2.0 */ @Deprecated public final class Header { /** * The name of the header. {@link HttpHeaders} is an enumeration of common header names. */ private String mName; /** * The list of values for the header */ private Map<String, String> mValues = new HashMap<String, String>(); /** * The list of raw values for the header (i.e., before parsing/splitting) */ private List<String> mRawValues = new LinkedList<String>(); /** * Create a new HTTP header * @param theName the name of the header attribute * @param theValue the singleton value of the header */ public Header(final String theName, String theValue) { mName = theName; addValue(theValue); } /** * Create a new HTTP header * @param theName the name of the header attribute * @param theValues the values of the HTTP header */ public Header(final String theName, final List<String> theValues) { mName = theName; for (String aValue : theValues) { addValue(aValue); } } /** * Create a new HTTP header * @param theName the name of the header attribute * @param theValues the values of the HTTP header */ public Header(final String theName, final Map<String, String> theValues) { mName = theName; mValues = theValues; // at this point there is no information about "raw" values // (need to "recreate" the "raw" version) mRawValues.add(mapToValue(theValues)); } /** * Add a key-value pair to this header * @param theName the name of the header element * @param theValue the value of the element * @return this Header object */ public Header addValue(String theName, String theValue) { addValues(Collections.singletonMap(theName, theValue)); return this; } /** * Add a value to the header * @param theValue the value to add */ void addValue(String theValue) { if (theValue == null) { return; } if (theValue.indexOf(";") != -1) { for (String aKeyValuePair : Splitter.on(";").trimResults().omitEmptyStrings().split(theValue)) { Tuple aTuple = split(aKeyValuePair); mValues.put(aTuple.<String>get(0), (aTuple.length() < 2 ? null : aTuple.<String>get(1))); } } else if (theValue.indexOf("=") != -1) { Tuple aTuple = split(theValue); mValues.put(aTuple.<String>get(0), (aTuple.length() < 2 ? null : aTuple.<String>get(1))); } else { mValues.put(null, theValue); } mRawValues.add(theValue); } /** * Add all the values to the header * @param theValues the values to add */ void addValues(Map<String, String> theValues) { mValues.putAll(theValues); // at this point there is no information about "raw" values // (need to "recreate" the "raw" version) mRawValues.add(mapToValue(theValues)); } /** * The name of the HTTP header. Common HTTP header names can be found in {@link HttpHeaders} * @return the header name */ public String getName() { return mName; } /** * Returns the values of the HTTP header * @return the header values */ public Map<String, String> getValues() { return mValues; } /** * Return the raw values of the HTTP header (i.e., before any processing/splitting has * occurred). * * @return the list of raw header values (one for each header occurrence) */ public Collection<String> getRawValues() { return mRawValues; } /** * Return the value of the header element * @param theKey the name of the header element, or null to get the value of the header * @return the value, or null if one is not specified */ public String getValue(String theKey) { return getValues().get(theKey); } /** * Splits the key-value string on the = sign. * @param theKeyValue the key/value string * @return a 2-tuple of strings with the key and value. */ private Tuple split(String theKeyValue) { List<String> aStrings = Lists.newArrayList(Splitter .on("=") .trimResults() .omitEmptyStrings() .split(theKeyValue)); return new Tuple((Object[])aStrings.toArray(new String[aStrings.size()])); } /** * Return the value(s) of the header as a semi-colon separated string. For example, if your values are "foo", "bar" * and "baz" this will return the string "foo; bar; baz" * @return the string encoded reprsentation of the header values suitable for insertion into a HTTP request */ public String getHeaderValue() { return mapToValue(getValues()); } /** * Converts a map of key-value pairs to a semi-colon separated string. For example, if your values are "foo", "bar" * and "baz" this will return the string "foo; bar; baz" * @param theValues a map to be converted * @return the string encoded reprsentation of the header values suitable for insertion into a HTTP request */ private static String mapToValue(Map<String,String> theValues) { StringBuffer aBuffer = new StringBuffer(); boolean aFirst = true; for (Map.Entry<String, String> aEntry : theValues.entrySet()) { if (!aFirst) { aBuffer.append("; "); } aFirst = false; if (aEntry.getKey() != null) { aBuffer.append(aEntry.getKey()).append("="); } aBuffer.append(aEntry.getValue()); } return aBuffer.toString(); } /** * Return a raw header value (i.e., before any processing/splitting). If the header was mentioned * multiple times, this method returns all the header values concatenated together and separated by a comma * (RFC 2616, Section 4.2 Message Headers: "It MUST be possible to combine the multiple header fields into one * (..) without changing the semantics of the message, by appending each subsequent field-value to the first, * each separated by a comma"). * * @return a single string that contain the raw header values concatenated together, separated by a comma */ public String getRawHeaderValue() { StringBuffer aBuffer = new StringBuffer(); boolean aFirst = true; for (String aRawValue : getRawValues()) { if (!aFirst) { aBuffer.append(", "); } aFirst = false; aBuffer.append(aRawValue); } return aBuffer.toString(); } /** * @inheritDoc */ @Override public String toString() { return getName() + " [" + getHeaderValue() + "]"; } }