Siehe:
[facebook-errors] / src / main / java / de / juplo / facebook / exceptions / GraphApiException.java
1 package de.juplo.facebook.exceptions;
2
3 import com.fasterxml.jackson.annotation.JsonProperty;
4 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
5 import com.fasterxml.jackson.annotation.JsonRootName;
6 import com.fasterxml.jackson.core.JsonParseException;
7 import com.fasterxml.jackson.core.JsonProcessingException;
8 import com.fasterxml.jackson.core.SerializableString;
9 import com.fasterxml.jackson.core.io.CharacterEscapes;
10 import com.fasterxml.jackson.databind.DeserializationFeature;
11 import com.fasterxml.jackson.databind.JsonMappingException;
12 import com.fasterxml.jackson.databind.ObjectMapper;
13 import com.fasterxml.jackson.databind.SerializationFeature;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.io.OutputStream;
17 import java.nio.ByteBuffer;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20 import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
21
22 /**
23  * Base exception for Facebook Graph-Api exceptions.
24  * 
25  * @author Kai Moritz
26  */
27 public class GraphApiException extends OAuth2Exception
28 {
29   public enum Type { OAuthException, GraphMethodException }
30
31
32   final static Logger LOG = LoggerFactory.getLogger(GraphApiException.class);
33   final static ObjectMapper OBJECT_MAPPER;
34
35   private final FacebookErrorMessage error;
36
37
38   static
39   {
40     OBJECT_MAPPER = new ObjectMapper();
41     OBJECT_MAPPER.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
42     OBJECT_MAPPER.configure(DeserializationFeature.ACCEPT_FLOAT_AS_INT, false);
43     OBJECT_MAPPER.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
44     OBJECT_MAPPER.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
45   }
46
47
48   public static GraphApiException create(InputStream in)
49       throws
50         IOException,
51         JsonParseException,
52         JsonMappingException
53   {
54     return create(OBJECT_MAPPER.readValue(in, FacebookErrorMessage.class));
55   }
56
57   public static GraphApiException create(byte[] message)
58       throws
59         IOException,
60         JsonParseException,
61         JsonMappingException
62   {
63     return create(OBJECT_MAPPER.readValue(message, FacebookErrorMessage.class));
64   }
65
66   public static GraphApiException create(FacebookErrorMessage error)
67   {
68     // see: http://fbdevwiki.com/wiki/Error_codes
69     switch(error.code)
70     {
71       // 1..99: general errors
72       case 1:     return new UnknownErrorException(error);
73       case 2:     return new UnexpectedErrorException(error);
74       case 21:    return new PageMigratedException(error);
75       // 100..199: graph method errors
76       case 100:   return new UnsupportedGetRequestException(error);
77       case 104:   return new AccessTokenRequiredException(error);
78       // 200..299: permission errors
79       // 300..399: data editing errors
80       // 400..449: authentication error
81       // 450..499: session errors
82       // 500..599: application messaging errors
83       // 600..699: FQL errors
84       case 613:   return new RateExceededException(error);
85       // 700..749: ref errors
86       // 750..799: application integration errors
87       // 900..949: application information errors
88       // 950..999: batch api errors
89       // 1000..1099: event api errors
90       // 1100..1199: live-message errors
91       case 2200:  return new CallbackVerificationFailedException(error);
92
93       default:
94         LOG.info("unmapped error: {}", error);
95         return new UnmappedErrorException(error);
96     }
97   }
98
99
100   protected GraphApiException(FacebookErrorMessage error)
101   {
102     super(error.message);
103     this.error = error;
104   }
105
106
107   public Type getType()
108   {
109     return error.type == null ? null : Type.valueOf(error.type);
110   }
111
112   public Integer getCode()
113   {
114     return error.code;
115   }
116
117   public Integer getSubCode()
118   {
119     return error.subCode;
120   }
121
122   public String getUserTitle()
123   {
124     return error.userTitle;
125   }
126
127   public String getUserMessage()
128   {
129     return error.userMessage;
130   }
131
132   public String getTraceId()
133   {
134     return error.traceId;
135   }
136
137
138   @Override
139   public String toString()
140   {
141     try
142     {
143       return OBJECT_MAPPER.writeValueAsString(error);
144     }
145     catch(JsonProcessingException e)
146     {
147       // This should never happen. But in case of a mistake: be verbose!
148       LOG.error("could not convert message into JSON: {}", e);
149       return e.getMessage();
150     }
151   }
152
153
154   /**
155    * This class represents an error message from the Graph-API
156    *
157    * @see <a href="https://developers.facebook.com/docs/graph-api/using-graph-api/v2.5#errors">Graph-API Documentation</a>
158    */
159   @JsonRootName("error")
160   @JsonPropertyOrder({ "message", "type", "code", "error_subcode", "error_user_title", "error_user_msg", "fbtrace_id" })
161   public static class FacebookErrorMessage
162   {
163     @JsonProperty("message")
164     String message;
165     @JsonProperty("type")
166     String type;
167     @JsonProperty("code")
168     Integer code;
169     @JsonProperty("error_subcode")
170     Integer subCode;
171     @JsonProperty("error_user_title")
172     String userTitle;
173     @JsonProperty("error_user_msg")
174     String userMessage;
175     @JsonProperty("fbtrace_id")
176     String traceId;
177   }
178
179   public static class CustomCharacterEscapes extends CharacterEscapes
180   {
181     private final int[] _asciiEscapes;
182
183
184     public CustomCharacterEscapes()
185     {
186       _asciiEscapes = standardAsciiEscapesForJSON();
187       _asciiEscapes['/'] = CharacterEscapes.ESCAPE_CUSTOM;
188     }
189
190
191     @Override
192     public int[] getEscapeCodesForAscii()
193     {
194         return _asciiEscapes;
195     }
196
197     @Override
198     public SerializableString getEscapeSequence(int i)
199     {
200       if(i == '/')
201       {
202         return new SerializableString()
203         {
204           @Override
205           public String getValue()
206           {
207             return "\\/";
208           }
209
210           @Override
211           public int charLength()
212           {
213             return 2;
214           }
215
216           @Override
217           public char[] asQuotedChars()
218           {
219             return new char[]{'\\','/'};
220           }
221
222           @Override
223           public byte[] asUnquotedUTF8()
224           {
225             return new byte[]{'\\','/'};
226           }
227
228           @Override
229           public byte[] asQuotedUTF8()
230           {
231             return new byte[]{'\\','/'};
232           }
233
234           @Override
235           public int appendQuotedUTF8(byte[] buffer, int offset)
236           {
237             throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
238           }
239
240           @Override
241           public int appendQuoted(char[] buffer, int offset)
242           {
243             throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
244           }
245
246           @Override
247           public int appendUnquotedUTF8(byte[] buffer, int offset)
248           {
249             throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
250           }
251
252           @Override
253           public int appendUnquoted(char[] buffer, int offset)
254           {
255             throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
256           }
257
258           @Override
259           public int writeQuotedUTF8(OutputStream out) throws IOException
260           {
261             throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
262           }
263
264           @Override
265           public int writeUnquotedUTF8(OutputStream out) throws IOException
266           {
267             throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
268           }
269
270           @Override
271           public int putQuotedUTF8(ByteBuffer buffer) throws IOException
272           {
273             throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
274           }
275
276           @Override
277           public int putUnquotedUTF8(ByteBuffer out) throws IOException
278           {
279             throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
280           }
281         };
282       }
283       else
284       {
285         return null;
286       }
287     }
288   }
289 }