// Path: src/main/java/org/springframework/social/salesforce/api/SalesforceRequestException.java
// public class SalesforceRequestException extends ApiException {
// 
//     private static final long serialVersionUID = 7047374539651371668L;
// 
//     private final List<String> fields;
//     private final String code;
// 
//     public SalesforceRequestException(String message) {
//         super(SalesforceServiceProvider.ID, message);
//         this.code = null;
//         this.fields = null;
//     }
//     
//     public SalesforceRequestException(String providerId, String message) {
//         super(providerId, message);
//         this.code = null;
//         this.fields = null;
//     }
// 
//     @SuppressWarnings("unchecked")
//     public SalesforceRequestException(Map<String, Object> errorDetails) {
//         super(SalesforceServiceProvider.ID, (String)errorDetails.get("message"));
// 
//         this.code = StringUtils.defaultString((String)errorDetails.get("errorCode"), "UNKNOWN");
//         this.fields = (List<String>) errorDetails.get("fields");
//     }
//     
//     @SuppressWarnings("unchecked")
//     public SalesforceRequestException(String providerId, Map<String, Object> errorDetails) {
//         super(providerId, (String)errorDetails.get("message"));
// 
//         this.code = StringUtils.defaultString((String)errorDetails.get("errorCode"), "UNKNOWN");
//         this.fields = (List<String>) errorDetails.get("fields");
//     }
// 
//     public List<String> getFields() {
//         return fields;
//     }
// 
//     public String getCode() {
//         return code;
//     }
// 
// }
// 
// Path: src/main/java/org/springframework/social/salesforce/connect/SalesforceServiceProvider.java
// public class SalesforceServiceProvider extends AbstractOAuth2ServiceProvider<Salesforce> {
//     
//     //Provider ID
//     public final static String ID = "salesforce";
//     
//     public final static String PRODUCTION_GATEWAY_URL = "https://login.salesforce.com";
//     public final static String SANDBOX_GATEWAY_URL    = "https://test.salesforce.com";
//     
//     public final static String TOKEN_PATH      = "/services/oauth2/token";
//     public final static String AUTHORIZE_PATH  = "/services/oauth2/authorize";
// 
//     public SalesforceServiceProvider(String clientId, String clientSecret) {
//         this(clientId, clientSecret,
//                 PRODUCTION_GATEWAY_URL + AUTHORIZE_PATH,
//                 PRODUCTION_GATEWAY_URL + TOKEN_PATH);
//     }
//     
//     public SalesforceServiceProvider(String clientId, String clientSecret, boolean sandbox)
//     {
//         super(new SalesforceOAuth2Template(clientId, clientSecret, (sandbox ? SANDBOX_GATEWAY_URL : PRODUCTION_GATEWAY_URL) + AUTHORIZE_PATH, (sandbox ? SANDBOX_GATEWAY_URL : PRODUCTION_GATEWAY_URL) + TOKEN_PATH));
//     }
// 
//     public SalesforceServiceProvider(String clientId, String clientSecret, String authorizeUrl, String tokenUrl) {
//         super(new SalesforceOAuth2Template(clientId, clientSecret, authorizeUrl, tokenUrl));
//     }
// 
// 
//     public Salesforce getApi(String accessToken) {
//         SalesforceTemplate template = new SalesforceTemplate(accessToken);
// 
//         // gets the returned instance url and sets to Salesforce template as base url.
//         String instanceUrl = ((SalesforceOAuth2Template) getOAuthOperations()).getInstanceUrl();
//         if (instanceUrl != null) {
//             template.setInstanceUrl(instanceUrl);
//         }
// 
//         return template;
//     }
// 
// }


import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.social.InsufficientPermissionException;
import org.springframework.social.InternalServerErrorException;
import org.springframework.social.InvalidAuthorizationException;
import org.springframework.social.RateLimitExceededException;
import org.springframework.social.ResourceNotFoundException;
import org.springframework.social.UncategorizedApiException;
import org.springframework.social.salesforce.api.SalesforceRequestException;
import org.springframework.social.salesforce.connect.SalesforceServiceProvider;
import org.springframework.web.client.DefaultResponseErrorHandler;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * Copyright (C) 2017 https://github.com/jottley/spring-social-salesforce
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.social.salesforce.api.impl;



/**
 * @author Umut Utkan
 * @author Jared Ottley
 */
public class SalesforceErrorHandler extends DefaultResponseErrorHandler {
    Logger logger = LoggerFactory.getLogger(SalesforceErrorHandler.class);
    
    private static final String ERROR_CODE = "errorCode";
    private static final String BAD_OAUTH_TOKEN = "Bad_OAuth_Token";
    private static final String MESSAGE = "message";
    private static final String SESSION_EXPIRED_INVALID = "Invalid access token";

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        Map<String, Object> errorDetails = extractErrorDetailsFromResponse(response);
        if (errorDetails == null) {
            handleUncategorizedError(response, errorDetails);
        }

        handleSalesforceError(response.getStatusCode(), errorDetails);

        // if not otherwise handled, do default handling and wrap with UncategorizedApiException
        handleUncategorizedError(response, errorDetails);
    }

    private void handleSalesforceError(HttpStatus statusCode, Map<String, Object> errorDetails) {
        if (statusCode.equals(HttpStatus.NOT_FOUND)) {
// Path: src/main/java/org/springframework/social/salesforce/api/SalesforceRequestException.java
// public class SalesforceRequestException extends ApiException {
// 
//     private static final long serialVersionUID = 7047374539651371668L;
// 
//     private final List<String> fields;
//     private final String code;
// 
//     public SalesforceRequestException(String message) {
//         super(SalesforceServiceProvider.ID, message);
//         this.code = null;
//         this.fields = null;
//     }
//     
//     public SalesforceRequestException(String providerId, String message) {
//         super(providerId, message);
//         this.code = null;
//         this.fields = null;
//     }
// 
//     @SuppressWarnings("unchecked")
//     public SalesforceRequestException(Map<String, Object> errorDetails) {
//         super(SalesforceServiceProvider.ID, (String)errorDetails.get("message"));
// 
//         this.code = StringUtils.defaultString((String)errorDetails.get("errorCode"), "UNKNOWN");
//         this.fields = (List<String>) errorDetails.get("fields");
//     }
//     
//     @SuppressWarnings("unchecked")
//     public SalesforceRequestException(String providerId, Map<String, Object> errorDetails) {
//         super(providerId, (String)errorDetails.get("message"));
// 
//         this.code = StringUtils.defaultString((String)errorDetails.get("errorCode"), "UNKNOWN");
//         this.fields = (List<String>) errorDetails.get("fields");
//     }
// 
//     public List<String> getFields() {
//         return fields;
//     }
// 
//     public String getCode() {
//         return code;
//     }
// 
// }
// 
// Path: src/main/java/org/springframework/social/salesforce/connect/SalesforceServiceProvider.java
// public class SalesforceServiceProvider extends AbstractOAuth2ServiceProvider<Salesforce> {
//     
//     //Provider ID
//     public final static String ID = "salesforce";
//     
//     public final static String PRODUCTION_GATEWAY_URL = "https://login.salesforce.com";
//     public final static String SANDBOX_GATEWAY_URL    = "https://test.salesforce.com";
//     
//     public final static String TOKEN_PATH      = "/services/oauth2/token";
//     public final static String AUTHORIZE_PATH  = "/services/oauth2/authorize";
// 
//     public SalesforceServiceProvider(String clientId, String clientSecret) {
//         this(clientId, clientSecret,
//                 PRODUCTION_GATEWAY_URL + AUTHORIZE_PATH,
//                 PRODUCTION_GATEWAY_URL + TOKEN_PATH);
//     }
//     
//     public SalesforceServiceProvider(String clientId, String clientSecret, boolean sandbox)
//     {
//         super(new SalesforceOAuth2Template(clientId, clientSecret, (sandbox ? SANDBOX_GATEWAY_URL : PRODUCTION_GATEWAY_URL) + AUTHORIZE_PATH, (sandbox ? SANDBOX_GATEWAY_URL : PRODUCTION_GATEWAY_URL) + TOKEN_PATH));
//     }
// 
//     public SalesforceServiceProvider(String clientId, String clientSecret, String authorizeUrl, String tokenUrl) {
//         super(new SalesforceOAuth2Template(clientId, clientSecret, authorizeUrl, tokenUrl));
//     }
// 
// 
//     public Salesforce getApi(String accessToken) {
//         SalesforceTemplate template = new SalesforceTemplate(accessToken);
// 
//         // gets the returned instance url and sets to Salesforce template as base url.
//         String instanceUrl = ((SalesforceOAuth2Template) getOAuthOperations()).getInstanceUrl();
//         if (instanceUrl != null) {
//             template.setInstanceUrl(instanceUrl);
//         }
// 
//         return template;
//     }
// 
// }


// Path: src/main/java/org/springframework/social/salesforce/api/impl/SalesforceErrorHandler.java
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.social.InsufficientPermissionException;
import org.springframework.social.InternalServerErrorException;
import org.springframework.social.InvalidAuthorizationException;
import org.springframework.social.RateLimitExceededException;
import org.springframework.social.ResourceNotFoundException;
import org.springframework.social.UncategorizedApiException;
import org.springframework.social.salesforce.api.SalesforceRequestException;
import org.springframework.social.salesforce.connect.SalesforceServiceProvider;
import org.springframework.web.client.DefaultResponseErrorHandler;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Copyright (C) 2017 https://github.com/jottley/spring-social-salesforce
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.social.salesforce.api.impl;



/**
 * @author Umut Utkan
 * @author Jared Ottley
 */
public class SalesforceErrorHandler extends DefaultResponseErrorHandler {
    Logger logger = LoggerFactory.getLogger(SalesforceErrorHandler.class);
    
    private static final String ERROR_CODE = "errorCode";
    private static final String BAD_OAUTH_TOKEN = "Bad_OAuth_Token";
    private static final String MESSAGE = "message";
    private static final String SESSION_EXPIRED_INVALID = "Invalid access token";

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        Map<String, Object> errorDetails = extractErrorDetailsFromResponse(response);
        if (errorDetails == null) {
            handleUncategorizedError(response, errorDetails);
        }

        handleSalesforceError(response.getStatusCode(), errorDetails);

        // if not otherwise handled, do default handling and wrap with UncategorizedApiException
        handleUncategorizedError(response, errorDetails);
    }

    private void handleSalesforceError(HttpStatus statusCode, Map<String, Object> errorDetails) {
        if (statusCode.equals(HttpStatus.NOT_FOUND)) {
            throw new ResourceNotFoundException(SalesforceServiceProvider.ID, extractErrorMessage(errorDetails));