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