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