001 002package io.vrap.rmf.base.client; 003 004import java.nio.charset.StandardCharsets; 005import java.util.HashMap; 006import java.util.Map; 007import java.util.Optional; 008 009import org.apache.commons.lang3.builder.EqualsBuilder; 010import org.apache.commons.lang3.builder.HashCodeBuilder; 011import org.apache.commons.lang3.builder.ToStringBuilder; 012 013public class ApiHttpResponse<U> extends Base implements ContextAware<ApiHttpResponse<U>> { 014 015 private int statusCode; 016 private ApiHttpHeaders headers; 017 private U body; 018 private String message; 019 020 private Map<Object, Object> contextMap = new HashMap<>(); 021 022 public ApiHttpResponse(final int statusCode, final ApiHttpHeaders headers, final U body) { 023 this(statusCode, headers, body, null); 024 } 025 026 public ApiHttpResponse(final int statusCode, final ApiHttpHeaders headers, final U body, final String message) { 027 this.statusCode = statusCode; 028 this.headers = Optional.ofNullable(headers).orElse(new ApiHttpHeaders()); 029 this.body = body; 030 this.message = message; 031 } 032 033 public ApiHttpResponse(final int statusCode, final ApiHttpHeaders headers, final U body, final String message, 034 final Map<Object, Object> contextMap) { 035 this.statusCode = statusCode; 036 this.headers = Optional.ofNullable(headers).orElse(new ApiHttpHeaders()); 037 this.body = body; 038 this.message = message; 039 this.contextMap = contextMap; 040 } 041 042 public ApiHttpResponse(final ApiHttpResponse<U> response) { 043 this.statusCode = response.statusCode; 044 this.headers = response.headers; 045 this.body = response.body; 046 this.message = response.message; 047 this.contextMap = response.contextMap; 048 } 049 050 public Map<Object, Object> getContextMap() { 051 return contextMap; 052 } 053 054 public ApiHttpResponse<U> withContextMap(final Map<Object, Object> contextMap) { 055 ApiHttpResponse<U> response = copy(); 056 response.contextMap = new HashMap<>(contextMap); 057 058 return response; 059 } 060 061 @SuppressWarnings("unchecked") 062 public <T> T getContext(Class<T> key) { 063 return (T) contextMap.get(key); 064 } 065 066 public <T> ApiHttpResponse<U> addContext(T value) { 067 ApiHttpResponse<U> response = copy(); 068 Map<Object, Object> contextMap = new HashMap<>(response.contextMap); 069 contextMap.put(value.getClass(), value); 070 response.contextMap = contextMap; 071 072 return response; 073 } 074 075 public Object getContext(Object key) { 076 return contextMap.get(key); 077 } 078 079 public ApiHttpResponse<U> addContext(Object key, Object value) { 080 ApiHttpResponse<U> response = copy(); 081 Map<Object, Object> contextMap = new HashMap<>(response.contextMap); 082 contextMap.put(key, value); 083 response.contextMap = contextMap; 084 085 return response; 086 } 087 088 public int getStatusCode() { 089 return statusCode; 090 } 091 092 public ApiHttpResponse<U> withStatusCode(final int statusCode) { 093 ApiHttpResponse<U> response = copy(); 094 response.statusCode = statusCode; 095 096 return response; 097 } 098 099 public ApiHttpHeaders getHeaders() { 100 return headers; 101 } 102 103 public ApiHttpResponse<U> withHeaders(final ApiHttpHeaders headers) { 104 ApiHttpResponse<U> response = copy(); 105 response.headers = headers; 106 107 return response; 108 } 109 110 public U getBody() { 111 return body; 112 } 113 114 public ApiHttpResponse<U> withBody(final U body) { 115 ApiHttpResponse<U> response = copy(); 116 response.body = body; 117 118 return response; 119 } 120 121 public String getMessage() { 122 return message; 123 } 124 125 public ApiHttpResponse<U> withMessage(final String message) { 126 ApiHttpResponse<U> response = copy(); 127 response.message = message; 128 129 return response; 130 } 131 132 @Override 133 public String toString() { 134 return new ToStringBuilder(this).append("statusCode", statusCode) 135 .append("headers", headers) 136 .append("textInterpretedBody", getSecuredBody()) 137 .toString(); 138 } 139 140 static String tryToFilter(final String input) { 141 return input.replaceAll("(\"\\w*([Pp]ass|access_token|refresh_token)\\w*\"):\"[^\"]*\"", 142 "$1:\"**removed from output**\""); 143 } 144 145 public Optional<String> getBodyAsString() { 146 if (body instanceof byte[]) { 147 return Optional.of(body).map(b -> tryToFilter(new String((byte[]) b, StandardCharsets.UTF_8))); 148 } 149 else { 150 return Optional.ofNullable(body).map(Object::toString); 151 } 152 } 153 154 public String getSecuredBody() { 155 return getBodyAsString().orElse("empty body"); 156 } 157 158 private ApiHttpResponse<U> copy() { 159 return new ApiHttpResponse<>(this); 160 } 161 162 @Override 163 public boolean equals(Object o) { 164 if (this == o) 165 return true; 166 167 if (o == null || getClass() != o.getClass()) 168 return false; 169 170 ApiHttpResponse<?> response = (ApiHttpResponse<?>) o; 171 172 return new EqualsBuilder().append(statusCode, response.statusCode) 173 .append(headers, response.headers) 174 .append(body, response.body) 175 .append(message, response.message) 176 .append(contextMap, response.contextMap) 177 .isEquals(); 178 } 179 180 @Override 181 public int hashCode() { 182 return new HashCodeBuilder(17, 37).append(statusCode) 183 .append(headers) 184 .append(body) 185 .append(message) 186 .append(contextMap) 187 .toHashCode(); 188 } 189}