WIP: WebClient -- DIE LĂ–SUNG! -- Feinschliff...
[facebook-errors] / src / main / java / de / juplo / facebook / errors / GraphApiException.java
1 package de.juplo.facebook.errors;
2
3
4 import com.fasterxml.jackson.core.JsonProcessingException;
5 import com.fasterxml.jackson.databind.DeserializationFeature;
6 import com.fasterxml.jackson.databind.ObjectMapper;
7 import com.fasterxml.jackson.databind.SerializationFeature;
8 import java.io.ByteArrayInputStream;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13 import org.springframework.http.HttpHeaders;
14 import org.springframework.http.HttpStatus;
15
16
17
18 /**
19  * Base exception for Facebook Graph-Api exceptions.
20  * 
21  * @author Kai Moritz
22  */
23 public class GraphApiException extends RuntimeException
24 {
25   public enum Type { OAuthException, GraphMethodException }
26
27
28   final static Logger LOG = LoggerFactory.getLogger(GraphApiException.class);
29   final static ObjectMapper OBJECT_MAPPER;
30
31   public final HttpStatus status;
32   public final HttpHeaders headers;
33   public final FacebookErrorMessage error;
34
35
36   static
37   {
38     OBJECT_MAPPER = new ObjectMapper();
39     OBJECT_MAPPER.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
40     OBJECT_MAPPER.configure(DeserializationFeature.ACCEPT_FLOAT_AS_INT, false);
41     OBJECT_MAPPER.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
42   }
43
44
45
46   public static GraphApiException create(
47       HttpStatus status,
48       HttpHeaders headers,
49       InputStream in
50       )
51   {
52     try
53     {
54       return create(status, headers, OBJECT_MAPPER.readValue(in, FacebookErrorMessage.class));
55     }
56     catch (IOException | RuntimeException e)
57     {
58       return new ErrorResponseParsingErrorException(status, headers, e);
59     }
60   }
61
62   public static GraphApiException create(
63       HttpStatus status,
64       HttpHeaders headers,
65       byte[] message
66       )
67   {
68     return create(status, headers, new ByteArrayInputStream(message));
69   }
70
71   public static GraphApiException create(
72       HttpStatus status,
73       HttpHeaders headers,
74       FacebookErrorMessage error
75       )
76   {
77     // see: http://fbdevwiki.com/wiki/Error_codes
78     switch(error.code)
79     {
80       // 1..99: general errors
81       case 1:     return new UnknownErrorException(status, headers, error);
82       case 2:     return new UnexpectedErrorException(status, headers, error);
83       case 4:     return new ApplicationRequestLimitReachedException(status, headers, error);
84       case 10:    return new AuthorizationMissingException(status, headers, error);
85       case 12:    return new DeprecatedException(status, headers, error);
86       case 17:    return new AccountRequestLimitReachedException(status, headers, error);
87       case 21:    return new PageMigratedException(status, headers, error);
88       case 32:    return new PageRequestLimitReachedException(status, headers, error);
89       // 100..199: graph method errors
90       case 100:   return new UnsupportedGetRequestException(status, headers, error);
91       case 102:   return new UserAccessTokenRequiredException(status, headers, error);
92       case 104:   return new AccessTokenRequiredException(status, headers, error);
93       case 190:   return new AccessTokenExpiredException(status, headers, error);
94       // 200..299: permission errors
95       case 200:   return new ApplicationNotAuthorizedByUserException(status, headers, error);
96       case 201:
97       case 202:
98       case 203:
99       case 204:
100       case 205:
101       case 206:
102       case 207:
103       case 208:
104       case 209:
105       case 210:
106       case 211:
107       case 212:
108       case 213:
109       case 214:
110       case 215:
111       case 216:
112       case 217:
113       case 218:
114       case 219:
115       case 220:
116       case 221:
117       case 222:
118       case 223:
119       case 224:
120       case 225:
121       case 226:
122       case 227:
123       case 228:
124       case 229:
125       case 230:
126       case 231:
127       case 232:
128       case 233:
129       case 234:
130       case 235:
131       case 236:
132       case 237:
133       case 238:
134       case 239:
135       case 240:
136       case 241:
137       case 242:
138       case 243:
139       case 244:
140       case 245:
141       case 246:
142       case 247:
143       case 248:
144       case 249:
145       case 250:
146       case 251:
147       case 252:
148       case 253:
149       case 254:
150       case 255:
151       case 256:
152       case 257:
153       case 258:
154       case 259:
155       case 260:
156       case 261:
157       case 262:
158       case 263:
159       case 264:
160       case 265:
161       case 266:
162       case 267:
163       case 268:
164       case 269:
165       case 270:
166       case 271:
167       case 272:
168       case 273:
169       case 274:
170       case 275:
171       case 276:
172       case 277:
173       case 278:
174       case 279:
175       case 280:
176       case 281:
177       case 282:
178       case 283:
179       case 284:
180       case 285:
181       case 286:
182       case 287:
183       case 288:
184       case 289:
185       case 290:
186       case 291:
187       case 292:
188       case 293:
189       case 294:
190       case 295:
191       case 296:
192       case 297:
193       case 298:
194       case 299:   return new AuthorizationMissingException(status, headers, error);
195       // 200..299: permission errors
196       // 300..399: data editing errors ?
197       case 341:   return new TemporaryRateLimitExceededException(status, headers, error);
198       // 400..449: authentication error
199       // 450..499: session errors
200       // 500..599: application messaging errors ?
201       case 506:   return new MultipleConcurrentPostsException(status, headers, error);
202       // 600..699: FQL errors
203       case 613:   return new RateLimitExceededException(status, headers, error);
204       // 700..749: ref errors
205       // 750..799: application integration errors
206       // 900..949: application information errors
207       // 950..999: batch api errors
208       // 1000..1099: event api errors
209       // 1100..1199: live-message errors
210       case 1609005: return new LinkPostFailureException(status, headers, error);
211       case 2200:  return new CallbackVerificationFailedException(status, headers, error);
212
213       default:
214         GraphApiException e = new UnmappedErrorException(status, headers, error);
215         LOG.info("unmapped error: {}", e.toString());
216         return e;
217     }
218   }
219
220
221   protected GraphApiException(
222       HttpStatus status,
223       HttpHeaders headers,
224       FacebookErrorMessage error
225       )
226   {
227     super(error.message);
228     this.status = status;
229     this.headers = headers;
230     this.error = error;
231   }
232
233
234   public HttpStatus getStatus()
235   {
236     return status;
237   }
238
239   public HttpHeaders getHeaders()
240   {
241     return headers;
242   }
243
244   public Type getType()
245   {
246     return error.type == null ? null : Type.valueOf(error.type);
247   }
248
249   public Integer getCode()
250   {
251     return error.code;
252   }
253
254   public Integer getSubCode()
255   {
256     return error.subCode;
257   }
258
259   public String getUserTitle()
260   {
261     return error.userTitle;
262   }
263
264   public String getUserMessage()
265   {
266     return error.userMessage;
267   }
268
269   public String getTraceId()
270   {
271     return error.traceId;
272   }
273
274
275   @Override
276   public String toString()
277   {
278     try
279     {
280       return OBJECT_MAPPER.writeValueAsString(error);
281     }
282     catch(JsonProcessingException e)
283     {
284       // This should never happen. But in case of a mistake: be verbose!
285       LOG.error("could not convert message into JSON: {}", e);
286       return e.getMessage();
287     }
288   }
289 }