001/* 002 * This file is part of the JDrupes non-blocking HTTP Codec 003 * Copyright (C) 2016, 2017 Michael N. Lipp 004 * 005 * This program is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Lesser General Public License as published 007 * by the Free Software Foundation; either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, but 011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 013 * License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License along 016 * with this program; if not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jdrupes.httpcodec; 020 021import java.nio.ByteBuffer; 022 023/** 024 * The base interface for all coders and decoders. 025 */ 026public interface Codec { 027 028 /** 029 * An empty input buffer that can be used for codec invocations 030 * when the (expected) body data is not yet available. 031 */ 032 public static final ByteBuffer EMPTY_IN = ByteBuffer.allocate(0); 033 034 /** 035 * The common properties of the result types returned by the various codecs. 036 * Derived classes add their respective additional values. 037 * 038 * The class is declared abstract to promote the usage of the factory 039 * method. 040 */ 041 public abstract static class Result { 042 043 private boolean overflow; 044 private boolean underflow; 045 private boolean closeConnection; 046 047 /** 048 * Creates a new result with the given values. 049 * 050 * @param overflow 051 * {@code true} if the data didn't fit in the out buffer 052 * @param underflow 053 * {@code true} if more data is expected 054 * @param closeConnection 055 * {@code true} if the connection should be closed 056 */ 057 protected Result(boolean overflow, boolean underflow, 058 boolean closeConnection) { 059 super(); 060 this.overflow = overflow; 061 this.underflow = underflow; 062 this.closeConnection = closeConnection; 063 } 064 065 /** 066 * Indicates that the data didn't fit in the out buffer. The encoding 067 * method that has returned this result should be re-invoked with the 068 * same parameters except for a new (or cleared) output buffer. 069 * 070 * @return {@code true} if overflow occurred 071 * @see #isUnderflow() 072 */ 073 public boolean isOverflow() { 074 return overflow; 075 } 076 077 /** 078 * Indicates that more data is needed to complete the encoding or 079 * decoding of the entity. 080 * <P> 081 * {@code Codec}s may report an underflow 082 * condition even if there is still data available in the input 083 * buffer in order to report some special condition in an extended 084 * result type. In this case, the encode or decode method should 085 * be reinvoked with the same parameters after handling the special 086 * condition that has been reported. 087 * <P> 088 * If underflow is reported and the input buffer is empty, the 089 * encode or decode method should be reinvoked with the same parameters 090 * except for an input buffer with additional information. 091 * <P> 092 * A result with both overflow and underflow set to false indicates 093 * the completion of the encoding or decoding process of the entity. 094 * In this case, the input buffer may still contain data that belongs 095 * to the next entity that is to be encoded or decoded. 096 * 097 * @return {@code true} if underflow occurred 098 */ 099 public boolean isUnderflow() { 100 return underflow; 101 } 102 103 /** 104 * Indicates that the connection to the receiver of the response must be 105 * closed after sending any remaining data in the out buffer. 106 * 107 * @return the value 108 */ 109 public boolean closeConnection() { 110 return closeConnection; 111 } 112 113 /* (non-Javadoc) 114 * @see java.lang.Object#hashCode() 115 */ 116 @Override 117 public int hashCode() { 118 final int prime = 31; 119 int result = 1; 120 result = prime * result + (closeConnection ? 1231 : 1237); 121 result = prime * result + (overflow ? 1231 : 1237); 122 result = prime * result + (underflow ? 1231 : 1237); 123 return result; 124 } 125 126 /* (non-Javadoc) 127 * @see java.lang.Object#equals(java.lang.Object) 128 */ 129 @Override 130 public boolean equals(Object obj) { 131 if (this == obj) { 132 return true; 133 } 134 if (obj == null) { 135 return false; 136 } 137 if (!(obj instanceof Result)) { 138 return false; 139 } 140 Result other = (Result) obj; 141 if (closeConnection != other.closeConnection) { 142 return false; 143 } 144 if (overflow != other.overflow) { 145 return false; 146 } 147 if (underflow != other.underflow) { 148 return false; 149 } 150 return true; 151 } 152 153 /* (non-Javadoc) 154 * @see java.lang.Object#toString() 155 */ 156 @Override 157 public String toString() { 158 StringBuilder builder = new StringBuilder(); 159 builder.append("Codec.Result [overflow="); 160 builder.append(overflow); 161 builder.append(", underflow="); 162 builder.append(underflow); 163 builder.append(", closeConnection="); 164 builder.append(closeConnection); 165 builder.append("]"); 166 return builder.toString(); 167 } 168 169 /** 170 * A base class for a factory that creates results. Factories 171 * are only used internally by the codec implementation 172 * and therefore defined as protected inner classes 173 * so that they don't appear as part of the public API. 174 * 175 * Factories are refined whenever the {@link Result} type 176 * is refined. Factories define methods only if they are 177 * actually needed by the codec in which they are defined. 178 */ 179 protected static class Factory { 180 } 181 } 182 183 /** 184 * Results that indicate a protocol switch must implement this interface. 185 */ 186 public interface ProtocolSwitchResult { 187 188 /** 189 * The name of the protocol to be used for the next request 190 * if a protocol switch occured. 191 * 192 * @return the name or {@code null} if no protocol switch occured 193 */ 194 public String newProtocol(); 195 196 /** 197 * The encoder to be used for the next message 198 * if a protocol switch occured. 199 * 200 * @return the encoder or {@code null} if no protocol switch occurred 201 */ 202 public Encoder<?, ?> newEncoder(); 203 204 /** 205 * The decoder to be used for the next message 206 * if a protocol switch occured. 207 * 208 * @return the decoder or {@code null} if no protocol switch occurred 209 */ 210 public Decoder<?, ?> newDecoder(); 211 } 212}