a8b2d28595c2b049c94a5b488147b95a1a2f6bb0
[facebook-errors] / src / main / java / de / juplo / facebook / client / GraphApiErrorHandler.java
1 package de.juplo.facebook.client;
2
3 import de.juplo.facebook.exceptions.GraphApiException;
4 import java.io.ByteArrayInputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import org.springframework.http.HttpHeaders;
8 import org.springframework.http.HttpStatus;
9 import org.springframework.http.client.ClientHttpResponse;
10 import org.springframework.util.FileCopyUtils;
11 import org.springframework.web.client.ResponseErrorHandler;
12
13
14
15 /**
16  * Error-Handler for error-messages from the Facebook Graph-API.
17  * <p>
18  * This error-handler handels responses withe the HTTP-status code
19  * {@code 400 BAD REQUEST}. It tries to extract and parse the error-message
20  * from the HTTP-body. Successfully extracted and parsed messages are mapped
21  * to a hierarchy of exceptions, that reflects the hierarchy of the error-
22  * codes and -types.
23  * <p>
24  * If the HTTP-status-code of the response is not {@code 400 BAD REQUEST} or
25  * the HTTP-body could not be extracted or parsed, this error-handler
26  * delegates the handling to its parent.
27  *
28  * @see <a href="https://developers.facebook.com/docs/graph-api/using-graph-api/v2.5#errors">Graph-API Documentation</a>
29  * @see <a href="http://fbdevwiki.com/wiki/Error_codes">Inofficial Wiki For Facebook-Developers</a>
30  * @author Kai Moritz
31  */
32 public class GraphApiErrorHandler implements ResponseErrorHandler
33 {
34   private final ResponseErrorHandler parent;
35
36
37   public GraphApiErrorHandler(ResponseErrorHandler errorHandler)
38   {
39     this.parent = errorHandler;
40   }
41
42
43   @Override
44   public boolean hasError(ClientHttpResponse response) throws IOException
45   {
46     return
47         HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series())
48         || this.parent.hasError(response);
49   }
50
51   @Override
52   public void handleError(final ClientHttpResponse response) throws IOException
53   {
54     if (!HttpStatus.BAD_REQUEST.equals(response.getStatusCode()))
55     {
56       // We will only handle 400 BAD REQUEST
57       parent.handleError(response);
58       return;
59     }
60
61
62     if (response.getBody() == null)
63     {
64       // There is no body to interpret in the HTTP-message
65       parent.handleError(response);
66       return;
67     }
68
69     final byte[] body = FileCopyUtils.copyToByteArray(response.getBody());
70     GraphApiException error;
71
72     try
73     {
74       error = GraphApiException.create(body);
75     }
76     catch (Exception e)
77     {
78       // The body of the HTTP-message could not be parsed.
79       // Let the parent error-handler try to handle the response.
80
81       // To do so, we have to wrap the original response to fill in
82       // the buffered body, if needed
83       ClientHttpResponse buffered = new ClientHttpResponse()
84       {
85         @Override
86         public HttpStatus getStatusCode() throws IOException
87         {
88           return response.getStatusCode();
89         }
90
91         @Override
92         public synchronized InputStream getBody() throws IOException
93         {
94           return new ByteArrayInputStream(body);
95         }
96
97         @Override
98         public HttpHeaders getHeaders()
99         {
100           return response.getHeaders();
101         }
102
103         @Override
104         public String getStatusText() throws IOException
105         {
106           return response.getStatusText();
107         }
108
109         @Override
110         public void close()
111         {
112           response.close();
113         }
114
115         @Override
116         public int getRawStatusCode() throws IOException
117         {
118           return response.getRawStatusCode();
119         }
120       };
121
122       parent.handleError(buffered);
123       return;
124     }
125
126     throw error;
127   }
128 }