Java tutorial
/* * Copyright 2017-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.vault.client; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Collection; import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpStatus; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.vault.VaultException; import org.springframework.vault.support.VaultResponseSupport; import org.springframework.web.client.HttpStatusCodeException; /** * Utility methods to unwrap Vault responses and build {@link VaultException}. * * @author Mark Paluch */ public abstract class VaultResponses { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter( OBJECT_MAPPER); /** * Build a {@link VaultException} given {@link HttpStatusCodeException}. * @param e must not be {@literal null}. * @return the {@link VaultException}. */ public static VaultException buildException(HttpStatusCodeException e) { Assert.notNull(e, "HttpStatusCodeException must not be null"); String message = VaultResponses.getError(e.getResponseBodyAsString()); if (StringUtils.hasText(message)) { return new VaultException( String.format("Status %s %s: %s", e.getRawStatusCode(), e.getStatusText(), message), e); } return new VaultException(String.format("Status %s %s", e.getRawStatusCode(), e.getStatusText()), e); } /** * Build a {@link VaultException} given {@link HttpStatusCodeException} and request * {@code path}. * @param e must not be {@literal null}. * @param path must not be {@literal null}. * @return the {@link VaultException}. */ public static VaultException buildException(HttpStatusCodeException e, String path) { Assert.notNull(e, "HttpStatusCodeException must not be null"); String message = VaultResponses.getError(e.getResponseBodyAsString()); if (StringUtils.hasText(message)) { return new VaultException( String.format("Status %s %s [%s]: %s", e.getRawStatusCode(), e.getStatusText(), path, message), e); } return new VaultException(String.format("Status %s %s [%s]", e.getRawStatusCode(), e.getStatusText(), path), e); } public static VaultException buildException(HttpStatus statusCode, String path, String message) { if (StringUtils.hasText(message)) { return new VaultException(String.format("Status %s [%s]: %s", statusCode, path, message)); } return new VaultException(String.format("Status %s [%s]", statusCode, path)); } /** * Create a {@link ParameterizedTypeReference} for {@code responseType}. * @param responseType must not be {@literal null}. * @return the {@link ParameterizedTypeReference} for {@code responseType}. */ public static <T> ParameterizedTypeReference<VaultResponseSupport<T>> getTypeReference( final Class<T> responseType) { Assert.notNull(responseType, "Response type must not be null"); final Type supportType = new ParameterizedType() { @Override public Type[] getActualTypeArguments() { return new Type[] { responseType }; } @Override public Type getRawType() { return VaultResponseSupport.class; } @Override public Type getOwnerType() { return VaultResponseSupport.class; } }; return new ParameterizedTypeReference<VaultResponseSupport<T>>() { @Override public Type getType() { return supportType; } }; } /** * Obtain the error message from a JSON response. * * @param json must not be {@literal null}. * @return */ @SuppressWarnings("unchecked") public static String getError(String json) { Assert.notNull(json, "Error JSON must not be null"); if (json.contains("\"errors\":")) { try { Map<String, Object> map = OBJECT_MAPPER.readValue(json.getBytes(), Map.class); if (map.containsKey("errors")) { Collection<String> errors = (Collection<String>) map.get("errors"); if (errors.size() == 1) { return errors.iterator().next(); } return errors.toString(); } } catch (IOException o_O) { // ignore } } return json; } /** * Unwrap a wrapped response created by Vault Response Wrapping * * @param wrappedResponse the wrapped response , must not be empty or {@literal null}. * @param responseType the type of the return value. * @return the unwrapped response. */ @SuppressWarnings("unchecked") public static <T> T unwrap(final String wrappedResponse, Class<T> responseType) { Assert.hasText(wrappedResponse, "Wrapped response must not be empty"); try { return (T) converter.read(responseType, new HttpInputMessage() { @Override public InputStream getBody() throws IOException { return new ByteArrayInputStream(wrappedResponse.getBytes()); } @Override public HttpHeaders getHeaders() { return new HttpHeaders(); } }); } catch (IOException e) { throw new IllegalStateException(e); } } }