View Javadoc
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.databind.DeserializationFeature;
9   import com.fasterxml.jackson.databind.JsonMappingException;
10  import com.fasterxml.jackson.databind.ObjectMapper;
11  import com.fasterxml.jackson.databind.SerializationFeature;
12  import java.io.IOException;
13  import java.io.InputStream;
14  import org.slf4j.Logger;
15  import org.slf4j.LoggerFactory;
16  import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
17  
18  /**
19   * Base exception for Facebook Graph-Api exceptions.
20   * 
21   * @author Kai Moritz
22   */
23  public class GraphApiException extends OAuth2Exception
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    private final FacebookErrorMessage error;
32  
33  
34    static
35    {
36      OBJECT_MAPPER = new ObjectMapper();
37      OBJECT_MAPPER.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
38      OBJECT_MAPPER.configure(DeserializationFeature.ACCEPT_FLOAT_AS_INT, false);
39      OBJECT_MAPPER.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
40    }
41  
42  
43    public static GraphApiException create(InputStream in)
44        throws
45          IOException,
46          JsonParseException,
47          JsonMappingException
48    {
49      return create(OBJECT_MAPPER.readValue(in, FacebookErrorMessage.class));
50    }
51  
52    public static GraphApiException create(byte[] message)
53        throws
54          IOException,
55          JsonParseException,
56          JsonMappingException
57    {
58      return create(OBJECT_MAPPER.readValue(message, FacebookErrorMessage.class));
59    }
60  
61    public static GraphApiException create(FacebookErrorMessage error)
62    {
63      // see: http://fbdevwiki.com/wiki/Error_codes
64      switch(error.code)
65      {
66        // 1..99: general errors
67        case 1:     return new UnknownErrorException(error);
68        case 2:     return new UnexpectedErrorException(error);
69        case 21:    return new PageMigratedException(error);
70        // 100..199: graph method errors
71        case 100:   return new UnsupportedGetRequestException(error);
72        case 104:   return new AccessTokenRequiredException(error);
73        // 200..299: permission errors
74        // 300..399: data editing errors
75        // 400..449: authentication error
76        // 450..499: session errors
77        // 500..599: application messaging errors
78        // 600..699: FQL errors
79        case 613:   return new RateExceededException(error);
80        // 700..749: ref errors
81        // 750..799: application integration errors
82        // 900..949: application information errors
83        // 950..999: batch api errors
84        // 1000..1099: event api errors
85        // 1100..1199: live-message errors
86        case 2200:  return new CallbackVerificationFailedException(error);
87  
88        default:
89          LOG.info("unmapped error: {}", error);
90          return new UnmappedErrorException(error);
91      }
92    }
93  
94  
95    protected GraphApiException(FacebookErrorMessage error)
96    {
97      super(error.message);
98      this.error = error;
99    }
100 
101 
102   public Type getType()
103   {
104     return error.type == null ? null : Type.valueOf(error.type);
105   }
106 
107   public Integer getCode()
108   {
109     return error.code;
110   }
111 
112   public Integer getSubCode()
113   {
114     return error.subCode;
115   }
116 
117   public String getUserTitle()
118   {
119     return error.userTitle;
120   }
121 
122   public String getUserMessage()
123   {
124     return error.userMessage;
125   }
126 
127   public String getTraceId()
128   {
129     return error.traceId;
130   }
131 
132 
133   @Override
134   public String toString()
135   {
136     try
137     {
138       return OBJECT_MAPPER.writeValueAsString(error);
139     }
140     catch(JsonProcessingException e)
141     {
142       // This should never happen. But in case of a mistake: be verbose!
143       LOG.error("could not convert message into JSON: {}", e);
144       return e.getMessage();
145     }
146   }
147 
148 
149   /**
150    * This class represents an error message from the Graph-API
151    *
152    * @see <a href="https://developers.facebook.com/docs/graph-api/using-graph-api/v2.5#errors">Graph-API Documentation</a>
153    */
154   @JsonRootName("error")
155   @JsonPropertyOrder({ "message", "type", "code", "error_subcode", "error_user_title", "error_user_msg", "fbtrace_id" })
156   public static class FacebookErrorMessage
157   {
158     @JsonProperty("message")
159     String message;
160     @JsonProperty("type")
161     String type;
162     @JsonProperty("code")
163     Integer code;
164     @JsonProperty("error_subcode")
165     Integer subCode;
166     @JsonProperty("error_user_title")
167     String userTitle;
168     @JsonProperty("error_user_msg")
169     String userMessage;
170     @JsonProperty("fbtrace_id")
171     String traceId;
172   }
173 }