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 if (value instanceof ClassReferenceContext) { 071 contextMap.put(((ClassReferenceContext) value).classReference(), value); 072 } 073 074 response.contextMap = contextMap; 075 076 return response; 077 } 078 079 public Object getContext(Object key) { 080 return contextMap.get(key); 081 } 082 083 public ApiHttpResponse<U> addContext(Object key, Object value) { 084 ApiHttpResponse<U> response = copy(); 085 Map<Object, Object> contextMap = new HashMap<>(response.contextMap); 086 contextMap.put(key, value); 087 response.contextMap = contextMap; 088 089 return response; 090 } 091 092 public int getStatusCode() { 093 return statusCode; 094 } 095 096 public ApiHttpResponse<U> withStatusCode(final int statusCode) { 097 ApiHttpResponse<U> response = copy(); 098 response.statusCode = statusCode; 099 100 return response; 101 } 102 103 public ApiHttpHeaders getHeaders() { 104 return headers; 105 } 106 107 public ApiHttpResponse<U> withHeaders(final ApiHttpHeaders headers) { 108 ApiHttpResponse<U> response = copy(); 109 response.headers = headers; 110 111 return response; 112 } 113 114 public U getBody() { 115 return body; 116 } 117 118 public ApiHttpResponse<U> withBody(final U body) { 119 ApiHttpResponse<U> response = copy(); 120 response.body = body; 121 122 return response; 123 } 124 125 public String getMessage() { 126 return message; 127 } 128 129 public ApiHttpResponse<U> withMessage(final String message) { 130 ApiHttpResponse<U> response = copy(); 131 response.message = message; 132 133 return response; 134 } 135 136 @Override 137 public String toString() { 138 return new ToStringBuilder(this).append("statusCode", statusCode) 139 .append("headers", headers) 140 .append("textInterpretedBody", getSecuredBody()) 141 .toString(); 142 } 143 144 static String tryToFilter(final String input) { 145 return input.replaceAll("(\"\\w*([Pp]ass|access_token|refresh_token)\\w*\"):\"[^\"]*\"", 146 "$1:\"**removed from output**\""); 147 } 148 149 public Optional<String> getBodyAsString() { 150 if (body instanceof byte[]) { 151 return Optional.of(body).map(b -> tryToFilter(new String((byte[]) b, StandardCharsets.UTF_8))); 152 } 153 else { 154 return Optional.ofNullable(body).map(Object::toString); 155 } 156 } 157 158 public String getSecuredBody() { 159 return getBodyAsString().orElse("empty body"); 160 } 161 162 private ApiHttpResponse<U> copy() { 163 return new ApiHttpResponse<>(this); 164 } 165 166 @Override 167 public boolean equals(Object o) { 168 if (this == o) 169 return true; 170 171 if (o == null || getClass() != o.getClass()) 172 return false; 173 174 ApiHttpResponse<?> response = (ApiHttpResponse<?>) o; 175 176 return new EqualsBuilder().append(statusCode, response.statusCode) 177 .append(headers, response.headers) 178 .append(body, response.body) 179 .append(message, response.message) 180 .append(contextMap, response.contextMap) 181 .isEquals(); 182 } 183 184 @Override 185 public int hashCode() { 186 return new HashCodeBuilder(17, 37).append(statusCode) 187 .append(headers) 188 .append(body) 189 .append(message) 190 .append(contextMap) 191 .toHashCode(); 192 } 193}