package de.juplo.facebook;
+import de.juplo.facebook.errors.GraphApiErrorHandler;
import de.juplo.facebook.token.SignedRequestAwareAuthorizationCodeAccessTokenProvider;
-import de.juplo.facebook.exceptions.GraphApiErrorHandler;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+
+/**
+ * 104: An access token is required to request this resource.
+ * @author Kai Moritz
+ */
+public class AccessTokenRequiredException extends OAuthException
+{
+ protected AccessTokenRequiredException(FacebookErrorMessage error)
+ {
+ super(error);
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+/**
+ * 2200: Callback verification failed.
+ * @author Kai Moritz
+ */
+public class CallbackVerificationFailedException extends OAuthException
+{
+ protected CallbackVerificationFailedException(FacebookErrorMessage error)
+ {
+ super(error);
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.annotation.JsonRootName;
+
+
+
+/**
+ * This class represents an error message from the Graph-API
+ *
+ * @see <a href="https://developers.facebook.com/docs/graph-api/using-graph-api/v2.5#errors">Graph-API Documentation</a>
+ * @author Kai Moritz
+ */
+@JsonRootName("error")
+@JsonPropertyOrder({
+ "message",
+ "type",
+ "code",
+ "error_subcode",
+ "error_user_title",
+ "error_user_msg",
+ "fbtrace_id"
+ })
+public class FacebookErrorMessage
+{
+ @JsonProperty("message")
+ String message;
+ @JsonProperty("type")
+ String type;
+ @JsonProperty("code")
+ Integer code;
+ @JsonProperty("error_subcode")
+ Integer subCode;
+ @JsonProperty("error_user_title")
+ String userTitle;
+ @JsonProperty("error_user_msg")
+ String userMessage;
+ @JsonProperty("fbtrace_id")
+ String traceId;
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.web.client.ResponseErrorHandler;
+
+
+
+/**
+ * Error-Handler for error-messages from the Facebook Graph-API.
+ * <p>
+ * This error-handler handels responses withe the HTTP-status code
+ * {@code 400 BAD REQUEST}. It tries to extract and parse the error-message
+ * from the HTTP-body. Successfully extracted and parsed messages are mapped
+ * to a hierarchy of exceptions, that reflects the hierarchy of the error-
+ * codes and -types.
+ * <p>
+ * If the HTTP-status-code of the response is not {@code 400 BAD REQUEST} or
+ * the HTTP-body could not be extracted or parsed, this error-handler
+ * delegates the handling to its parent.
+ *
+ * @see <a href="https://developers.facebook.com/docs/graph-api/using-graph-api/v2.5#errors">Graph-API Documentation</a>
+ * @see <a href="http://fbdevwiki.com/wiki/Error_codes">Inofficial Wiki For Facebook-Developers</a>
+ * @author Kai Moritz
+ */
+public class GraphApiErrorHandler implements ResponseErrorHandler
+{
+ private final static Logger LOG =
+ LoggerFactory.getLogger(GraphApiErrorHandler.class);
+
+ private final ResponseErrorHandler parent;
+
+
+ public GraphApiErrorHandler(ResponseErrorHandler errorHandler)
+ {
+ this.parent = errorHandler;
+ }
+
+
+ @Override
+ public boolean hasError(ClientHttpResponse response) throws IOException
+ {
+ return
+ HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series())
+ || this.parent.hasError(response);
+ }
+
+ @Override
+ public void handleError(final ClientHttpResponse response) throws IOException
+ {
+ if (!HttpStatus.BAD_REQUEST.equals(response.getStatusCode()))
+ {
+ // We will only handle 400 BAD REQUEST
+ LOG.debug("ignoring response with status-code {}.", response.getStatusCode());
+ parent.handleError(response);
+ return;
+ }
+
+
+ if (response.getBody() == null)
+ {
+ // There is no body to interpret in the HTTP-message
+ LOG.warn("Could not convert the response into an exception, because there is no message-body.");
+ parent.handleError(response);
+ return;
+ }
+
+ final byte[] body = FileCopyUtils.copyToByteArray(response.getBody());
+ GraphApiException error;
+
+ try
+ {
+ error = GraphApiException.create(body);
+ if (LOG.isInfoEnabled())
+ LOG.info("error-response: {}", new String(body, Charset.forName("UTF-8")));
+ }
+ catch (Exception e)
+ {
+ // The body of the HTTP-message could not be parsed.
+ // Let the parent error-handler try to handle the response.
+
+ LOG.warn("Could not convert the response into an exception, because the body is unparsable: {}", body);
+
+ // To do so, we have to wrap the original response to fill in
+ // the buffered body, if needed
+ ClientHttpResponse buffered = new ClientHttpResponse()
+ {
+ @Override
+ public HttpStatus getStatusCode() throws IOException
+ {
+ return response.getStatusCode();
+ }
+
+ @Override
+ public synchronized InputStream getBody() throws IOException
+ {
+ return new ByteArrayInputStream(body);
+ }
+
+ @Override
+ public HttpHeaders getHeaders()
+ {
+ return response.getHeaders();
+ }
+
+ @Override
+ public String getStatusText() throws IOException
+ {
+ return response.getStatusText();
+ }
+
+ @Override
+ public void close()
+ {
+ response.close();
+ }
+
+ @Override
+ public int getRawStatusCode() throws IOException
+ {
+ return response.getRawStatusCode();
+ }
+ };
+
+ parent.handleError(buffered);
+ return;
+ }
+
+ throw error;
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import java.io.IOException;
+import java.io.InputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
+
+
+
+/**
+ * Base exception for Facebook Graph-Api exceptions.
+ *
+ * @author Kai Moritz
+ */
+public class GraphApiException extends OAuth2Exception
+{
+ public enum Type { OAuthException, GraphMethodException }
+
+
+ final static Logger LOG = LoggerFactory.getLogger(GraphApiException.class);
+ final static ObjectMapper OBJECT_MAPPER;
+
+ private final FacebookErrorMessage error;
+
+
+ static
+ {
+ OBJECT_MAPPER = new ObjectMapper();
+ OBJECT_MAPPER.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
+ OBJECT_MAPPER.configure(DeserializationFeature.ACCEPT_FLOAT_AS_INT, false);
+ OBJECT_MAPPER.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
+ }
+
+
+ public static GraphApiException create(InputStream in)
+ throws
+ IOException,
+ JsonParseException,
+ JsonMappingException
+ {
+ return create(OBJECT_MAPPER.readValue(in, FacebookErrorMessage.class));
+ }
+
+ public static GraphApiException create(byte[] message)
+ throws
+ IOException,
+ JsonParseException,
+ JsonMappingException
+ {
+ return create(OBJECT_MAPPER.readValue(message, FacebookErrorMessage.class));
+ }
+
+ public static GraphApiException create(FacebookErrorMessage error)
+ {
+ // see: http://fbdevwiki.com/wiki/Error_codes
+ switch(error.code)
+ {
+ // 1..99: general errors
+ case 1: return new UnknownErrorException(error);
+ case 2: return new UnexpectedErrorException(error);
+ case 21: return new PageMigratedException(error);
+ // 100..199: graph method errors
+ case 100: return new UnsupportedGetRequestException(error);
+ case 104: return new AccessTokenRequiredException(error);
+ // 200..299: permission errors
+ // 300..399: data editing errors
+ // 400..449: authentication error
+ // 450..499: session errors
+ // 500..599: application messaging errors
+ // 600..699: FQL errors
+ case 613: return new RateExceededException(error);
+ // 700..749: ref errors
+ // 750..799: application integration errors
+ // 900..949: application information errors
+ // 950..999: batch api errors
+ // 1000..1099: event api errors
+ // 1100..1199: live-message errors
+ case 2200: return new CallbackVerificationFailedException(error);
+
+ default:
+ LOG.info("unmapped error: {}", error);
+ return new UnmappedErrorException(error);
+ }
+ }
+
+
+ protected GraphApiException(FacebookErrorMessage error)
+ {
+ super(error.message);
+ this.error = error;
+ }
+
+
+ public Type getType()
+ {
+ return error.type == null ? null : Type.valueOf(error.type);
+ }
+
+ public Integer getCode()
+ {
+ return error.code;
+ }
+
+ public Integer getSubCode()
+ {
+ return error.subCode;
+ }
+
+ public String getUserTitle()
+ {
+ return error.userTitle;
+ }
+
+ public String getUserMessage()
+ {
+ return error.userMessage;
+ }
+
+ public String getTraceId()
+ {
+ return error.traceId;
+ }
+
+
+ @Override
+ public String toString()
+ {
+ try
+ {
+ return OBJECT_MAPPER.writeValueAsString(error);
+ }
+ catch(JsonProcessingException e)
+ {
+ // This should never happen. But in case of a mistake: be verbose!
+ LOG.error("could not convert message into JSON: {}", e);
+ return e.getMessage();
+ }
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+
+/**
+ * Baseclass for exceptions of type {@code GraphMethodException}.
+ * @author Kai Moritz
+ */
+public abstract class GraphMethodException extends GraphApiException
+{
+ GraphMethodException(FacebookErrorMessage error)
+ {
+ super(error);
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+
+/**
+ * Baseclass for exceptions of type {@code OAuthException}.
+ * @author Kai Moritz
+ */
+public class OAuthException extends GraphApiException
+{
+ protected OAuthException(FacebookErrorMessage error)
+ {
+ super(error);
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+
+/**
+ * 21: Page ID (XXX) was migrated to page ID (YYY).
+ * @author Kai Moritz
+ */
+public class PageMigratedException extends OAuthException
+{
+ private final static Pattern pattern =
+ Pattern.compile("Page ID ([0-9]+) was migrated to page ID ([0-9]+)");
+
+ private final Long oldId, newId;
+
+
+ protected PageMigratedException(FacebookErrorMessage error)
+ {
+ super(error);
+ Matcher matcher = pattern.matcher(error.message);
+ if (!matcher.find())
+ {
+ String warning = "Could not parse migration-error: " + error.message;
+ LOG.error(warning);
+ throw new RuntimeException(warning);
+ }
+ oldId = Long.parseLong(matcher.group(1));
+ newId = Long.parseLong(matcher.group(2));
+ }
+
+
+ public Long getOldId()
+ {
+ return oldId;
+ }
+
+ public Long getNewId()
+ {
+ return newId;
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+
+/**
+ * 613: Calls to stream have exceeded the rate of 600 calls per 600 seconds.
+ * @author Kai Moritz
+ */
+public class RateExceededException extends OAuthException
+{
+ protected RateExceededException(FacebookErrorMessage error)
+ {
+ super(error);
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+
+/**
+ * 2: An unexpected error has occurred.
+ * @author Kai Moritz
+ */
+public class UnexpectedErrorException extends OAuthException
+{
+ protected UnexpectedErrorException(FacebookErrorMessage error)
+ {
+ super(error);
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+
+/**
+ * 1: An unknown error has occurred.
+ * @author Kai Moritz
+ */
+public class UnknownErrorException extends OAuthException
+{
+ protected UnknownErrorException(FacebookErrorMessage error)
+ {
+ super(error);
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+
+/**
+ * Marker class for error-messages, that are not mapped yet.
+ * Pleas help us to complete the list of possible errors and report errors,
+ * that are mapped to this class to info@juplo.de. Thanxs!
+ *
+ * @author Kai Moritz
+ */
+public class UnmappedErrorException extends GraphApiException
+{
+ protected UnmappedErrorException(FacebookErrorMessage error)
+ {
+ super(error);
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+
+/**
+ * 100: Unsupported get request.
+ * @author Kai Moritz
+ */
+public class UnsupportedGetRequestException extends GraphMethodException
+{
+ protected UnsupportedGetRequestException(FacebookErrorMessage error)
+ {
+ super(error);
+ }
+}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-
-/**
- * 104: An access token is required to request this resource.
- * @author Kai Moritz
- */
-public class AccessTokenRequiredException extends OAuthException
-{
- protected AccessTokenRequiredException(FacebookErrorMessage error)
- {
- super(error);
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-/**
- * 2200: Callback verification failed.
- * @author Kai Moritz
- */
-public class CallbackVerificationFailedException extends OAuthException
-{
- protected CallbackVerificationFailedException(FacebookErrorMessage error)
- {
- super(error);
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import com.fasterxml.jackson.annotation.JsonRootName;
-
-
-
-/**
- * This class represents an error message from the Graph-API
- *
- * @see <a href="https://developers.facebook.com/docs/graph-api/using-graph-api/v2.5#errors">Graph-API Documentation</a>
- * @author Kai Moritz
- */
-@JsonRootName("error")
-@JsonPropertyOrder({
- "message",
- "type",
- "code",
- "error_subcode",
- "error_user_title",
- "error_user_msg",
- "fbtrace_id"
- })
-public class FacebookErrorMessage
-{
- @JsonProperty("message")
- String message;
- @JsonProperty("type")
- String type;
- @JsonProperty("code")
- Integer code;
- @JsonProperty("error_subcode")
- Integer subCode;
- @JsonProperty("error_user_title")
- String userTitle;
- @JsonProperty("error_user_msg")
- String userMessage;
- @JsonProperty("fbtrace_id")
- String traceId;
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.util.FileCopyUtils;
-import org.springframework.web.client.ResponseErrorHandler;
-
-
-
-/**
- * Error-Handler for error-messages from the Facebook Graph-API.
- * <p>
- * This error-handler handels responses withe the HTTP-status code
- * {@code 400 BAD REQUEST}. It tries to extract and parse the error-message
- * from the HTTP-body. Successfully extracted and parsed messages are mapped
- * to a hierarchy of exceptions, that reflects the hierarchy of the error-
- * codes and -types.
- * <p>
- * If the HTTP-status-code of the response is not {@code 400 BAD REQUEST} or
- * the HTTP-body could not be extracted or parsed, this error-handler
- * delegates the handling to its parent.
- *
- * @see <a href="https://developers.facebook.com/docs/graph-api/using-graph-api/v2.5#errors">Graph-API Documentation</a>
- * @see <a href="http://fbdevwiki.com/wiki/Error_codes">Inofficial Wiki For Facebook-Developers</a>
- * @author Kai Moritz
- */
-public class GraphApiErrorHandler implements ResponseErrorHandler
-{
- private final static Logger LOG =
- LoggerFactory.getLogger(GraphApiErrorHandler.class);
-
- private final ResponseErrorHandler parent;
-
-
- public GraphApiErrorHandler(ResponseErrorHandler errorHandler)
- {
- this.parent = errorHandler;
- }
-
-
- @Override
- public boolean hasError(ClientHttpResponse response) throws IOException
- {
- return
- HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series())
- || this.parent.hasError(response);
- }
-
- @Override
- public void handleError(final ClientHttpResponse response) throws IOException
- {
- if (!HttpStatus.BAD_REQUEST.equals(response.getStatusCode()))
- {
- // We will only handle 400 BAD REQUEST
- LOG.debug("ignoring response with status-code {}.", response.getStatusCode());
- parent.handleError(response);
- return;
- }
-
-
- if (response.getBody() == null)
- {
- // There is no body to interpret in the HTTP-message
- LOG.warn("Could not convert the response into an exception, because there is no message-body.");
- parent.handleError(response);
- return;
- }
-
- final byte[] body = FileCopyUtils.copyToByteArray(response.getBody());
- GraphApiException error;
-
- try
- {
- error = GraphApiException.create(body);
- if (LOG.isInfoEnabled())
- LOG.info("error-response: {}", new String(body, Charset.forName("UTF-8")));
- }
- catch (Exception e)
- {
- // The body of the HTTP-message could not be parsed.
- // Let the parent error-handler try to handle the response.
-
- LOG.warn("Could not convert the response into an exception, because the body is unparsable: {}", body);
-
- // To do so, we have to wrap the original response to fill in
- // the buffered body, if needed
- ClientHttpResponse buffered = new ClientHttpResponse()
- {
- @Override
- public HttpStatus getStatusCode() throws IOException
- {
- return response.getStatusCode();
- }
-
- @Override
- public synchronized InputStream getBody() throws IOException
- {
- return new ByteArrayInputStream(body);
- }
-
- @Override
- public HttpHeaders getHeaders()
- {
- return response.getHeaders();
- }
-
- @Override
- public String getStatusText() throws IOException
- {
- return response.getStatusText();
- }
-
- @Override
- public void close()
- {
- response.close();
- }
-
- @Override
- public int getRawStatusCode() throws IOException
- {
- return response.getRawStatusCode();
- }
- };
-
- parent.handleError(buffered);
- return;
- }
-
- throw error;
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import java.io.IOException;
-import java.io.InputStream;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
-
-/**
- * Base exception for Facebook Graph-Api exceptions.
- *
- * @author Kai Moritz
- */
-public class GraphApiException extends OAuth2Exception
-{
- public enum Type { OAuthException, GraphMethodException }
-
-
- final static Logger LOG = LoggerFactory.getLogger(GraphApiException.class);
- final static ObjectMapper OBJECT_MAPPER;
-
- private final FacebookErrorMessage error;
-
-
- static
- {
- OBJECT_MAPPER = new ObjectMapper();
- OBJECT_MAPPER.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
- OBJECT_MAPPER.configure(DeserializationFeature.ACCEPT_FLOAT_AS_INT, false);
- OBJECT_MAPPER.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
- }
-
-
- public static GraphApiException create(InputStream in)
- throws
- IOException,
- JsonParseException,
- JsonMappingException
- {
- return create(OBJECT_MAPPER.readValue(in, FacebookErrorMessage.class));
- }
-
- public static GraphApiException create(byte[] message)
- throws
- IOException,
- JsonParseException,
- JsonMappingException
- {
- return create(OBJECT_MAPPER.readValue(message, FacebookErrorMessage.class));
- }
-
- public static GraphApiException create(FacebookErrorMessage error)
- {
- // see: http://fbdevwiki.com/wiki/Error_codes
- switch(error.code)
- {
- // 1..99: general errors
- case 1: return new UnknownErrorException(error);
- case 2: return new UnexpectedErrorException(error);
- case 21: return new PageMigratedException(error);
- // 100..199: graph method errors
- case 100: return new UnsupportedGetRequestException(error);
- case 104: return new AccessTokenRequiredException(error);
- // 200..299: permission errors
- // 300..399: data editing errors
- // 400..449: authentication error
- // 450..499: session errors
- // 500..599: application messaging errors
- // 600..699: FQL errors
- case 613: return new RateExceededException(error);
- // 700..749: ref errors
- // 750..799: application integration errors
- // 900..949: application information errors
- // 950..999: batch api errors
- // 1000..1099: event api errors
- // 1100..1199: live-message errors
- case 2200: return new CallbackVerificationFailedException(error);
-
- default:
- LOG.info("unmapped error: {}", error);
- return new UnmappedErrorException(error);
- }
- }
-
-
- protected GraphApiException(FacebookErrorMessage error)
- {
- super(error.message);
- this.error = error;
- }
-
-
- public Type getType()
- {
- return error.type == null ? null : Type.valueOf(error.type);
- }
-
- public Integer getCode()
- {
- return error.code;
- }
-
- public Integer getSubCode()
- {
- return error.subCode;
- }
-
- public String getUserTitle()
- {
- return error.userTitle;
- }
-
- public String getUserMessage()
- {
- return error.userMessage;
- }
-
- public String getTraceId()
- {
- return error.traceId;
- }
-
-
- @Override
- public String toString()
- {
- try
- {
- return OBJECT_MAPPER.writeValueAsString(error);
- }
- catch(JsonProcessingException e)
- {
- // This should never happen. But in case of a mistake: be verbose!
- LOG.error("could not convert message into JSON: {}", e);
- return e.getMessage();
- }
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-/**
- * Baseclass for exceptions of type {@code GraphMethodException}.
- * @author Kai Moritz
- */
-public abstract class GraphMethodException extends GraphApiException
-{
- GraphMethodException(FacebookErrorMessage error)
- {
- super(error);
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-
-/**
- * Baseclass for exceptions of type {@code OAuthException}.
- * @author Kai Moritz
- */
-public class OAuthException extends GraphApiException
-{
- protected OAuthException(FacebookErrorMessage error)
- {
- super(error);
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-
-
-/**
- * 21: Page ID (XXX) was migrated to page ID (YYY).
- * @author Kai Moritz
- */
-public class PageMigratedException extends OAuthException
-{
- private final static Pattern pattern =
- Pattern.compile("Page ID ([0-9]+) was migrated to page ID ([0-9]+)");
-
- private final Long oldId, newId;
-
-
- protected PageMigratedException(FacebookErrorMessage error)
- {
- super(error);
- Matcher matcher = pattern.matcher(error.message);
- if (!matcher.find())
- {
- String warning = "Could not parse migration-error: " + error.message;
- LOG.error(warning);
- throw new RuntimeException(warning);
- }
- oldId = Long.parseLong(matcher.group(1));
- newId = Long.parseLong(matcher.group(2));
- }
-
-
- public Long getOldId()
- {
- return oldId;
- }
-
- public Long getNewId()
- {
- return newId;
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-/**
- * 613: Calls to stream have exceeded the rate of 600 calls per 600 seconds.
- * @author Kai Moritz
- */
-public class RateExceededException extends OAuthException
-{
- protected RateExceededException(FacebookErrorMessage error)
- {
- super(error);
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-
-/**
- * 2: An unexpected error has occurred.
- * @author Kai Moritz
- */
-public class UnexpectedErrorException extends OAuthException
-{
- protected UnexpectedErrorException(FacebookErrorMessage error)
- {
- super(error);
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-
-/**
- * 1: An unknown error has occurred.
- * @author Kai Moritz
- */
-public class UnknownErrorException extends OAuthException
-{
- protected UnknownErrorException(FacebookErrorMessage error)
- {
- super(error);
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-/**
- * Marker class for error-messages, that are not mapped yet.
- * Pleas help us to complete the list of possible errors and report errors,
- * that are mapped to this class to info@juplo.de. Thanxs!
- *
- * @author Kai Moritz
- */
-public class UnmappedErrorException extends GraphApiException
-{
- protected UnmappedErrorException(FacebookErrorMessage error)
- {
- super(error);
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-/**
- * 100: Unsupported get request.
- * @author Kai Moritz
- */
-public class UnsupportedGetRequestException extends GraphMethodException
-{
- protected UnsupportedGetRequestException(FacebookErrorMessage error)
- {
- super(error);
- }
-}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import static de.juplo.facebook.errors.GraphApiException.OBJECT_MAPPER;
+import de.juplo.facebook.errors.GraphApiException.Type;
+import java.io.IOException;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+
+
+/**
+ * @author Kai Moritz
+ */
+public class FacebookErrorMessageMappingTest
+{
+ final String example =
+ "{" +
+ "\"error\":{" +
+ "\"message\":\"Message describing the error\"," +
+ "\"type\":\"OAuthException\"," +
+ "\"code\":190," +
+ "\"error_subcode\":460," +
+ "\"error_user_title\":\"A title\"," +
+ "\"error_user_msg\":\"A message\"," +
+ "\"fbtrace_id\":\"EJplcsCHuLu\"" +
+ "}" +
+ "}";
+
+
+ @Test
+ public void testSerialize() throws JsonProcessingException
+ {
+ FacebookErrorMessage error = new FacebookErrorMessage();
+ error.message = "Message describing the error";
+ error.type = Type.OAuthException.name();
+ error.code = 190;
+ error.subCode = 460;
+ error.userTitle = "A title";
+ error.userMessage = "A message";
+ error.traceId = "EJplcsCHuLu";
+
+ assertEquals(example, OBJECT_MAPPER.writeValueAsString(error));
+ }
+
+ @Test
+ public void testDeserialize() throws IOException
+ {
+ FacebookErrorMessage error =
+ OBJECT_MAPPER.readValue(example, FacebookErrorMessage.class);
+
+ assertEquals("Message describing the error", error.message);
+ assertEquals(Type.OAuthException.name(), error.type);
+ assertEquals(new Integer(190), error.code);
+ assertEquals(new Integer(460), error.subCode);
+ assertEquals("A title", error.userTitle);
+ assertEquals("A message", error.userMessage);
+ assertEquals("EJplcsCHuLu", error.traceId);
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+import de.juplo.facebook.errors.GraphApiException.Type;
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.Resource;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.oauth2.client.OAuth2RestTemplate;
+import org.springframework.security.oauth2.client.http.OAuth2ErrorHandler;
+import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
+import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException;
+import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException;
+import org.springframework.security.oauth2.client.token.AccessTokenProvider;
+import org.springframework.security.oauth2.client.token.AccessTokenRequest;
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import static org.springframework.security.oauth2.common.OAuth2AccessToken.OAUTH2_TYPE;
+import org.springframework.security.oauth2.common.OAuth2RefreshToken;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.client.HttpClientErrorException;
+
+
+
+/**
+ *
+ * @author Kai Moritz
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(
+ locations = {
+ "classpath:/spring/test-facebook-error-handler.xml"
+ })
+public class GraphApiErrorHandlerTest
+{
+ private static final Logger log =
+ LoggerFactory.getLogger(GraphApiErrorHandlerTest.class);
+
+ @Resource
+ private OAuth2RestTemplate clientTemplate;
+
+ private MockClientHttpRequestFactory requestFactory;
+
+
+ @Test
+ public void testError1()
+ {
+ log.info("testError1");
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": \"An unknown error has occurred.\",\n" +
+ " \"type\": \"OAuthException\",\n" +
+ " \"code\": 1\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(UnknownErrorException e)
+ {
+ log.debug("{}", e.toString());
+ assertEquals("invalid_request", e.getOAuth2ErrorCode());
+ assertEquals(new Integer(1), e.getCode());
+ assertEquals("An unknown error has occurred.", e.getMessage());
+ assertEquals(Type.OAuthException, e.getType());
+ }
+ }
+
+ @Test
+ public void testError2()
+ {
+ log.info("testError2");
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": \"An unexpected error has occurred. Please retry your request later.\",\n" +
+ " \"type\": \"OAuthException\",\n" +
+ " \"code\": 2\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(UnexpectedErrorException e)
+ {
+ log.debug("{}", e.toString());
+ assertEquals("invalid_request", e.getOAuth2ErrorCode());
+ assertEquals(new Integer(2), e.getCode());
+ assertEquals("An unexpected error has occurred. Please retry your request later.", e.getMessage());
+ assertEquals(Type.OAuthException, e.getType());
+ }
+ }
+
+ @Test
+ public void testError21()
+ {
+ log.info("testError21");
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": \"(#21) Page ID 590408587650316 was migrated to page ID 1421620791415603. Please update your API calls to the new ID\",\n" +
+ " \"type\": \"OAuthException\",\n" +
+ " \"code\": 21\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(PageMigratedException e)
+ {
+ log.debug("{}", e.toString());
+ assertEquals("invalid_request", e.getOAuth2ErrorCode());
+ assertEquals(new Integer(21), e.getCode());
+ assertEquals("(#21) Page ID 590408587650316 was migrated to page ID 1421620791415603. Please update your API calls to the new ID", e.getMessage());
+ assertEquals(Type.OAuthException, e.getType());
+ }
+ }
+
+ @Test
+ public void testError100()
+ {
+ log.info("testError100");
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": \"Unsupported get request.\",\n" +
+ " \"type\": \"GraphMethodException\",\n" +
+ " \"code\": 100\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(UnsupportedGetRequestException e)
+ {
+ log.debug("{}", e.toString());
+ assertEquals("invalid_request", e.getOAuth2ErrorCode());
+ assertEquals(new Integer(100), e.getCode());
+ assertEquals("Unsupported get request.", e.getMessage());
+ assertEquals(Type.GraphMethodException, e.getType());
+ }
+ }
+
+ @Test
+ public void testError104()
+ {
+ log.info("testError104");
+
+ requestFactory.setBody("{\"error\":{\"message\":\"An access token is required to request this resource.\",\"type\":\"OAuthException\",\"code\":104,\"fbtrace_id\":\"E2Jjkj5++LL\"}}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(AccessTokenRequiredException e)
+ {
+ log.debug("{}", e.toString());
+ assertEquals("invalid_request", e.getOAuth2ErrorCode());
+ assertEquals(new Integer(104), e.getCode());
+ assertEquals("An access token is required to request this resource.", e.getMessage());
+ assertEquals(Type.OAuthException, e.getType());
+ assertEquals("E2Jjkj5++LL", e.getTraceId());
+ }
+ }
+
+ @Test
+ public void testError613()
+ {
+ log.info("testError613");
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": \"(#613) Calls to stream have exceeded the rate of 600 calls per 600 seconds.\",\n" +
+ " \"type\": \"OAuthException\",\n" +
+ " \"code\": 613\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(RateExceededException e)
+ {
+ log.debug("{}", e.toString());
+ assertEquals("invalid_request", e.getOAuth2ErrorCode());
+ assertEquals(new Integer(613), e.getCode());
+ assertEquals("(#613) Calls to stream have exceeded the rate of 600 calls per 600 seconds.", e.getMessage());
+ assertEquals(Type.OAuthException, e.getType());
+ }
+ }
+
+ @Test
+ public void testError2200()
+ {
+ requestFactory.setBody("{\"error\":{\"message\":\"(#2200) callback verification failed: \",\"type\":\"OAuthException\",\"code\":2200,\"fbtrace_id\":\"ESLjoZKvPXg\"}}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(CallbackVerificationFailedException e)
+ {
+ log.debug("{}", e.toString());
+ assertEquals("invalid_request", e.getOAuth2ErrorCode());
+ assertEquals(new Integer(2200), e.getCode());
+ assertEquals("(#2200) callback verification failed: ", e.getMessage());
+ assertEquals(Type.OAuthException, e.getType());
+ assertEquals("ESLjoZKvPXg", e.getTraceId());
+ }
+ }
+
+ @Test
+ public void testUnmappedError()
+ {
+ log.info("testUnmappedError");
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": \"This error does not exist.\",\n" +
+ " \"type\": \"NonexistentTypeException\",\n" +
+ " \"code\": 999999999\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(GraphApiException e)
+ {
+ log.debug("{}", e.toString());
+ assertEquals("invalid_request", e.getOAuth2ErrorCode());
+ assertEquals(new Integer(999999999), e.getCode());
+ assertEquals("This error does not exist.", e.getMessage());
+ try
+ {
+ Type type = e.getType();
+ log.error("unknown type: {}", type);
+ fail("unmapped type was resolved by enum: " + type);
+ }
+ catch (IllegalArgumentException ee) {}
+ }
+ }
+
+ @Test
+ public void testUnmappedErrors()
+ {
+ log.info("testUnmappedErrors");
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": null,\n" +
+ " \"type\": \"WhateverTypeException\",\n" +
+ " \"code\": 999999999\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(UnmappedErrorException e)
+ {
+ log.debug("{}", e.toString());
+ assertNull(e.getMessage());
+ try
+ {
+ Type type = e.getType();
+ log.error("unknown type: {}", type);
+ fail("unmapped type was resolved by enum: " + type);
+ }
+ catch (IllegalArgumentException ee) {}
+ assertEquals(new Integer(999999999), e.getCode());
+ assertNull(e.getSubCode());
+ assertNull(e.getUserTitle());
+ assertNull(e.getUserMessage());
+ assertNull(e.getTraceId());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"type\": \"WhateverTypeException\",\n" +
+ " \"code\": 999999999\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(UnmappedErrorException e)
+ {
+ log.debug("{}", e.toString());
+ assertNull(e.getMessage());
+ try
+ {
+ Type type = e.getType();
+ log.error("unknown type: {}", type);
+ fail("unmapped type was resolved by enum: " + type);
+ }
+ catch (IllegalArgumentException ee) {}
+ assertEquals(new Integer(999999999), e.getCode());
+ assertNull(e.getSubCode());
+ assertNull(e.getUserTitle());
+ assertNull(e.getUserMessage());
+ assertNull(e.getTraceId());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": \"An unmapped Graph-API-Exception.\",\n" +
+ " \"type\": null,\n" +
+ " \"code\": 999999999\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(UnmappedErrorException e)
+ {
+ log.debug("{}", e.toString());
+ assertEquals("An unmapped Graph-API-Exception.", e.getMessage());
+ assertNull(e.getType());
+ assertEquals(new Integer(999999999), e.getCode());
+ assertNull(e.getSubCode());
+ assertNull(e.getUserTitle());
+ assertNull(e.getUserMessage());
+ assertNull(e.getTraceId());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": \"An unmapped Graph-API-Exception.\",\n" +
+ " \"code\": 999999999\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(UnmappedErrorException e)
+ {
+ log.debug("{}", e.toString());
+ assertEquals("An unmapped Graph-API-Exception.", e.getMessage());
+ assertNull(e.getType());
+ assertEquals(new Integer(999999999), e.getCode());
+ assertNull(e.getSubCode());
+ assertNull(e.getUserTitle());
+ assertNull(e.getUserMessage());
+ assertNull(e.getTraceId());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testInvlalidErrors()
+ {
+ log.info("testInvalidErrors");
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": \"Not a Graph-Api-Exception.\",\n" +
+ " \"type\": \"Whatever\",\n" +
+ " \"code\": \"some string\"\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": \"Not a Graph-Api-Exception.\",\n" +
+ " \"type\": \"Whatever\",\n" +
+ " \"code\": 9.9\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": \"Not a Graph-Api-Exception.\",\n" +
+ " \"type\": \"Whatever\",\n" +
+ " \"code\": null\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody(
+ "{\n" +
+ " \"error\":\n" +
+ " {\n" +
+ " \"message\": \"Not a Graph-Api-Exception.\",\n" +
+ " \"type\": \"Whatever\"\n" +
+ " }\n" +
+ "}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody("{\"error\":{\"message\":null}}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody("{\"error\":{\"type\":null}}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody("{\"error\":{\"code\":null}}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody("{\"error\":{}}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody("{\"error\":\"some message\"}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody("{\"error\":null}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody("{\"some filed\":\"some message\"}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody("{}");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+
+
+ requestFactory.setBody("");
+
+ try
+ {
+ clientTemplate.getForObject("ANY", SOME.class);
+ fail("The expected exception was not thrown");
+ }
+ catch(HttpClientErrorException e)
+ {
+ log.debug("{}", e.toString());
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
+ }
+
+
+ @Before
+ public void setUp()
+ {
+ requestFactory = new MockClientHttpRequestFactory();
+ requestFactory.setStatus(HttpStatus.BAD_REQUEST);
+ requestFactory.addHeader("Content-Type", "application/json");
+ clientTemplate.setRequestFactory(requestFactory);
+
+ clientTemplate.setErrorHandler(
+ new GraphApiErrorHandler(
+ (OAuth2ErrorHandler)clientTemplate.getErrorHandler()
+ )
+ );
+
+ clientTemplate.setAccessTokenProvider(new AccessTokenProvider()
+ {
+ @Override
+ public OAuth2AccessToken obtainAccessToken(
+ OAuth2ProtectedResourceDetails details,
+ AccessTokenRequest parameters
+ )
+ throws
+ UserRedirectRequiredException,
+ UserApprovalRequiredException,
+ AccessDeniedException
+ {
+ return new OAuth2AccessToken() {
+
+ @Override
+ public Map<String, Object> getAdditionalInformation()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Set<String> getScope()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public OAuth2RefreshToken getRefreshToken()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public String getTokenType()
+ {
+ return OAUTH2_TYPE;
+ }
+
+ @Override
+ public boolean isExpired()
+ {
+ return false;
+ }
+
+ @Override
+ public Date getExpiration()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public int getExpiresIn()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public String getValue()
+ {
+ return "ANY";
+ }
+ };
+ }
+
+ @Override
+ public boolean supportsResource(OAuth2ProtectedResourceDetails resource)
+ {
+ return true;
+ }
+
+ @Override
+ public OAuth2AccessToken refreshAccessToken(
+ OAuth2ProtectedResourceDetails resource,
+ OAuth2RefreshToken refreshToken,
+ AccessTokenRequest request
+ )
+ throws
+ UserRedirectRequiredException
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean supportsRefresh(OAuth2ProtectedResourceDetails resource)
+ {
+ return false;
+ }
+ });
+ }
+
+
+ static class SOME
+ {
+ }
+}
--- /dev/null
+package de.juplo.facebook.errors;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.client.ClientHttpRequest;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.ClientHttpResponse;
+
+
+
+/**
+ *
+ * @author kai
+ */
+public class MockClientHttpRequestFactory implements ClientHttpRequestFactory
+{
+ private static final Logger log =
+ LoggerFactory.getLogger(MockClientHttpRequestFactory.class);
+
+ private HttpStatus status = HttpStatus.OK;
+ private HttpHeaders headers = new HttpHeaders();
+ private String body = "";
+
+
+ @Override
+ public ClientHttpRequest createRequest(URI uri, HttpMethod method) throws IOException
+ {
+ return new MockClientHttpRequest(uri, method);
+ }
+
+ public void setStatus(HttpStatus status)
+ {
+ this.status = status;
+ }
+
+ public void setHeaders(HttpHeaders headers)
+ {
+ this.headers = headers;
+ }
+
+ public void addHeader(String name, String value)
+ {
+ headers.add(name, value);
+ }
+
+ public void setBody(String body)
+ {
+ log.trace(body);
+ this.body = body;
+ }
+
+
+ class MockClientHttpRequest implements ClientHttpRequest
+ {
+ private final URI uri;
+ private final HttpMethod method;
+
+
+ public MockClientHttpRequest(URI uri, HttpMethod method)
+ {
+ this.uri = uri;
+ this.method = method;
+ }
+
+
+ @Override
+ public ClientHttpResponse execute() throws IOException
+ {
+ return new MockClientHttpResponse();
+ }
+
+ @Override
+ public HttpMethod getMethod()
+ {
+ return method;
+ }
+
+ @Override
+ public URI getURI()
+ {
+ return uri;
+ }
+
+ @Override
+ public HttpHeaders getHeaders()
+ {
+ return headers;
+ }
+
+ @Override
+ public OutputStream getBody() throws IOException
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+
+
+ class MockClientHttpResponse implements ClientHttpResponse
+ {
+ @Override
+ public HttpStatus getStatusCode() throws IOException
+ {
+ return status;
+ }
+
+ @Override
+ public int getRawStatusCode() throws IOException
+ {
+ return status.value();
+ }
+
+ @Override
+ public String getStatusText() throws IOException
+ {
+ return status.getReasonPhrase();
+ }
+
+ @Override
+ public void close()
+ {
+ }
+
+ @Override
+ public InputStream getBody() throws IOException
+ {
+ return new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));
+ }
+
+ @Override
+ public HttpHeaders getHeaders()
+ {
+ return headers;
+ }
+ }
+}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import static de.juplo.facebook.exceptions.GraphApiException.OBJECT_MAPPER;
-import de.juplo.facebook.exceptions.GraphApiException.Type;
-import java.io.IOException;
-import org.junit.Test;
-import static org.junit.Assert.assertEquals;
-
-
-
-/**
- * @author Kai Moritz
- */
-public class FacebookErrorMessageMappingTest
-{
- final String example =
- "{" +
- "\"error\":{" +
- "\"message\":\"Message describing the error\"," +
- "\"type\":\"OAuthException\"," +
- "\"code\":190," +
- "\"error_subcode\":460," +
- "\"error_user_title\":\"A title\"," +
- "\"error_user_msg\":\"A message\"," +
- "\"fbtrace_id\":\"EJplcsCHuLu\"" +
- "}" +
- "}";
-
-
- @Test
- public void testSerialize() throws JsonProcessingException
- {
- FacebookErrorMessage error = new FacebookErrorMessage();
- error.message = "Message describing the error";
- error.type = Type.OAuthException.name();
- error.code = 190;
- error.subCode = 460;
- error.userTitle = "A title";
- error.userMessage = "A message";
- error.traceId = "EJplcsCHuLu";
-
- assertEquals(example, OBJECT_MAPPER.writeValueAsString(error));
- }
-
- @Test
- public void testDeserialize() throws IOException
- {
- FacebookErrorMessage error =
- OBJECT_MAPPER.readValue(example, FacebookErrorMessage.class);
-
- assertEquals("Message describing the error", error.message);
- assertEquals(Type.OAuthException.name(), error.type);
- assertEquals(new Integer(190), error.code);
- assertEquals(new Integer(460), error.subCode);
- assertEquals("A title", error.userTitle);
- assertEquals("A message", error.userMessage);
- assertEquals("EJplcsCHuLu", error.traceId);
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-import de.juplo.facebook.exceptions.GraphApiException.Type;
-import java.util.Date;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.Resource;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpStatus;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.security.oauth2.client.OAuth2RestTemplate;
-import org.springframework.security.oauth2.client.http.OAuth2ErrorHandler;
-import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
-import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException;
-import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException;
-import org.springframework.security.oauth2.client.token.AccessTokenProvider;
-import org.springframework.security.oauth2.client.token.AccessTokenRequest;
-import org.springframework.security.oauth2.common.OAuth2AccessToken;
-import static org.springframework.security.oauth2.common.OAuth2AccessToken.OAUTH2_TYPE;
-import org.springframework.security.oauth2.common.OAuth2RefreshToken;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.web.client.HttpClientErrorException;
-
-
-
-/**
- *
- * @author Kai Moritz
- */
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(
- locations = {
- "classpath:/spring/test-facebook-error-handler.xml"
- })
-public class GraphApiErrorHandlerTest
-{
- private static final Logger log =
- LoggerFactory.getLogger(GraphApiErrorHandlerTest.class);
-
- @Resource
- private OAuth2RestTemplate clientTemplate;
-
- private MockClientHttpRequestFactory requestFactory;
-
-
- @Test
- public void testError1()
- {
- log.info("testError1");
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": \"An unknown error has occurred.\",\n" +
- " \"type\": \"OAuthException\",\n" +
- " \"code\": 1\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(UnknownErrorException e)
- {
- log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertEquals(new Integer(1), e.getCode());
- assertEquals("An unknown error has occurred.", e.getMessage());
- assertEquals(Type.OAuthException, e.getType());
- }
- }
-
- @Test
- public void testError2()
- {
- log.info("testError2");
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": \"An unexpected error has occurred. Please retry your request later.\",\n" +
- " \"type\": \"OAuthException\",\n" +
- " \"code\": 2\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(UnexpectedErrorException e)
- {
- log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertEquals(new Integer(2), e.getCode());
- assertEquals("An unexpected error has occurred. Please retry your request later.", e.getMessage());
- assertEquals(Type.OAuthException, e.getType());
- }
- }
-
- @Test
- public void testError21()
- {
- log.info("testError21");
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": \"(#21) Page ID 590408587650316 was migrated to page ID 1421620791415603. Please update your API calls to the new ID\",\n" +
- " \"type\": \"OAuthException\",\n" +
- " \"code\": 21\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(PageMigratedException e)
- {
- log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertEquals(new Integer(21), e.getCode());
- assertEquals("(#21) Page ID 590408587650316 was migrated to page ID 1421620791415603. Please update your API calls to the new ID", e.getMessage());
- assertEquals(Type.OAuthException, e.getType());
- }
- }
-
- @Test
- public void testError100()
- {
- log.info("testError100");
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": \"Unsupported get request.\",\n" +
- " \"type\": \"GraphMethodException\",\n" +
- " \"code\": 100\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(UnsupportedGetRequestException e)
- {
- log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertEquals(new Integer(100), e.getCode());
- assertEquals("Unsupported get request.", e.getMessage());
- assertEquals(Type.GraphMethodException, e.getType());
- }
- }
-
- @Test
- public void testError104()
- {
- log.info("testError104");
-
- requestFactory.setBody("{\"error\":{\"message\":\"An access token is required to request this resource.\",\"type\":\"OAuthException\",\"code\":104,\"fbtrace_id\":\"E2Jjkj5++LL\"}}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(AccessTokenRequiredException e)
- {
- log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertEquals(new Integer(104), e.getCode());
- assertEquals("An access token is required to request this resource.", e.getMessage());
- assertEquals(Type.OAuthException, e.getType());
- assertEquals("E2Jjkj5++LL", e.getTraceId());
- }
- }
-
- @Test
- public void testError613()
- {
- log.info("testError613");
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": \"(#613) Calls to stream have exceeded the rate of 600 calls per 600 seconds.\",\n" +
- " \"type\": \"OAuthException\",\n" +
- " \"code\": 613\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(RateExceededException e)
- {
- log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertEquals(new Integer(613), e.getCode());
- assertEquals("(#613) Calls to stream have exceeded the rate of 600 calls per 600 seconds.", e.getMessage());
- assertEquals(Type.OAuthException, e.getType());
- }
- }
-
- @Test
- public void testError2200()
- {
- requestFactory.setBody("{\"error\":{\"message\":\"(#2200) callback verification failed: \",\"type\":\"OAuthException\",\"code\":2200,\"fbtrace_id\":\"ESLjoZKvPXg\"}}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(CallbackVerificationFailedException e)
- {
- log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertEquals(new Integer(2200), e.getCode());
- assertEquals("(#2200) callback verification failed: ", e.getMessage());
- assertEquals(Type.OAuthException, e.getType());
- assertEquals("ESLjoZKvPXg", e.getTraceId());
- }
- }
-
- @Test
- public void testUnmappedError()
- {
- log.info("testUnmappedError");
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": \"This error does not exist.\",\n" +
- " \"type\": \"NonexistentTypeException\",\n" +
- " \"code\": 999999999\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(GraphApiException e)
- {
- log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertEquals(new Integer(999999999), e.getCode());
- assertEquals("This error does not exist.", e.getMessage());
- try
- {
- Type type = e.getType();
- log.error("unknown type: {}", type);
- fail("unmapped type was resolved by enum: " + type);
- }
- catch (IllegalArgumentException ee) {}
- }
- }
-
- @Test
- public void testUnmappedErrors()
- {
- log.info("testUnmappedErrors");
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": null,\n" +
- " \"type\": \"WhateverTypeException\",\n" +
- " \"code\": 999999999\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(UnmappedErrorException e)
- {
- log.debug("{}", e.toString());
- assertNull(e.getMessage());
- try
- {
- Type type = e.getType();
- log.error("unknown type: {}", type);
- fail("unmapped type was resolved by enum: " + type);
- }
- catch (IllegalArgumentException ee) {}
- assertEquals(new Integer(999999999), e.getCode());
- assertNull(e.getSubCode());
- assertNull(e.getUserTitle());
- assertNull(e.getUserMessage());
- assertNull(e.getTraceId());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"type\": \"WhateverTypeException\",\n" +
- " \"code\": 999999999\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(UnmappedErrorException e)
- {
- log.debug("{}", e.toString());
- assertNull(e.getMessage());
- try
- {
- Type type = e.getType();
- log.error("unknown type: {}", type);
- fail("unmapped type was resolved by enum: " + type);
- }
- catch (IllegalArgumentException ee) {}
- assertEquals(new Integer(999999999), e.getCode());
- assertNull(e.getSubCode());
- assertNull(e.getUserTitle());
- assertNull(e.getUserMessage());
- assertNull(e.getTraceId());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": \"An unmapped Graph-API-Exception.\",\n" +
- " \"type\": null,\n" +
- " \"code\": 999999999\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(UnmappedErrorException e)
- {
- log.debug("{}", e.toString());
- assertEquals("An unmapped Graph-API-Exception.", e.getMessage());
- assertNull(e.getType());
- assertEquals(new Integer(999999999), e.getCode());
- assertNull(e.getSubCode());
- assertNull(e.getUserTitle());
- assertNull(e.getUserMessage());
- assertNull(e.getTraceId());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": \"An unmapped Graph-API-Exception.\",\n" +
- " \"code\": 999999999\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(UnmappedErrorException e)
- {
- log.debug("{}", e.toString());
- assertEquals("An unmapped Graph-API-Exception.", e.getMessage());
- assertNull(e.getType());
- assertEquals(new Integer(999999999), e.getCode());
- assertNull(e.getSubCode());
- assertNull(e.getUserTitle());
- assertNull(e.getUserMessage());
- assertNull(e.getTraceId());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
- }
-
- @Test
- public void testInvlalidErrors()
- {
- log.info("testInvalidErrors");
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": \"Not a Graph-Api-Exception.\",\n" +
- " \"type\": \"Whatever\",\n" +
- " \"code\": \"some string\"\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": \"Not a Graph-Api-Exception.\",\n" +
- " \"type\": \"Whatever\",\n" +
- " \"code\": 9.9\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": \"Not a Graph-Api-Exception.\",\n" +
- " \"type\": \"Whatever\",\n" +
- " \"code\": null\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody(
- "{\n" +
- " \"error\":\n" +
- " {\n" +
- " \"message\": \"Not a Graph-Api-Exception.\",\n" +
- " \"type\": \"Whatever\"\n" +
- " }\n" +
- "}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody("{\"error\":{\"message\":null}}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody("{\"error\":{\"type\":null}}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody("{\"error\":{\"code\":null}}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody("{\"error\":{}}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody("{\"error\":\"some message\"}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody("{\"error\":null}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody("{\"some filed\":\"some message\"}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody("{}");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
-
-
- requestFactory.setBody("");
-
- try
- {
- clientTemplate.getForObject("ANY", SOME.class);
- fail("The expected exception was not thrown");
- }
- catch(HttpClientErrorException e)
- {
- log.debug("{}", e.toString());
- }
- catch(Exception e)
- {
- fail("A wrong exception was thrown: " + e.toString());
- }
- }
-
-
- @Before
- public void setUp()
- {
- requestFactory = new MockClientHttpRequestFactory();
- requestFactory.setStatus(HttpStatus.BAD_REQUEST);
- requestFactory.addHeader("Content-Type", "application/json");
- clientTemplate.setRequestFactory(requestFactory);
-
- clientTemplate.setErrorHandler(
- new GraphApiErrorHandler(
- (OAuth2ErrorHandler)clientTemplate.getErrorHandler()
- )
- );
-
- clientTemplate.setAccessTokenProvider(new AccessTokenProvider()
- {
- @Override
- public OAuth2AccessToken obtainAccessToken(
- OAuth2ProtectedResourceDetails details,
- AccessTokenRequest parameters
- )
- throws
- UserRedirectRequiredException,
- UserApprovalRequiredException,
- AccessDeniedException
- {
- return new OAuth2AccessToken() {
-
- @Override
- public Map<String, Object> getAdditionalInformation()
- {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public Set<String> getScope()
- {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public OAuth2RefreshToken getRefreshToken()
- {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public String getTokenType()
- {
- return OAUTH2_TYPE;
- }
-
- @Override
- public boolean isExpired()
- {
- return false;
- }
-
- @Override
- public Date getExpiration()
- {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public int getExpiresIn()
- {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public String getValue()
- {
- return "ANY";
- }
- };
- }
-
- @Override
- public boolean supportsResource(OAuth2ProtectedResourceDetails resource)
- {
- return true;
- }
-
- @Override
- public OAuth2AccessToken refreshAccessToken(
- OAuth2ProtectedResourceDetails resource,
- OAuth2RefreshToken refreshToken,
- AccessTokenRequest request
- )
- throws
- UserRedirectRequiredException
- {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public boolean supportsRefresh(OAuth2ProtectedResourceDetails resource)
- {
- return false;
- }
- });
- }
-
-
- static class SOME
- {
- }
-}
+++ /dev/null
-package de.juplo.facebook.exceptions;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URI;
-import java.nio.charset.StandardCharsets;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.client.ClientHttpRequest;
-import org.springframework.http.client.ClientHttpRequestFactory;
-import org.springframework.http.client.ClientHttpResponse;
-
-
-
-/**
- *
- * @author kai
- */
-public class MockClientHttpRequestFactory implements ClientHttpRequestFactory
-{
- private static final Logger log =
- LoggerFactory.getLogger(MockClientHttpRequestFactory.class);
-
- private HttpStatus status = HttpStatus.OK;
- private HttpHeaders headers = new HttpHeaders();
- private String body = "";
-
-
- @Override
- public ClientHttpRequest createRequest(URI uri, HttpMethod method) throws IOException
- {
- return new MockClientHttpRequest(uri, method);
- }
-
- public void setStatus(HttpStatus status)
- {
- this.status = status;
- }
-
- public void setHeaders(HttpHeaders headers)
- {
- this.headers = headers;
- }
-
- public void addHeader(String name, String value)
- {
- headers.add(name, value);
- }
-
- public void setBody(String body)
- {
- log.trace(body);
- this.body = body;
- }
-
-
- class MockClientHttpRequest implements ClientHttpRequest
- {
- private final URI uri;
- private final HttpMethod method;
-
-
- public MockClientHttpRequest(URI uri, HttpMethod method)
- {
- this.uri = uri;
- this.method = method;
- }
-
-
- @Override
- public ClientHttpResponse execute() throws IOException
- {
- return new MockClientHttpResponse();
- }
-
- @Override
- public HttpMethod getMethod()
- {
- return method;
- }
-
- @Override
- public URI getURI()
- {
- return uri;
- }
-
- @Override
- public HttpHeaders getHeaders()
- {
- return headers;
- }
-
- @Override
- public OutputStream getBody() throws IOException
- {
- throw new UnsupportedOperationException("Not supported yet.");
- }
- }
-
-
- class MockClientHttpResponse implements ClientHttpResponse
- {
- @Override
- public HttpStatus getStatusCode() throws IOException
- {
- return status;
- }
-
- @Override
- public int getRawStatusCode() throws IOException
- {
- return status.value();
- }
-
- @Override
- public String getStatusText() throws IOException
- {
- return status.getReasonPhrase();
- }
-
- @Override
- public void close()
- {
- }
-
- @Override
- public InputStream getBody() throws IOException
- {
- return new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));
- }
-
- @Override
- public HttpHeaders getHeaders()
- {
- return headers;
- }
- }
-}