/* * JLibs: Common Utilities for Java * Copyright (C) 2009 Santhosh Kumar T <santhosh.tekuri@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package jlibs.nio.http.msg; import jlibs.core.lang.Util; import jlibs.nio.http.SocketPayload; import jlibs.nio.http.expr.Bean; import jlibs.nio.http.expr.UnresolvedException; import jlibs.nio.http.util.ContentDisposition; import jlibs.nio.http.util.Encoding; import jlibs.nio.http.util.MediaType; import jlibs.nio.http.util.Parser; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Collection; import java.util.List; import java.util.function.Function; /** * @author Santhosh Kumar Tekuri */ public abstract class Message implements Bean{ public Version version = Version.HTTP_1_1; public final Headers headers = new Headers(); public Headers trailers; public abstract void putLineInto(ByteBuffer buffer); public abstract Status badMessageStatus(); public RuntimeException badMessage(String message){ return badMessageStatus().with(message); } public RuntimeException badMessage(Throwable thr){ return badMessageStatus().with(thr); } public abstract Status timeoutStatus(); /*-------------------------------------------------[ Bean ]---------------------------------------------------*/ @Override @SuppressWarnings("StringEquality") public Object getField(String name) throws UnresolvedException{ if(name=="headers") return headers; else if(name=="version") return version; else if(name=="keep_alive") return isKeepAlive(); else if(name=="content_length") return getContentLength(); else if(name=="content_type") return getMediaType(); else throw new UnresolvedException(name); } /*-------------------------------------------------[ Payload ]---------------------------------------------------*/ private Payload payload = EmptyPayload.INSTANCE; public Payload getPayload(){ return payload; } public void setPayload(Payload payload) throws IOException{ if(this.payload instanceof SocketPayload) ((SocketPayload)this.payload).socket().close(); this.payload = payload; } /*-------------------------------------------------[ Connection ]---------------------------------------------------*/ public static final AsciiString CONNECTION = new AsciiString("Connection"); public static final AsciiString PROXY_CONNECTION = new AsciiString("Proxy-Connection"); public static final String CLOSE = "close"; public static final String KEEP_ALIVE = "keep-alive"; public boolean isKeepAlive(){ String value = headers.value(CONNECTION); if(version.keepAliveDefault) return !(value!=null && CLOSE.equalsIgnoreCase(value)); else return value!=null && KEEP_ALIVE.equalsIgnoreCase(value); } public void setKeepAlive(boolean keepAlive){ String value; if(version.keepAliveDefault) value = keepAlive ? null : CLOSE; else value = keepAlive ? KEEP_ALIVE : null; if(value==null) headers.remove(CONNECTION); else headers.set(CONNECTION, value); } /*-------------------------------------------------[ Content-Length ]---------------------------------------------------*/ // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13 public static final AsciiString CONTENT_LENGTH = new AsciiString("Content-Length"); public long getContentLength(){ String value = headers.value(CONTENT_LENGTH); return value==null? -1 : Util.parseLong(value); } public void setContentLength(long length){ if(length<0) headers.remove(CONTENT_LENGTH); else{ headers.remove(TRANSFER_ENCODING); headers.set(CONTENT_LENGTH, length==0 ? "0" : Long.toString(length)); } } /*-------------------------------------------------[ Transfer-Encoding ]---------------------------------------------------*/ // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.41 public static final AsciiString TRANSFER_ENCODING = new AsciiString("Transfer-Encoding"); public static final String IDENTITY = "identity"; public static final String CHUNKED = "chunked"; public boolean isChunked(){ String value = headers.value(TRANSFER_ENCODING); return value!=null && !IDENTITY.equalsIgnoreCase(value); } public void setChunked(){ headers.remove(CONTENT_LENGTH); headers.set(TRANSFER_ENCODING, CHUNKED); } /*-------------------------------------------------[ Content-Encoding ]---------------------------------------------------*/ // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11 public static final AsciiString CONTENT_ENCODING = new AsciiString("Content-Encoding"); protected static final Function<Parser, Encoding> encodingDelegate = Parser.lvalueDelegate(Encoding::valueOf); public List<Encoding> getContentEncodings(){ return headers.getListValue(CONTENT_ENCODING, encodingDelegate, true); } public void setContentEncodings(Collection<Encoding> encodings){ headers.setListValue(CONTENT_ENCODING, encodings, null, true); } /*-------------------------------------------------[ Content-Type ]---------------------------------------------------*/ // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17 public static final AsciiString CONTENT_TYPE = new AsciiString("Content-Type"); public MediaType getMediaType(){ return headers.getSingleValue(CONTENT_TYPE, MediaType::new); } public void setMediaType(MediaType mt){ headers.setSingleValue(CONTENT_TYPE, mt, null); } /*-------------------------------------------------[ Content-Disposition ]---------------------------------------------------*/ // http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1 public static final AsciiString CONTENT_DISPOSITION = new AsciiString("Content-Disposition"); public ContentDisposition getContentDisposition(){ return headers.getSingleValue(CONTENT_DISPOSITION, ContentDisposition::new); } public void setContentDisposition(ContentDisposition cd){ headers.setSingleValue(CONTENT_DISPOSITION, cd, null); } // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9 public static final AsciiString CACHE_CONTROL = new AsciiString("Cache-Control"); // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.15 public static final AsciiString CONTENT_MD5 = new AsciiString("Content-MD5"); }