org.refcodes.web.AbstractHeaderFields Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of refcodes-web Show documentation
Show all versions of refcodes-web Show documentation
This artifact provides web (HTTP) related definitions and types being used
by REFCODES.ORG web related functionality and artifacts.
The newest version!
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// /////////////////////////////////////////////////////////////////////////////
// This code is copyright (c) by Siegfried Steiner, Munich, Germany, distributed
// on an "AS IS" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, and licen-
// sed under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// -----------------------------------------------------------------------------
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// -----------------------------------------------------------------------------
// Apache License, v2.0 ("http://www.apache.org/licenses/TEXT-2.0")
// -----------------------------------------------------------------------------
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////
package org.refcodes.web;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.refcodes.data.Delimiter;
/**
* Abstract implementation of the {@link HeaderFields} type.
*
* @param The {@link Cookie} type to be used by sub-classes.
* @param The type of the sub-class, required for the builder methods such
* as {@link #withHost(String)}.
*/
@SuppressWarnings("serial")
public abstract class AbstractHeaderFields> extends AbstractHttpFields implements HeaderFields {
// /////////////////////////////////////////////////////////////////////////
// VARIABLES:
// /////////////////////////////////////////////////////////////////////////
private final List _cookies = new ArrayList<>();
// /////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS:
// /////////////////////////////////////////////////////////////////////////
/**
* Instantiates a new abstract Header-Fields.
*/
public AbstractHeaderFields() {}
/**
* Instantiates a new abstract Header-Fields.
*
* @param aHttpFields the http fields
*/
public AbstractHeaderFields( Map> aHttpFields ) {
toHeaderFields( aHttpFields, this );
}
// /////////////////////////////////////////////////////////////////////////
// METHODS:
// /////////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
@Override
public List get( Object aKey ) {
final String theKey = toHeaderField( aKey );
// Cookie Header-Field bypass |-->
if ( theKey != null && theKey.equalsIgnoreCase( getCookieFieldName() ) ) {
final String[] theCookies = toHttpCookies();
if ( theCookies != null ) {
return new ArrayList<>( Arrays.asList( theCookies ) );
}
else {
return null;
}
}
// <--| Cookie Header-Field bypass
return super.get( theKey );
}
/**
* {@inheritDoc}
*/
@Override
public Set keySet() {
if ( _cookies.size() != 0 ) {
final Set theKeySet = new HashSet<>( super.keySet() );
theKeySet.add( getCookieFieldName() );
return theKeySet;
}
return super.keySet();
}
/**
* {@inheritDoc}
*/
@Override
public Set>> entrySet() {
if ( _cookies.size() != 0 ) {
final String[] theCookies = toHttpCookies();
if ( theCookies != null ) {
final Set>> theEntrySet = new HashSet<>( super.entrySet() );
theEntrySet.add( new Field( getCookieFieldName(), new ArrayList( Arrays.asList( theCookies ) ) ) );
return theEntrySet;
}
}
return super.entrySet();
}
/**
* {@inheritDoc}
*/
@Override
public List put( String aKey, List aValue ) {
final String theKey = toHeaderField( aKey );
// Cookie Header-Field bypass |-->
if ( theKey != null && theKey.equalsIgnoreCase( getCookieFieldName() ) ) {
synchronized ( _cookies ) {
List theCookieFields = null;
if ( _cookies != null && _cookies.size() != 0 ) {
theCookieFields = new ArrayList<>();
for ( C eCookie : _cookies ) {
theCookieFields.add( eCookie.toHttpCookie() );
}
}
_cookies.clear();
for ( String aHttpCookie : aValue ) {
addCookie( createCookie( aHttpCookie ) );
}
return theCookieFields;
}
}
// <--| Cookie Header-Field bypass
return super.put( theKey, aValue );
}
/**
* {@inheritDoc}
*/
@Override
public void addTo( String aHeaderField, String aValue ) {
final String theKey = toHeaderField( aHeaderField );
// Cookie Header-Field bypass |-->
if ( theKey.equals( getCookieFieldName() ) ) {
addCookie( createCookie( aValue ) );
}
// <--| Cookie Header-Field bypass
else {
HeaderFields.super.addTo( theKey, aValue );
}
}
/**
* {@inheritDoc}
*/
@Override
public C addCookie( C aCookie ) {
_cookies.add( aCookie );
return aCookie;
}
/**
* {@inheritDoc}
*/
@Override
public List getAllCookies() {
return _cookies;
}
/**
* {@inheritDoc}
*/
@Override
public C addCookie( String aCookieName, String aValue ) {
return addCookie( createCookie( aCookieName, aValue ) );
}
/**
* {@inheritDoc}
*/
@Override
public void putAll( Map extends String, ? extends List> aMap ) {
// As the field names are varying their case, we must go this way:
List eValues;
for ( String eKey : aMap.keySet() ) {
eValues = aMap.get( eKey );
eKey = HeaderField.toHttpHeaderField( eKey );
if ( getCookieFieldName().equalsIgnoreCase( eKey ) ) {
if ( eValues != null && !eValues.isEmpty() ) {
for ( String eHttpCookie : eValues ) {
addCookie( eHttpCookie );
}
}
}
else {
put( eKey, new ArrayList( eValues ) );
}
}
}
// /////////////////////////////////////////////////////////////////////////
// HOOKS:
// /////////////////////////////////////////////////////////////////////////
/**
* Tests the given HTTP Header-Field name whether it holds a comma separated
* value. You may overwrite this method and add your own implementation or
* extend this method by overwriting it and calling it in you overwritten
* method.
*
* @param aHeaderName The name of the header to be tested.
*
* @return True if the value being held by the given Header-Field name is a
* comma separated list.
*/
protected static boolean isCommaSeparatedHeaderField( String aHeaderName ) {
return HeaderField.ACCEPT.getName().equalsIgnoreCase( aHeaderName ) || HeaderField.COOKIE.getName().equalsIgnoreCase( aHeaderName ) || HeaderField.SET_COOKIE.getName().equalsIgnoreCase( aHeaderName );
}
/**
* Copies the provided "from" fields into the provided "to" fields. Omits
* empty or null values.
*
* @param aFromFields The fields from which to copy.
* @param aToFields The fields to which to copy.
*/
protected static void toHeaderFields( Map> aFromFields, HeaderFields, ?> aToFields ) {
List eValues;
String eElement;
for ( String eKey : aFromFields.keySet() ) {
eValues = aFromFields.get( eKey );
eKey = HeaderField.toHttpHeaderField( eKey );
if ( eValues != null ) {
final Iterator e = eValues.iterator();
while ( e.hasNext() ) {
eElement = e.next();
if ( eElement != null && eElement.trim().length() != 0 ) {
// Do https://www.metacodes.pro Header-Fields processing |-->
// Question: Which Header-Fields are known to be comma
// separated?
if ( isCommaSeparatedHeaderField( eKey ) ) {
final String[] eElements = eElement.split( "" + Delimiter.HTTP_HEADER_ELEMENTS.getChar() );
aToFields.addTo( eKey, eElements );
}
// <--| Do https://www.metacodes.pro Header-Fields processing
else {
aToFields.addTo( eKey, eElement );
}
}
}
}
}
}
/**
* Normalizes the case of the provided Header-Field to conform to the
* {@link HeaderField#getName()} format if possible. Else the unmodified
* Header-Field is returned.
*
* @param aHeaderField The field to normalize.
*
* @return The Header-Field, in case of normalization the normalized one.
*/
protected String toHeaderField( Object aHeaderField ) {
final String theHeaderField;
if ( aHeaderField == null ) {
return null;
}
theHeaderField = !( aHeaderField instanceof String ) ? aHeaderField.toString() : (String) aHeaderField;
return HeaderField.toHttpHeaderField( theHeaderField );
}
/**
* The Header-Field name for the {@link Cookie} elements. The Header-Field
* name differs from the context, e.g. when setting a {@link Cookie}
* server-side or when retrieving a {@link Cookie} client-side.
*
* @return The Header-Field where the {@link Cookie} elements are stored.
*/
protected abstract String getCookieFieldName();
/**
* Creates a plain {@link Cookie} with the given name and value.
*
* @param aCookieName The name of the {@link Cookie}.
* @param aValue The value for the {@link Cookie}
*
* @return The {@link Cookie} with the given name and value.
*/
protected abstract C createCookie( String aCookieName, String aValue );
/**
* Creates a {@link Cookie} from the given HTTP cookie {@link String} as
* retrieved from the according Header-Field.
*
* @param aHttpCookie The text of the Header-Field for the cookie to be
* created.
*
* @return The {@link Cookie} with the given cookie properties.
*/
protected abstract C createCookie( String aHttpCookie );
// /////////////////////////////////////////////////////////////////////////
// INNER CLASSES:
// /////////////////////////////////////////////////////////////////////////
/**
* The Class EntryImpl.
*/
private static class Field implements Entry> {
private final String _key;
private List _value;
/**
* Instantiates a new entry impl.
*
* @param aKey the key
* @param aValue the value
*/
public Field( String aKey, List aValue ) {
_key = aKey;
_value = aValue;
}
/**
* Gets the key.
*
* @return the key
*/
@Override
public String getKey() {
return _key;
}
/**
* Gets the value.
*
* @return the value
*/
@Override
public List getValue() {
return _value;
}
/**
* Sets the value.
*
* @param value the value
*
* @return the list
*/
@Override
public List setValue( List value ) {
final List theReturn = _value;
_value = value;
return theReturn;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy