--- /dev/null
+package de.juplo.facebook.client;
+
+import de.juplo.facebook.exceptions.GraphApiException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.security.oauth2.client.http.OAuth2ErrorHandler;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.web.client.HttpMessageConverterExtractor;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+
+
+/**
+ *
+ * @author kai
+ */
+public class GraphApiErrorHandler extends OAuth2ErrorHandler
+{
+ private final OAuth2ErrorHandler errorHandler;
+ private List<HttpMessageConverter<?>> messageConverters =
+ new RestTemplate().getMessageConverters();
+
+
+ public GraphApiErrorHandler(OAuth2ErrorHandler errorHandler)
+ {
+ super(null);
+ this.errorHandler = errorHandler;
+ }
+
+
+ /**
+ * @param messageConverters the messageConverters to set
+ */
+ @Override
+ public void setMessageConverters(
+ List<HttpMessageConverter<?>> messageConverters
+ )
+ {
+ this.messageConverters = messageConverters;
+ errorHandler.setMessageConverters(messageConverters);
+ }
+
+ @Override
+ public boolean hasError(ClientHttpResponse response) throws IOException
+ {
+ return
+ HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series())
+ || this.errorHandler.hasError(response);
+ }
+
+ @Override
+ public void handleError(final ClientHttpResponse response) throws IOException
+ {
+ if (!HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series()))
+ {
+ // We should only care about 400 level errors. Ex: A 500 server error shouldn't
+ // be an oauth related error.
+ errorHandler.handleError(response);
+ }
+ else
+ {
+ // Need to use buffered response because input stream may need to be consumed multiple times.
+ ClientHttpResponse bufferedResponse = new ClientHttpResponse()
+ {
+ private byte[] lazyBody;
+
+ @Override
+ public HttpStatus getStatusCode() throws IOException
+ {
+ return response.getStatusCode();
+ }
+
+ @Override
+ public synchronized InputStream getBody() throws IOException
+ {
+ if (lazyBody == null) {
+ InputStream bodyStream = response.getBody();
+ if (bodyStream != null) {
+ lazyBody = FileCopyUtils.copyToByteArray(bodyStream);
+ }
+ else {
+ lazyBody = new byte[0];
+ }
+ }
+ return new ByteArrayInputStream(lazyBody);
+ }
+
+ @Override
+ public HttpHeaders getHeaders()
+ {
+ return response.getHeaders();
+ }
+
+ @Override
+ public String getStatusText() throws IOException
+ {
+ return response.getStatusText();
+ }
+
+ @Override
+ public void close()
+ {
+ response.close();
+ }
+
+ @Override
+ public int getRawStatusCode() throws IOException
+ {
+ return response.getRawStatusCode();
+ }
+ };
+
+
+ HttpMessageConverterExtractor<GraphApiException> extractor =
+ new HttpMessageConverterExtractor<>(
+ GraphApiException.class,
+ messageConverters
+ );
+
+ try
+ {
+ GraphApiException body = extractor.extractData(bufferedResponse);
+ if (body != null)
+ {
+ // If we can get an OAuth2Exception already from the body, it is likely
+ // to have more information than the header does, so just re-throw it
+ // here.
+ body.setHttpErrorCode(response.getRawStatusCode());
+ throw body;
+ }
+ }
+ catch (RestClientException|HttpMessageNotReadableException e)
+ {
+ // ignore
+ }
+
+ errorHandler.handleError(bufferedResponse);
+ }
+ }
+}